From 7207a1cc047edf35e7e9b202bf36c3fdd4aebd5c Mon Sep 17 00:00:00 2001 From: Roel Adriaans Date: Sat, 21 Jul 2018 21:40:27 +0200 Subject: [PATCH] [ADD] Module add to make the #START# and #END# date on the time markers configurable. --- contract_time_markers/README.rst | 21 +++++ contract_time_markers/__init__.py | 1 + contract_time_markers/__manifest__.py | 18 ++++ contract_time_markers/models/__init__.py | 3 + .../models/account_analytic_account.py | 49 +++++++++++ contract_time_markers/readme/CONTRIBUTORS.rst | 1 + contract_time_markers/readme/DESCRIPTION.rst | 1 + contract_time_markers/readme/USAGE.rst | 18 ++++ contract_time_markers/tests/__init__.py | 4 + contract_time_markers/tests/test_contract.py | 87 +++++++++++++++++++ .../views/account_analytic_account_view.xml | 27 ++++++ 11 files changed, 230 insertions(+) create mode 100644 contract_time_markers/README.rst create mode 100644 contract_time_markers/__init__.py create mode 100644 contract_time_markers/__manifest__.py create mode 100644 contract_time_markers/models/__init__.py create mode 100644 contract_time_markers/models/account_analytic_account.py create mode 100644 contract_time_markers/readme/CONTRIBUTORS.rst create mode 100644 contract_time_markers/readme/DESCRIPTION.rst create mode 100644 contract_time_markers/readme/USAGE.rst create mode 100644 contract_time_markers/tests/__init__.py create mode 100644 contract_time_markers/tests/test_contract.py create mode 100644 contract_time_markers/views/account_analytic_account_view.xml diff --git a/contract_time_markers/README.rst b/contract_time_markers/README.rst new file mode 100644 index 00000000..21cd7854 --- /dev/null +++ b/contract_time_markers/README.rst @@ -0,0 +1,21 @@ +**This file is going to be generated by oca-gen-addon-readme.** + +*Manual changes will be overwritten.* + +Please provide content in the ``readme`` directory: + +* **DESCRIPTION.rst** (required) +* INSTALL.rst (optional) +* CONFIGURE.rst (optional) +* **USAGE.rst** (optional, highly recommended) +* DEVELOP.rst (optional) +* ROADMAP.rst (optional) +* HISTORY.rst (optional, recommended) +* **CONTRIBUTORS.rst** (optional, highly recommended) +* CREDITS.rst (optional) + +Content of this README will also be drawn from the addon manifest, +from keys such as name, authors, maintainers, development_status, +and license. + +A good, one sentence summary in the manifest is also highly recommended. diff --git a/contract_time_markers/__init__.py b/contract_time_markers/__init__.py new file mode 100644 index 00000000..0650744f --- /dev/null +++ b/contract_time_markers/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/contract_time_markers/__manifest__.py b/contract_time_markers/__manifest__.py new file mode 100644 index 00000000..ab876d9d --- /dev/null +++ b/contract_time_markers/__manifest__.py @@ -0,0 +1,18 @@ +# Copyright 2018 Road-Support - Roel Adriaans +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +{ + 'name': 'Contracts Management - Configure time markers', + 'version': '11.0.1.0.0', + 'category': 'Contract Management', + 'license': 'AGPL-3', + 'author': "Road-Support, " + "Odoo Community Association (OCA)", + 'website': 'https://github.com/oca/contract', + 'depends': ['contract'], + 'data': [ + 'views/account_analytic_account_view.xml', + ], + 'development_status': 'alpha', + 'installable': True, +} diff --git a/contract_time_markers/models/__init__.py b/contract_time_markers/models/__init__.py new file mode 100644 index 00000000..7db322b8 --- /dev/null +++ b/contract_time_markers/models/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import account_analytic_account diff --git a/contract_time_markers/models/account_analytic_account.py b/contract_time_markers/models/account_analytic_account.py new file mode 100644 index 00000000..0e3c16e0 --- /dev/null +++ b/contract_time_markers/models/account_analytic_account.py @@ -0,0 +1,49 @@ +# Copyright 2018 Road-Support - Roel Adriaans + +import re + +from odoo import api, fields, models +from odoo.tools.misc import format_date + + +class AccountAnalyticAccount(models.Model): + _inherit = 'account.analytic.account' + + def _format_date(self, date, partner_lang, parse): + try: + res = format_date(self.env, date, partner_lang, parse) + return res + except (AttributeError, ValueError) as e: + # At the moment we catch exceptions silent, and return + # an empty string. + # Should we raise an error, or create a new mail.activity? + return "" + + @api.model + def _insert_markers(self, line, date_format): + date_from = fields.Date.from_string(line.date_from) + date_to = fields.Date.from_string(line.date_to) + from_regex = r"#START\((.*?)\)#" + to_regex = r"#END\((.*?)\)#" + name = line.name + + from_result = re.findall(from_regex, name) + to_result = re.findall(to_regex, name) + + partner_lang = line.analytic_account_id.partner_id.lang + + if from_result and len(from_result[0]) > 1: + from_string = self._format_date(date_from, partner_lang, from_result[0]) + name = re.sub(from_regex, from_string, name) + else: + # Original behaviour + name = name.replace('#START#', date_from.strftime(date_format)) + + if to_result and len(to_result[0]) > 1: + to_string = self._format_date(date_to, partner_lang, to_result[0]) + name = re.sub(to_regex, to_string, name) + else: + # Original behaviour + name = name.replace('#END#', date_to.strftime(date_format)) + + return name diff --git a/contract_time_markers/readme/CONTRIBUTORS.rst b/contract_time_markers/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000..dd5b1e49 --- /dev/null +++ b/contract_time_markers/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Roel Adriaans diff --git a/contract_time_markers/readme/DESCRIPTION.rst b/contract_time_markers/readme/DESCRIPTION.rst new file mode 100644 index 00000000..f147a0d5 --- /dev/null +++ b/contract_time_markers/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +Make the #START# and #END# date on the time markers configurable. diff --git a/contract_time_markers/readme/USAGE.rst b/contract_time_markers/readme/USAGE.rst new file mode 100644 index 00000000..a4572698 --- /dev/null +++ b/contract_time_markers/readme/USAGE.rst @@ -0,0 +1,18 @@ +To use this module, you need to: + +#. Install the contract module +#. Use the markers #START# or #END#. +#. With this module installed + it is possible to configure the date format using the LDML + format. See http://babel.pocoo.org/en/latest/dates.html#date-fields + +Only date fields are supported. + +Examples for 1 September 2018 + +- #START(MMMM yyyy)# -- September 2018 +- #START(d MMMM yy)# -- 1 September 18 +- #END(dd MMMM yyy)# -- 01 September 2018 +- #END(EEEE dd MMMM yyy)# -- Sunday 01 September 2018 +- #START(dd/MM/yyyy) -- 30/09/2018 +- #END# -- Default behaviour - Date format on based on partner language \ No newline at end of file diff --git a/contract_time_markers/tests/__init__.py b/contract_time_markers/tests/__init__.py new file mode 100644 index 00000000..a2982fdc --- /dev/null +++ b/contract_time_markers/tests/__init__.py @@ -0,0 +1,4 @@ +# © 2016 Carlos Dauden +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import test_contract diff --git a/contract_time_markers/tests/test_contract.py b/contract_time_markers/tests/test_contract.py new file mode 100644 index 00000000..ecf375a2 --- /dev/null +++ b/contract_time_markers/tests/test_contract.py @@ -0,0 +1,87 @@ +# Copyright 2016 Tecnativa - Carlos Dauden +# Copyright 2017 Tecnativa - Pedro M. Baeza +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import fields +from odoo.exceptions import ValidationError +from odoo.tests import common + + +class TestContractBase(common.SavepointCase): + @classmethod + def setUpClass(cls): + super(TestContractBase, cls).setUpClass() + cls.partner = cls.env.ref('base.res_partner_2') + cls.product = cls.env.ref('product.product_product_2') + cls.product.taxes_id += cls.env['account.tax'].search( + [('type_tax_use', '=', 'sale')], limit=1) + cls.product.description_sale = 'Test description sale' + cls.template_vals = { + 'recurring_rule_type': 'yearly', + 'recurring_interval': 12345, + 'name': 'Test Contract Template', + } + cls.template = cls.env['account.analytic.contract'].create( + cls.template_vals, + ) + cls.contract = cls.env['account.analytic.account'].create({ + 'name': 'Test Contract', + 'partner_id': cls.partner.id, + 'pricelist_id': cls.partner.property_product_pricelist.id, + 'recurring_invoices': True, + 'date_start': '2016-02-15', + 'recurring_next_date': '2016-02-29', + }) + cls.line_vals = { + 'analytic_account_id': cls.contract.id, + 'product_id': cls.product.id, + 'name': 'Services from #START# to #END#', + 'quantity': 1, + 'uom_id': cls.product.uom_id.id, + 'price_unit': 100, + 'discount': 50, + } + cls.acct_line = cls.env['account.analytic.invoice.line'].create( + cls.line_vals, + ) + + +class TestContract(TestContractBase): + def test_contract_default_name(self): + """ Create invoice, based on default values. + Should have a valid name""" + self.contract.cron_recurring_create_invoice() + invoice_id = self.env['account.invoice'].search( + [('contract_id', '=', self.contract.id)]) + self.assertEqual(invoice_id.invoice_line_ids.name, + 'Services from 02/29/2016 to 03/28/2016') + + def test_contract_computed_name(self): + """ Create invoice, based on computed values. + Should have these computed values in invoice line.""" + self.acct_line.unlink() + self.line_vals['name'] = "Services from #START(dd/MM/yyyy)# " \ + "to #END(d MMMM yy)#" + self.acct_line = self.env['account.analytic.invoice.line'].create( + self.line_vals, + ) + self.contract.cron_recurring_create_invoice() + invoice_id = self.env['account.invoice'].search( + [('contract_id', '=', self.contract.id)]) + self.assertEqual(invoice_id.invoice_line_ids.name, + 'Services from 29/02/2016 to 28 March 16') + + def test_contract_computed_broken_name(self): + """ Broken date format. Should not give an error, but empty + test in the invoice line.""" + self.acct_line.unlink() + self.line_vals['name'] = "Services from #START(Invalid)# " \ + "to #END(EEEE dd MMMM yyy)#" + self.acct_line = self.env['account.analytic.invoice.line'].create( + self.line_vals, + ) + self.contract.cron_recurring_create_invoice() + invoice_id = self.env['account.invoice'].search( + [('contract_id', '=', self.contract.id)]) + self.assertEqual(invoice_id.invoice_line_ids.name, + 'Services from to Monday 28 March 2016') diff --git a/contract_time_markers/views/account_analytic_account_view.xml b/contract_time_markers/views/account_analytic_account_view.xml new file mode 100644 index 00000000..ebb141ca --- /dev/null +++ b/contract_time_markers/views/account_analytic_account_view.xml @@ -0,0 +1,27 @@ + + + + + Contract form + account.analytic.account + + + +

#START(FORMATTING)# and #END(FORMATTING): Format the date according to + the LDML + format. Examples: for 1 September 2018 +

+

+

    +
  • #START(MMMM yyyy)# : September 2018
  • +
  • #START(d MMMM yy)# : 1 September 18
  • +
  • #END(dd MMMM yyy)# : 01 September 2018
  • +
  • #END(EEEE dd MMMM yyy)# : Sunday 01 September 2018
  • +
  • #START(dd/MM/yyyy) : 30/09/2018
  • +
  • #END# : Default behaviour - Date format on based on partner language
  • +
+

+
+
+
+