From 867fe5abba84e5bb50c24487fdc2c0949248d24c Mon Sep 17 00:00:00 2001 From: Carlos Dauden Date: Fri, 13 Mar 2020 12:37:48 +0100 Subject: [PATCH 01/11] [ADD] sale_timesheet_order_line_sync: New module [UPD] Update sale_timesheet_order_line_sync.pot --- sale_timesheet_order_line_sync/README.rst | 86 ++++ sale_timesheet_order_line_sync/__init__.py | 3 + .../__manifest__.py | 19 + .../i18n/sale_timesheet_order_line_sync.pot | 20 + .../models/__init__.py | 3 + .../models/project_task.py | 23 + .../readme/CONTRIBUTORS.rst | 3 + .../readme/DESCRIPTION.rst | 4 + .../readme/USAGE.rst | 4 + .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 432 ++++++++++++++++++ .../tests/__init__.py | 3 + .../test_sale_timesheet_order_line_sync.py | 136 ++++++ 13 files changed, 736 insertions(+) create mode 100644 sale_timesheet_order_line_sync/README.rst create mode 100644 sale_timesheet_order_line_sync/__init__.py create mode 100644 sale_timesheet_order_line_sync/__manifest__.py create mode 100644 sale_timesheet_order_line_sync/i18n/sale_timesheet_order_line_sync.pot create mode 100644 sale_timesheet_order_line_sync/models/__init__.py create mode 100644 sale_timesheet_order_line_sync/models/project_task.py create mode 100644 sale_timesheet_order_line_sync/readme/CONTRIBUTORS.rst create mode 100644 sale_timesheet_order_line_sync/readme/DESCRIPTION.rst create mode 100644 sale_timesheet_order_line_sync/readme/USAGE.rst create mode 100644 sale_timesheet_order_line_sync/static/description/icon.png create mode 100644 sale_timesheet_order_line_sync/static/description/index.html create mode 100644 sale_timesheet_order_line_sync/tests/__init__.py create mode 100644 sale_timesheet_order_line_sync/tests/test_sale_timesheet_order_line_sync.py diff --git a/sale_timesheet_order_line_sync/README.rst b/sale_timesheet_order_line_sync/README.rst new file mode 100644 index 000000000..47a698d1a --- /dev/null +++ b/sale_timesheet_order_line_sync/README.rst @@ -0,0 +1,86 @@ +============================== +Sale Timesheet Order Line Sync +============================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! 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/12.0/sale_timesheet_order_line_sync + :alt: OCA/timesheet +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/timesheet-12-0/timesheet-12-0-sale_timesheet_order_line_sync + :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/12.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module synchronises task sale order line in *not invoiced* timesheet +lines. + +Synchronization occurs only when saving a different order line in the task. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +# Go to *Project > All Tasks* +# Open specific task for editing +# Set Order Line +# Open Sale Order to view delivered quantity + +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 `_: + + * Carlos Dauden + +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. + +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_order_line_sync/__init__.py b/sale_timesheet_order_line_sync/__init__.py new file mode 100644 index 000000000..31660d6a9 --- /dev/null +++ b/sale_timesheet_order_line_sync/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import models diff --git a/sale_timesheet_order_line_sync/__manifest__.py b/sale_timesheet_order_line_sync/__manifest__.py new file mode 100644 index 000000000..a2a6df576 --- /dev/null +++ b/sale_timesheet_order_line_sync/__manifest__.py @@ -0,0 +1,19 @@ +# Copyright 2020 Tecnativa - Carlos Dauden +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +{ + 'name': 'Sale Timesheet Order Line Sync', + 'version': '12.0.1.0.0', + 'category': 'Sales', + 'website': 'https://github.com/OCA/timesheet', + 'author': + 'Tecnativa, ' + 'Odoo Community Association (OCA)', + 'license': 'AGPL-3', + 'installable': True, + 'application': False, + 'summary': 'Propagate task order line in not invoiced timesheet lines', + 'depends': [ + 'sale_timesheet', + ], +} diff --git a/sale_timesheet_order_line_sync/i18n/sale_timesheet_order_line_sync.pot b/sale_timesheet_order_line_sync/i18n/sale_timesheet_order_line_sync.pot new file mode 100644 index 000000000..63918eebc --- /dev/null +++ b/sale_timesheet_order_line_sync/i18n/sale_timesheet_order_line_sync.pot @@ -0,0 +1,20 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_timesheet_order_line_sync +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \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_order_line_sync +#: model:ir.model,name:sale_timesheet_order_line_sync.model_project_task +msgid "Task" +msgstr "" + diff --git a/sale_timesheet_order_line_sync/models/__init__.py b/sale_timesheet_order_line_sync/models/__init__.py new file mode 100644 index 000000000..efeeba8d3 --- /dev/null +++ b/sale_timesheet_order_line_sync/models/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import project_task diff --git a/sale_timesheet_order_line_sync/models/project_task.py b/sale_timesheet_order_line_sync/models/project_task.py new file mode 100644 index 000000000..9f17d8dcf --- /dev/null +++ b/sale_timesheet_order_line_sync/models/project_task.py @@ -0,0 +1,23 @@ +# Copyright 2020 Tecnativa - Carlos Dauden +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import models + + +class ProjectTask(models.Model): + _inherit = 'project.task' + + def write(self, vals): + res = super().write(vals) + sale_line_id = vals.get('sale_line_id', None) + if sale_line_id is None: + return res + # Avoid rewrite so_line if billable_type is employee_rate + self.filtered( + lambda t: t.billable_type == 'task_rate' + ).mapped('timesheet_ids').filtered(lambda l: ( + not l.timesheet_invoice_id and l.so_line.id != sale_line_id + )).write({ + 'so_line': sale_line_id, + }) + return res diff --git a/sale_timesheet_order_line_sync/readme/CONTRIBUTORS.rst b/sale_timesheet_order_line_sync/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..af740da8f --- /dev/null +++ b/sale_timesheet_order_line_sync/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* `Tecnativa `_: + + * Carlos Dauden diff --git a/sale_timesheet_order_line_sync/readme/DESCRIPTION.rst b/sale_timesheet_order_line_sync/readme/DESCRIPTION.rst new file mode 100644 index 000000000..e38db50fe --- /dev/null +++ b/sale_timesheet_order_line_sync/readme/DESCRIPTION.rst @@ -0,0 +1,4 @@ +This module synchronises task sale order line in *not invoiced* timesheet +lines. + +Synchronization occurs only when saving a different order line in the task. diff --git a/sale_timesheet_order_line_sync/readme/USAGE.rst b/sale_timesheet_order_line_sync/readme/USAGE.rst new file mode 100644 index 000000000..427a733aa --- /dev/null +++ b/sale_timesheet_order_line_sync/readme/USAGE.rst @@ -0,0 +1,4 @@ +# Go to *Project > All Tasks* +# Open specific task for editing +# Set Order Line +# Open Sale Order to view delivered quantity diff --git a/sale_timesheet_order_line_sync/static/description/icon.png b/sale_timesheet_order_line_sync/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_order_line_sync/static/description/index.html b/sale_timesheet_order_line_sync/static/description/index.html new file mode 100644 index 000000000..c198b35f0 --- /dev/null +++ b/sale_timesheet_order_line_sync/static/description/index.html @@ -0,0 +1,432 @@ + + + + + + +Sale Timesheet Order Line Sync + + + +
+

Sale Timesheet Order Line Sync

+ + +

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

+

This module synchronises task sale order line in not invoiced timesheet +lines.

+

Synchronization occurs only when saving a different order line in the task.

+

Table of contents

+ +
+

Usage

+

# Go to Project > All Tasks +# Open specific task for editing +# Set Order Line +# Open Sale Order to view delivered quantity

+
+
+

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

+ +
+
+

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.

+

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_order_line_sync/tests/__init__.py b/sale_timesheet_order_line_sync/tests/__init__.py new file mode 100644 index 000000000..f2c1a9cf2 --- /dev/null +++ b/sale_timesheet_order_line_sync/tests/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html). + +from . import test_sale_timesheet_order_line_sync diff --git a/sale_timesheet_order_line_sync/tests/test_sale_timesheet_order_line_sync.py b/sale_timesheet_order_line_sync/tests/test_sale_timesheet_order_line_sync.py new file mode 100644 index 000000000..87b299622 --- /dev/null +++ b/sale_timesheet_order_line_sync/tests/test_sale_timesheet_order_line_sync.py @@ -0,0 +1,136 @@ +# Copyright 2020 Tecnativa - Carlos Dauden +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo.tests import common + + +class TestSaleTimesheetOrderLineSync(common.TransactionCase): + + def setUp(self): + super().setUp() + + self.uom_hour = self.env.ref('uom.product_uom_hour') + self.user_type_payable = self.env.ref( + 'account.data_account_type_payable' + ) + self.user_type_receivable = self.env.ref( + 'account.data_account_type_receivable' + ) + self.user_type_revenue = self.env.ref( + 'account.data_account_type_revenue' + ) + self.Partner = self.env['res.partner'] + self.SudoPartner = self.Partner.sudo() + self.Employee = self.env['hr.employee'] + self.SudoEmployee = self.Employee.sudo() + self.AccountAccount = self.env['account.account'] + self.SudoAccountAccount = self.AccountAccount.sudo() + self.Project = self.env['project.project'] + self.SudoProject = self.Project.sudo() + self.ProjectTask = self.env['project.task'] + self.SudoProjectTask = self.ProjectTask.sudo() + self.AccountAnalyticLine = self.env['account.analytic.line'] + self.SudoAccountAnalyticLine = self.AccountAnalyticLine.sudo() + self.ProductProduct = self.env['product.product'] + self.SudoProductProduct = self.ProductProduct.sudo() + self.SaleOrder = self.env['sale.order'] + self.SudoSaleOrder = self.SaleOrder.sudo() + self.SaleOrderLine = self.env['sale.order.line'] + self.SudoSaleOrderLine = self.SaleOrderLine.sudo() + self.ProjectCreateSaleOrder = self.env['project.create.sale.order'] + + def test_sale_timesheet_order_line_sync(self): + account = self.SudoAccountAccount.create({ + 'code': 'TEST-1', + 'name': 'Sales #1', + 'reconcile': True, + 'user_type_id': self.user_type_revenue.id, + }) + project = self.SudoProject.create({ + 'name': 'Project #1', + 'allow_timesheets': True, + }) + product = self.SudoProductProduct.create({ + 'name': 'Service #1', + 'standard_price': 30, + 'list_price': 90, + 'type': 'service', + 'invoice_policy': 'delivery', + 'uom_id': self.uom_hour.id, + 'uom_po_id': self.uom_hour.id, + 'default_code': 'CODE-1', + 'service_type': 'timesheet', + 'service_tracking': 'task_global_project', + 'project_id': project.id, + 'taxes_id': False, + 'property_account_income_id': account.id, + }) + employee = self.SudoEmployee.create({ + 'name': 'Employee #1', + 'timesheet_cost': 42, + }) + account_payable = self.SudoAccountAccount.create({ + 'code': 'AP1', + 'name': 'Payable #1', + 'user_type_id': self.user_type_payable.id, + 'reconcile': True, + }) + account_receivable = self.SudoAccountAccount.create({ + 'code': 'AR1', + 'name': 'Receivable #1', + 'user_type_id': self.user_type_receivable.id, + 'reconcile': True + }) + partner = self.SudoPartner.create({ + 'name': 'Partner #1', + 'email': 'partner1@localhost', + 'customer': True, + 'property_account_payable_id': account_payable.id, + 'property_account_receivable_id': account_receivable.id, + }) + sale_order = self.SudoSaleOrder.create({ + 'partner_id': partner.id, + 'partner_invoice_id': partner.id, + 'partner_shipping_id': partner.id, + }) + sale_order_line = self.SudoSaleOrderLine.create({ + 'order_id': sale_order.id, + 'name': product.name, + 'product_id': product.id, + 'product_uom_qty': 0, + 'product_uom': self.uom_hour.id, + 'price_unit': product.list_price + }) + sale_order.action_confirm() + task = self.SudoProjectTask.search([ + ('sale_line_id', '=', sale_order_line.id) + ]) + timesheet = self.SudoAccountAnalyticLine.create({ + 'project_id': task.project_id.id, + 'task_id': task.id, + 'name': 'Entry #1', + 'unit_amount': 1, + 'employee_id': employee.id, + }) + self.assertEqual(timesheet.so_line, sale_order_line) + self.assertEqual(task.billable_type, 'task_rate') + self.assertAlmostEqual(sale_order_line.qty_delivered, 1.0, 2) + + sale_order2 = self.SudoSaleOrder.create({ + 'partner_id': partner.id, + 'partner_invoice_id': partner.id, + 'partner_shipping_id': partner.id, + }) + sale_order_line2 = self.SudoSaleOrderLine.create({ + 'order_id': sale_order.id, + 'name': product.name, + 'product_id': product.id, + 'product_uom_qty': 0, + 'product_uom': self.uom_hour.id, + 'price_unit': product.list_price + }) + sale_order2.action_confirm() + task.sale_line_id = sale_order_line2 + self.assertEqual(timesheet.so_line, sale_order_line2) + self.assertAlmostEqual(sale_order_line2.qty_delivered, 1.0, 2) + self.assertAlmostEqual(sale_order_line.qty_delivered, 0.0, 2) From 3a3ac77fa7e913dcaea3c9ecd96e73babcebdd53 Mon Sep 17 00:00:00 2001 From: Josep M Date: Mon, 18 May 2020 17:53:25 +0000 Subject: [PATCH 02/11] Added translation using Weblate (Spanish) --- sale_timesheet_order_line_sync/i18n/es.po | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 sale_timesheet_order_line_sync/i18n/es.po diff --git a/sale_timesheet_order_line_sync/i18n/es.po b/sale_timesheet_order_line_sync/i18n/es.po new file mode 100644 index 000000000..f877e8d99 --- /dev/null +++ b/sale_timesheet_order_line_sync/i18n/es.po @@ -0,0 +1,20 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * sale_timesheet_order_line_sync +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#. module: sale_timesheet_order_line_sync +#: model:ir.model,name:sale_timesheet_order_line_sync.model_project_task +msgid "Task" +msgstr "" From 659b773f15351ad4aa1fa9fc9291bc52328b8107 Mon Sep 17 00:00:00 2001 From: Josep M Date: Mon, 18 May 2020 17:53:33 +0000 Subject: [PATCH 03/11] Translated using Weblate (Spanish) Currently translated at 100.0% (1 of 1 strings) Translation: timesheet-12.0/timesheet-12.0-sale_timesheet_order_line_sync Translate-URL: https://translation.odoo-community.org/projects/timesheet-12-0/timesheet-12-0-sale_timesheet_order_line_sync/es/ --- sale_timesheet_order_line_sync/i18n/es.po | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sale_timesheet_order_line_sync/i18n/es.po b/sale_timesheet_order_line_sync/i18n/es.po index f877e8d99..5e228abee 100644 --- a/sale_timesheet_order_line_sync/i18n/es.po +++ b/sale_timesheet_order_line_sync/i18n/es.po @@ -6,15 +6,17 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 12.0\n" "Report-Msgid-Bugs-To: \n" -"Last-Translator: Automatically generated\n" +"PO-Revision-Date: 2020-05-18 20:19+0000\n" +"Last-Translator: Josep M \n" "Language-Team: none\n" "Language: es\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 3.10\n" #. module: sale_timesheet_order_line_sync #: model:ir.model,name:sale_timesheet_order_line_sync.model_project_task msgid "Task" -msgstr "" +msgstr "Tarea" From b48ec0d98efce26cd0beb00d69af4df2a9d89d4e Mon Sep 17 00:00:00 2001 From: Carlos Dauden Date: Thu, 21 May 2020 00:43:07 +0200 Subject: [PATCH 04/11] [IMP] sale_timesheet_order_line_sync: Add sudo to avoid access error with timesheet user group sale_timesheet_order_line_sync 12.0.1.0.1 --- sale_timesheet_order_line_sync/__manifest__.py | 2 +- sale_timesheet_order_line_sync/models/project_task.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sale_timesheet_order_line_sync/__manifest__.py b/sale_timesheet_order_line_sync/__manifest__.py index a2a6df576..091d24239 100644 --- a/sale_timesheet_order_line_sync/__manifest__.py +++ b/sale_timesheet_order_line_sync/__manifest__.py @@ -3,7 +3,7 @@ { 'name': 'Sale Timesheet Order Line Sync', - 'version': '12.0.1.0.0', + 'version': '12.0.1.0.1', 'category': 'Sales', 'website': 'https://github.com/OCA/timesheet', 'author': diff --git a/sale_timesheet_order_line_sync/models/project_task.py b/sale_timesheet_order_line_sync/models/project_task.py index 9f17d8dcf..60a08dbcf 100644 --- a/sale_timesheet_order_line_sync/models/project_task.py +++ b/sale_timesheet_order_line_sync/models/project_task.py @@ -15,7 +15,7 @@ def write(self, vals): # Avoid rewrite so_line if billable_type is employee_rate self.filtered( lambda t: t.billable_type == 'task_rate' - ).mapped('timesheet_ids').filtered(lambda l: ( + ).sudo().mapped('timesheet_ids').filtered(lambda l: ( not l.timesheet_invoice_id and l.so_line.id != sale_line_id )).write({ 'so_line': sale_line_id, From d978a851f4bad98b2f34a802c982ac987ebf1203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Marques?= Date: Wed, 23 Sep 2020 16:02:04 +0200 Subject: [PATCH 05/11] [IMP] sale_timesheet_order_line_sync: black, isort, prettier --- .../__manifest__.py | 24 +- .../models/project_task.py | 18 +- .../test_sale_timesheet_order_line_sync.py | 221 +++++++++--------- 3 files changed, 134 insertions(+), 129 deletions(-) diff --git a/sale_timesheet_order_line_sync/__manifest__.py b/sale_timesheet_order_line_sync/__manifest__.py index 091d24239..b7e54094b 100644 --- a/sale_timesheet_order_line_sync/__manifest__.py +++ b/sale_timesheet_order_line_sync/__manifest__.py @@ -2,18 +2,14 @@ # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). { - 'name': 'Sale Timesheet Order Line Sync', - 'version': '12.0.1.0.1', - 'category': 'Sales', - 'website': 'https://github.com/OCA/timesheet', - 'author': - 'Tecnativa, ' - 'Odoo Community Association (OCA)', - 'license': 'AGPL-3', - 'installable': True, - 'application': False, - 'summary': 'Propagate task order line in not invoiced timesheet lines', - 'depends': [ - 'sale_timesheet', - ], + "name": "Sale Timesheet Order Line Sync", + "version": "12.0.1.0.1", + "category": "Sales", + "website": "https://github.com/OCA/timesheet", + "author": "Tecnativa, " "Odoo Community Association (OCA)", + "license": "AGPL-3", + "installable": True, + "application": False, + "summary": "Propagate task order line in not invoiced timesheet lines", + "depends": ["sale_timesheet",], } diff --git a/sale_timesheet_order_line_sync/models/project_task.py b/sale_timesheet_order_line_sync/models/project_task.py index 60a08dbcf..697626820 100644 --- a/sale_timesheet_order_line_sync/models/project_task.py +++ b/sale_timesheet_order_line_sync/models/project_task.py @@ -5,19 +5,19 @@ class ProjectTask(models.Model): - _inherit = 'project.task' + _inherit = "project.task" def write(self, vals): res = super().write(vals) - sale_line_id = vals.get('sale_line_id', None) + sale_line_id = vals.get("sale_line_id", None) if sale_line_id is None: return res # Avoid rewrite so_line if billable_type is employee_rate - self.filtered( - lambda t: t.billable_type == 'task_rate' - ).sudo().mapped('timesheet_ids').filtered(lambda l: ( - not l.timesheet_invoice_id and l.so_line.id != sale_line_id - )).write({ - 'so_line': sale_line_id, - }) + self.filtered(lambda t: t.billable_type == "task_rate").sudo().mapped( + "timesheet_ids" + ).filtered( + lambda l: (not l.timesheet_invoice_id and l.so_line.id != sale_line_id) + ).write( + {"so_line": sale_line_id,} + ) return res diff --git a/sale_timesheet_order_line_sync/tests/test_sale_timesheet_order_line_sync.py b/sale_timesheet_order_line_sync/tests/test_sale_timesheet_order_line_sync.py index 87b299622..631612951 100644 --- a/sale_timesheet_order_line_sync/tests/test_sale_timesheet_order_line_sync.py +++ b/sale_timesheet_order_line_sync/tests/test_sale_timesheet_order_line_sync.py @@ -5,130 +5,139 @@ class TestSaleTimesheetOrderLineSync(common.TransactionCase): - def setUp(self): super().setUp() - self.uom_hour = self.env.ref('uom.product_uom_hour') - self.user_type_payable = self.env.ref( - 'account.data_account_type_payable' - ) - self.user_type_receivable = self.env.ref( - 'account.data_account_type_receivable' - ) - self.user_type_revenue = self.env.ref( - 'account.data_account_type_revenue' - ) - self.Partner = self.env['res.partner'] + self.uom_hour = self.env.ref("uom.product_uom_hour") + self.user_type_payable = self.env.ref("account.data_account_type_payable") + self.user_type_receivable = self.env.ref("account.data_account_type_receivable") + self.user_type_revenue = self.env.ref("account.data_account_type_revenue") + self.Partner = self.env["res.partner"] self.SudoPartner = self.Partner.sudo() - self.Employee = self.env['hr.employee'] + self.Employee = self.env["hr.employee"] self.SudoEmployee = self.Employee.sudo() - self.AccountAccount = self.env['account.account'] + self.AccountAccount = self.env["account.account"] self.SudoAccountAccount = self.AccountAccount.sudo() - self.Project = self.env['project.project'] + self.Project = self.env["project.project"] self.SudoProject = self.Project.sudo() - self.ProjectTask = self.env['project.task'] + self.ProjectTask = self.env["project.task"] self.SudoProjectTask = self.ProjectTask.sudo() - self.AccountAnalyticLine = self.env['account.analytic.line'] + self.AccountAnalyticLine = self.env["account.analytic.line"] self.SudoAccountAnalyticLine = self.AccountAnalyticLine.sudo() - self.ProductProduct = self.env['product.product'] + self.ProductProduct = self.env["product.product"] self.SudoProductProduct = self.ProductProduct.sudo() - self.SaleOrder = self.env['sale.order'] + self.SaleOrder = self.env["sale.order"] self.SudoSaleOrder = self.SaleOrder.sudo() - self.SaleOrderLine = self.env['sale.order.line'] + self.SaleOrderLine = self.env["sale.order.line"] self.SudoSaleOrderLine = self.SaleOrderLine.sudo() - self.ProjectCreateSaleOrder = self.env['project.create.sale.order'] + self.ProjectCreateSaleOrder = self.env["project.create.sale.order"] def test_sale_timesheet_order_line_sync(self): - account = self.SudoAccountAccount.create({ - 'code': 'TEST-1', - 'name': 'Sales #1', - 'reconcile': True, - 'user_type_id': self.user_type_revenue.id, - }) - project = self.SudoProject.create({ - 'name': 'Project #1', - 'allow_timesheets': True, - }) - product = self.SudoProductProduct.create({ - 'name': 'Service #1', - 'standard_price': 30, - 'list_price': 90, - 'type': 'service', - 'invoice_policy': 'delivery', - 'uom_id': self.uom_hour.id, - 'uom_po_id': self.uom_hour.id, - 'default_code': 'CODE-1', - 'service_type': 'timesheet', - 'service_tracking': 'task_global_project', - 'project_id': project.id, - 'taxes_id': False, - 'property_account_income_id': account.id, - }) - employee = self.SudoEmployee.create({ - 'name': 'Employee #1', - 'timesheet_cost': 42, - }) - account_payable = self.SudoAccountAccount.create({ - 'code': 'AP1', - 'name': 'Payable #1', - 'user_type_id': self.user_type_payable.id, - 'reconcile': True, - }) - account_receivable = self.SudoAccountAccount.create({ - 'code': 'AR1', - 'name': 'Receivable #1', - 'user_type_id': self.user_type_receivable.id, - 'reconcile': True - }) - partner = self.SudoPartner.create({ - 'name': 'Partner #1', - 'email': 'partner1@localhost', - 'customer': True, - 'property_account_payable_id': account_payable.id, - 'property_account_receivable_id': account_receivable.id, - }) - sale_order = self.SudoSaleOrder.create({ - 'partner_id': partner.id, - 'partner_invoice_id': partner.id, - 'partner_shipping_id': partner.id, - }) - sale_order_line = self.SudoSaleOrderLine.create({ - 'order_id': sale_order.id, - 'name': product.name, - 'product_id': product.id, - 'product_uom_qty': 0, - 'product_uom': self.uom_hour.id, - 'price_unit': product.list_price - }) + account = self.SudoAccountAccount.create( + { + "code": "TEST-1", + "name": "Sales #1", + "reconcile": True, + "user_type_id": self.user_type_revenue.id, + } + ) + project = self.SudoProject.create( + {"name": "Project #1", "allow_timesheets": True,} + ) + product = self.SudoProductProduct.create( + { + "name": "Service #1", + "standard_price": 30, + "list_price": 90, + "type": "service", + "invoice_policy": "delivery", + "uom_id": self.uom_hour.id, + "uom_po_id": self.uom_hour.id, + "default_code": "CODE-1", + "service_type": "timesheet", + "service_tracking": "task_global_project", + "project_id": project.id, + "taxes_id": False, + "property_account_income_id": account.id, + } + ) + employee = self.SudoEmployee.create( + {"name": "Employee #1", "timesheet_cost": 42,} + ) + account_payable = self.SudoAccountAccount.create( + { + "code": "AP1", + "name": "Payable #1", + "user_type_id": self.user_type_payable.id, + "reconcile": True, + } + ) + account_receivable = self.SudoAccountAccount.create( + { + "code": "AR1", + "name": "Receivable #1", + "user_type_id": self.user_type_receivable.id, + "reconcile": True, + } + ) + partner = self.SudoPartner.create( + { + "name": "Partner #1", + "email": "partner1@localhost", + "customer": True, + "property_account_payable_id": account_payable.id, + "property_account_receivable_id": account_receivable.id, + } + ) + sale_order = self.SudoSaleOrder.create( + { + "partner_id": partner.id, + "partner_invoice_id": partner.id, + "partner_shipping_id": partner.id, + } + ) + sale_order_line = self.SudoSaleOrderLine.create( + { + "order_id": sale_order.id, + "name": product.name, + "product_id": product.id, + "product_uom_qty": 0, + "product_uom": self.uom_hour.id, + "price_unit": product.list_price, + } + ) sale_order.action_confirm() - task = self.SudoProjectTask.search([ - ('sale_line_id', '=', sale_order_line.id) - ]) - timesheet = self.SudoAccountAnalyticLine.create({ - 'project_id': task.project_id.id, - 'task_id': task.id, - 'name': 'Entry #1', - 'unit_amount': 1, - 'employee_id': employee.id, - }) + task = self.SudoProjectTask.search([("sale_line_id", "=", sale_order_line.id)]) + timesheet = self.SudoAccountAnalyticLine.create( + { + "project_id": task.project_id.id, + "task_id": task.id, + "name": "Entry #1", + "unit_amount": 1, + "employee_id": employee.id, + } + ) self.assertEqual(timesheet.so_line, sale_order_line) - self.assertEqual(task.billable_type, 'task_rate') + self.assertEqual(task.billable_type, "task_rate") self.assertAlmostEqual(sale_order_line.qty_delivered, 1.0, 2) - sale_order2 = self.SudoSaleOrder.create({ - 'partner_id': partner.id, - 'partner_invoice_id': partner.id, - 'partner_shipping_id': partner.id, - }) - sale_order_line2 = self.SudoSaleOrderLine.create({ - 'order_id': sale_order.id, - 'name': product.name, - 'product_id': product.id, - 'product_uom_qty': 0, - 'product_uom': self.uom_hour.id, - 'price_unit': product.list_price - }) + sale_order2 = self.SudoSaleOrder.create( + { + "partner_id": partner.id, + "partner_invoice_id": partner.id, + "partner_shipping_id": partner.id, + } + ) + sale_order_line2 = self.SudoSaleOrderLine.create( + { + "order_id": sale_order.id, + "name": product.name, + "product_id": product.id, + "product_uom_qty": 0, + "product_uom": self.uom_hour.id, + "price_unit": product.list_price, + } + ) sale_order2.action_confirm() task.sale_line_id = sale_order_line2 self.assertEqual(timesheet.so_line, sale_order_line2) From 99e31779f1aef5bf928a211f6b5b82c298d781e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Marques?= Date: Thu, 24 Sep 2020 10:48:57 +0200 Subject: [PATCH 06/11] [MIG] sale_timesheet_order_line_sync: Migration to 13.0 [UPD] Update sale_timesheet_order_line_sync.pot --- sale_timesheet_order_line_sync/README.rst | 21 +++++++++++-------- .../__manifest__.py | 5 +++-- .../i18n/sale_timesheet_order_line_sync.pot | 7 +++---- .../models/project_task.py | 2 +- .../readme/CONTRIBUTORS.rst | 1 + .../readme/USAGE.rst | 10 +++++---- .../static/description/index.html | 19 ++++++++++------- .../test_sale_timesheet_order_line_sync.py | 6 +++--- 8 files changed, 41 insertions(+), 30 deletions(-) diff --git a/sale_timesheet_order_line_sync/README.rst b/sale_timesheet_order_line_sync/README.rst index 47a698d1a..7dde49030 100644 --- a/sale_timesheet_order_line_sync/README.rst +++ b/sale_timesheet_order_line_sync/README.rst @@ -14,13 +14,13 @@ Sale Timesheet Order Line Sync :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/12.0/sale_timesheet_order_line_sync + :target: https://github.com/OCA/timesheet/tree/13.0/sale_timesheet_order_line_sync :alt: OCA/timesheet .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/timesheet-12-0/timesheet-12-0-sale_timesheet_order_line_sync + :target: https://translation.odoo-community.org/projects/timesheet-13-0/timesheet-13-0-sale_timesheet_order_line_sync :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/12.0 + :target: https://runbot.odoo-community.org/runbot/117/13.0 :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| @@ -38,10 +38,12 @@ Synchronization occurs only when saving a different order line in the task. Usage ===== -# Go to *Project > All Tasks* -# Open specific task for editing -# Set Order Line -# Open Sale Order to view delivered quantity +#. Go to **Project > All Tasks** +#. Open specific task for editing +#. In *Extra Info*, select a customer. +#. Set a Sales Order Item where the invoiced product's *Service Invoicing Policy* is *Timesheets on tasks* +#. Add *Timesheets* to the task if there aren't any. +#. Open Sale Order to view delivered quantity Bug Tracker =========== @@ -49,7 +51,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 smashing it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -67,6 +69,7 @@ Contributors * `Tecnativa `_: * Carlos Dauden + * João Marques Maintainers ~~~~~~~~~~~ @@ -81,6 +84,6 @@ 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. -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_order_line_sync/__manifest__.py b/sale_timesheet_order_line_sync/__manifest__.py index b7e54094b..54323ccb1 100644 --- a/sale_timesheet_order_line_sync/__manifest__.py +++ b/sale_timesheet_order_line_sync/__manifest__.py @@ -1,9 +1,10 @@ # Copyright 2020 Tecnativa - Carlos Dauden +# Copyright 2020 Tecnativa - João Marques # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). { "name": "Sale Timesheet Order Line Sync", - "version": "12.0.1.0.1", + "version": "13.0.1.0.0", "category": "Sales", "website": "https://github.com/OCA/timesheet", "author": "Tecnativa, " "Odoo Community Association (OCA)", @@ -11,5 +12,5 @@ "installable": True, "application": False, "summary": "Propagate task order line in not invoiced timesheet lines", - "depends": ["sale_timesheet",], + "depends": ["sale_timesheet"], } diff --git a/sale_timesheet_order_line_sync/i18n/sale_timesheet_order_line_sync.pot b/sale_timesheet_order_line_sync/i18n/sale_timesheet_order_line_sync.pot index 63918eebc..e3b0d91fe 100644 --- a/sale_timesheet_order_line_sync/i18n/sale_timesheet_order_line_sync.pot +++ b/sale_timesheet_order_line_sync/i18n/sale_timesheet_order_line_sync.pot @@ -1,12 +1,12 @@ # Translation of Odoo Server. # This file contains the translation of the following modules: -# * sale_timesheet_order_line_sync +# * sale_timesheet_order_line_sync # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 12.0\n" +"Project-Id-Version: Odoo Server 13.0\n" "Report-Msgid-Bugs-To: \n" -"Last-Translator: <>\n" +"Last-Translator: \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -17,4 +17,3 @@ msgstr "" #: model:ir.model,name:sale_timesheet_order_line_sync.model_project_task msgid "Task" msgstr "" - diff --git a/sale_timesheet_order_line_sync/models/project_task.py b/sale_timesheet_order_line_sync/models/project_task.py index 697626820..56fbbcf19 100644 --- a/sale_timesheet_order_line_sync/models/project_task.py +++ b/sale_timesheet_order_line_sync/models/project_task.py @@ -18,6 +18,6 @@ def write(self, vals): ).filtered( lambda l: (not l.timesheet_invoice_id and l.so_line.id != sale_line_id) ).write( - {"so_line": sale_line_id,} + {"so_line": sale_line_id} ) return res diff --git a/sale_timesheet_order_line_sync/readme/CONTRIBUTORS.rst b/sale_timesheet_order_line_sync/readme/CONTRIBUTORS.rst index af740da8f..25f38220e 100644 --- a/sale_timesheet_order_line_sync/readme/CONTRIBUTORS.rst +++ b/sale_timesheet_order_line_sync/readme/CONTRIBUTORS.rst @@ -1,3 +1,4 @@ * `Tecnativa `_: * Carlos Dauden + * João Marques diff --git a/sale_timesheet_order_line_sync/readme/USAGE.rst b/sale_timesheet_order_line_sync/readme/USAGE.rst index 427a733aa..3d7cef453 100644 --- a/sale_timesheet_order_line_sync/readme/USAGE.rst +++ b/sale_timesheet_order_line_sync/readme/USAGE.rst @@ -1,4 +1,6 @@ -# Go to *Project > All Tasks* -# Open specific task for editing -# Set Order Line -# Open Sale Order to view delivered quantity +#. Go to **Project > All Tasks** +#. Open specific task for editing +#. In *Extra Info*, select a customer. +#. Set a Sales Order Item where the invoiced product's *Service Invoicing Policy* is *Timesheets on tasks* +#. Add *Timesheets* to the task if there aren't any. +#. Open Sale Order to view delivered quantity diff --git a/sale_timesheet_order_line_sync/static/description/index.html b/sale_timesheet_order_line_sync/static/description/index.html index c198b35f0..bdfd6140b 100644 --- a/sale_timesheet_order_line_sync/static/description/index.html +++ b/sale_timesheet_order_line_sync/static/description/index.html @@ -367,7 +367,7 @@

Sale Timesheet Order Line Sync

!! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

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

+

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

This module synchronises task sale order line in not invoiced timesheet lines.

Synchronization occurs only when saving a different order line in the task.

@@ -386,17 +386,21 @@

Sale Timesheet Order Line Sync

Usage

-

# Go to Project > All Tasks -# Open specific task for editing -# Set Order Line -# Open Sale Order to view delivered quantity

+
    +
  1. Go to Project > All Tasks
  2. +
  3. Open specific task for editing
  4. +
  5. In Extra Info, select a customer.
  6. +
  7. Set a Sales Order Item where the invoiced product’s Service Invoicing Policy is Timesheets on tasks
  8. +
  9. Add Timesheets to the task if there aren’t any.
  10. +
  11. Open Sale Order to view delivered quantity
  12. +

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.

+feedback.

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

@@ -412,6 +416,7 @@

Contributors

@@ -423,7 +428,7 @@

Maintainers

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.

-

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_order_line_sync/tests/test_sale_timesheet_order_line_sync.py b/sale_timesheet_order_line_sync/tests/test_sale_timesheet_order_line_sync.py index 631612951..5b8e16bdb 100644 --- a/sale_timesheet_order_line_sync/tests/test_sale_timesheet_order_line_sync.py +++ b/sale_timesheet_order_line_sync/tests/test_sale_timesheet_order_line_sync.py @@ -1,4 +1,5 @@ # Copyright 2020 Tecnativa - Carlos Dauden +# Copyright 2020 Tecnativa - João Marques # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). from odoo.tests import common @@ -42,7 +43,7 @@ def test_sale_timesheet_order_line_sync(self): } ) project = self.SudoProject.create( - {"name": "Project #1", "allow_timesheets": True,} + {"name": "Project #1", "allow_timesheets": True} ) product = self.SudoProductProduct.create( { @@ -62,7 +63,7 @@ def test_sale_timesheet_order_line_sync(self): } ) employee = self.SudoEmployee.create( - {"name": "Employee #1", "timesheet_cost": 42,} + {"name": "Employee #1", "timesheet_cost": 42} ) account_payable = self.SudoAccountAccount.create( { @@ -84,7 +85,6 @@ def test_sale_timesheet_order_line_sync(self): { "name": "Partner #1", "email": "partner1@localhost", - "customer": True, "property_account_payable_id": account_payable.id, "property_account_receivable_id": account_receivable.id, } From 4ac28d2a18c252906363bfecfedd04c7f2603b0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Mart=C3=ADnez?= Date: Fri, 8 Oct 2021 12:09:37 +0200 Subject: [PATCH 07/11] [MIG] sale_timesheet_order_line_sync: Migration to 14.0 --- sale_timesheet_order_line_sync/README.rst | 10 +++++----- sale_timesheet_order_line_sync/__manifest__.py | 4 ++-- sale_timesheet_order_line_sync/models/project_task.py | 4 ++-- .../static/description/index.html | 8 ++++---- .../tests/test_sale_timesheet_order_line_sync.py | 4 ++-- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/sale_timesheet_order_line_sync/README.rst b/sale_timesheet_order_line_sync/README.rst index 7dde49030..9e6651d0d 100644 --- a/sale_timesheet_order_line_sync/README.rst +++ b/sale_timesheet_order_line_sync/README.rst @@ -14,13 +14,13 @@ Sale Timesheet Order Line Sync :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/13.0/sale_timesheet_order_line_sync + :target: https://github.com/OCA/timesheet/tree/14.0/sale_timesheet_order_line_sync :alt: OCA/timesheet .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/timesheet-13-0/timesheet-13-0-sale_timesheet_order_line_sync + :target: https://translation.odoo-community.org/projects/timesheet-14-0/timesheet-14-0-sale_timesheet_order_line_sync :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/13.0 + :target: https://runbot.odoo-community.org/runbot/117/14.0 :alt: Try me on Runbot |badge1| |badge2| |badge3| |badge4| |badge5| @@ -51,7 +51,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 smashing it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -84,6 +84,6 @@ 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. -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_order_line_sync/__manifest__.py b/sale_timesheet_order_line_sync/__manifest__.py index 54323ccb1..5b7294fb2 100644 --- a/sale_timesheet_order_line_sync/__manifest__.py +++ b/sale_timesheet_order_line_sync/__manifest__.py @@ -4,10 +4,10 @@ { "name": "Sale Timesheet Order Line Sync", - "version": "13.0.1.0.0", + "version": "14.0.1.0.0", "category": "Sales", "website": "https://github.com/OCA/timesheet", - "author": "Tecnativa, " "Odoo Community Association (OCA)", + "author": "Tecnativa, Odoo Community Association (OCA)", "license": "AGPL-3", "installable": True, "application": False, diff --git a/sale_timesheet_order_line_sync/models/project_task.py b/sale_timesheet_order_line_sync/models/project_task.py index 56fbbcf19..f06d227b5 100644 --- a/sale_timesheet_order_line_sync/models/project_task.py +++ b/sale_timesheet_order_line_sync/models/project_task.py @@ -12,8 +12,8 @@ def write(self, vals): sale_line_id = vals.get("sale_line_id", None) if sale_line_id is None: return res - # Avoid rewrite so_line if billable_type is employee_rate - self.filtered(lambda t: t.billable_type == "task_rate").sudo().mapped( + # Avoid rewrite so_line if pricing_type is fixed_rate + self.filtered(lambda t: t.pricing_type == "fixed_rate").sudo().mapped( "timesheet_ids" ).filtered( lambda l: (not l.timesheet_invoice_id and l.so_line.id != sale_line_id) diff --git a/sale_timesheet_order_line_sync/static/description/index.html b/sale_timesheet_order_line_sync/static/description/index.html index bdfd6140b..adb669c83 100644 --- a/sale_timesheet_order_line_sync/static/description/index.html +++ b/sale_timesheet_order_line_sync/static/description/index.html @@ -3,7 +3,7 @@ - + Sale Timesheet Order Line Sync