From 7747b38ad561c8b932d323ca83be3aa32fae7a21 Mon Sep 17 00:00:00 2001 From: Kitti U Date: Sat, 8 May 2021 22:01:59 +0700 Subject: [PATCH 1/7] [14.0][ADD] base_sequence_option --- base_sequence_option/__init__.py | 4 + base_sequence_option/__manifest__.py | 20 + base_sequence_option/models/__init__.py | 5 + base_sequence_option/models/ir_sequence.py | 22 + .../models/sequence_option.py | 101 ++++ base_sequence_option/readme/CONTRIBUTORS.rst | 1 + base_sequence_option/readme/DESCRIPTION.rst | 16 + base_sequence_option/readme/USAGE.rst | 14 + .../security/ir.model.access.csv | 5 + .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 436 ++++++++++++++++++ base_sequence_option/tests/__init__.py | 5 + .../tests/base_sequence_tester.py | 30 ++ base_sequence_option/tests/common.py | 93 ++++ .../tests/test_base_sequence_option.py | 30 ++ .../views/sequence_option_view.xml | 95 ++++ 16 files changed, 877 insertions(+) create mode 100644 base_sequence_option/__init__.py create mode 100644 base_sequence_option/__manifest__.py create mode 100644 base_sequence_option/models/__init__.py create mode 100644 base_sequence_option/models/ir_sequence.py create mode 100644 base_sequence_option/models/sequence_option.py create mode 100644 base_sequence_option/readme/CONTRIBUTORS.rst create mode 100644 base_sequence_option/readme/DESCRIPTION.rst create mode 100644 base_sequence_option/readme/USAGE.rst create mode 100644 base_sequence_option/security/ir.model.access.csv create mode 100644 base_sequence_option/static/description/icon.png create mode 100644 base_sequence_option/static/description/index.html create mode 100644 base_sequence_option/tests/__init__.py create mode 100644 base_sequence_option/tests/base_sequence_tester.py create mode 100644 base_sequence_option/tests/common.py create mode 100644 base_sequence_option/tests/test_base_sequence_option.py create mode 100644 base_sequence_option/views/sequence_option_view.xml diff --git a/base_sequence_option/__init__.py b/base_sequence_option/__init__.py new file mode 100644 index 00000000000..b7f345e3e80 --- /dev/null +++ b/base_sequence_option/__init__.py @@ -0,0 +1,4 @@ +# Copyright 2021 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from . import models diff --git a/base_sequence_option/__manifest__.py b/base_sequence_option/__manifest__.py new file mode 100644 index 00000000000..ad23285b67d --- /dev/null +++ b/base_sequence_option/__manifest__.py @@ -0,0 +1,20 @@ +# Copyright 2021 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +{ + "name": "Base Sequence Option", + "summary": "Alternative sequence options for specific models", + "version": "14.0.1.0.0", + "author": "Ecosoft, Odoo Community Association (OCA)", + "maintainers": ["kittiu"], + "development_status": "Alpha", + "website": "https://github.com/OCA/server-tools", + "category": "Tools", + "depends": ["base"], + "data": [ + "security/ir.model.access.csv", + "views/sequence_option_view.xml", + ], + "license": "LGPL-3", + "installable": True, +} diff --git a/base_sequence_option/models/__init__.py b/base_sequence_option/models/__init__.py new file mode 100644 index 00000000000..94cb0ad4022 --- /dev/null +++ b/base_sequence_option/models/__init__.py @@ -0,0 +1,5 @@ +# Copyright 2021 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from . import sequence_option +from . import ir_sequence diff --git a/base_sequence_option/models/ir_sequence.py b/base_sequence_option/models/ir_sequence.py new file mode 100644 index 00000000000..c3b54f29277 --- /dev/null +++ b/base_sequence_option/models/ir_sequence.py @@ -0,0 +1,22 @@ +# Copyright 2021 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import api, models + + +class IrSequence(models.Model): + _inherit = "ir.sequence" + + def next_by_id(self, sequence_date=None): + sequence_id = self.env.context.get("sequence_option_id", False) + if sequence_id: + self = self.browse(sequence_id) + return super().next_by_id(sequence_date=sequence_date) + + @api.model + def next_by_code(self, sequence_code, sequence_date=None): + sequence_id = self.env.context.get("sequence_option_id", False) + if sequence_id: + self = self.browse(sequence_id) + return super().next_by_id(sequence_date=sequence_date) + return super().next_by_code(sequence_code, sequence_date=sequence_date) diff --git a/base_sequence_option/models/sequence_option.py b/base_sequence_option/models/sequence_option.py new file mode 100644 index 00000000000..e2197148cc7 --- /dev/null +++ b/base_sequence_option/models/sequence_option.py @@ -0,0 +1,101 @@ +# Copyright 2021 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import _, fields, models +from odoo.exceptions import ValidationError +from odoo.tools import safe_eval + + +class BaseSequenceOption(models.Model): + _name = "base.sequence.option" + _description = "Sequence Option Base Model" + + name = fields.Char(readonly=True) + use_sequence_option = fields.Boolean( + string="Use sequence options", + help="If checked, Odoo will try to find the new matching sequence first, " + "if not found, fall back to use the original Odoo sequence.", + ) + model = fields.Selection( + selection=[], + string="Apply On Model", + required=True, + readonly=True, + ) + option_ids = fields.One2many( + string="Sequence Options", + comodel_name="sequence.option", + inverse_name="base_id", + ) + + +class SequenceOption(models.Model): + _name = "sequence.option" + _description = "Sequence Options" + + base_id = fields.Many2one( + comodel_name="base.sequence.option", + index=True, + required=True, + ondelete="cascade", + ) + name = fields.Char( + string="Description", + required=True, + ) + model = fields.Selection( + related="base_id.model", + store=True, + readonly=True, + ) + use_sequence_option = fields.Boolean( + related="base_id.use_sequence_option", + store=True, + ) + filter_domain = fields.Char( + string="Apply On", + default="[]", + help="Find matching option by document values", + ) + sequence_id = fields.Many2one( + comodel_name="ir.sequence", + string="Sequence", + required=True, + ) + prefix = fields.Char( + related="sequence_id.prefix", + string="Prefix", + readonly=True, + ) + suffix = fields.Char( + related="sequence_id.suffix", + string="Suffix", + readonly=True, + ) + implementation = fields.Selection( + related="sequence_id.implementation", + string="Implementation", + readonly=True, + ) + + def get_model_options(self, model): + return self.sudo().search( + [("use_sequence_option", "=", True), ("model", "=", model)] + ) + + def get_sequence(self, record, options=False): + """ + Find sequence option that match the record values + """ + if not options: + options = self.get_model_options(record._name) + sequence = self.env["ir.sequence"] + for option in options: + domain = safe_eval.safe_eval(option.filter_domain) + if record.sudo().filtered_domain(domain): + if sequence: # Do not allow > 1 match + raise ValidationError( + _("Multiple optional sequences found for this model!") + ) + sequence = option.sequence_id + return sequence diff --git a/base_sequence_option/readme/CONTRIBUTORS.rst b/base_sequence_option/readme/CONTRIBUTORS.rst new file mode 100644 index 00000000000..6ce956d9619 --- /dev/null +++ b/base_sequence_option/readme/CONTRIBUTORS.rst @@ -0,0 +1 @@ +* Kitti U. diff --git a/base_sequence_option/readme/DESCRIPTION.rst b/base_sequence_option/readme/DESCRIPTION.rst new file mode 100644 index 00000000000..6b2f0c6b927 --- /dev/null +++ b/base_sequence_option/readme/DESCRIPTION.rst @@ -0,0 +1,16 @@ +This module allow user to add optional sequences to some document model. +On which sequence is used, is based on domain matching with document values +(and original sequence will be bypassed). + +For example, it is now possible to, + +* Avoid using Odoo automatic sequence on invoice and vendor bill with old style sequence. +* Customer payment and vendor payment to run on different sequence. +* Assign different sales order sequence based on customer region. + +This is a base module and does nothing by itself. Following are modules +that will allow managing sequence options for each type of documents, I.e., + +* Purchase Order: purchase_sequence_option +* Invoice / Bill / Refund / Payment: account_sequence_option +* Others: create a new module with few lines of code diff --git a/base_sequence_option/readme/USAGE.rst b/base_sequence_option/readme/USAGE.rst new file mode 100644 index 00000000000..3d902ff879c --- /dev/null +++ b/base_sequence_option/readme/USAGE.rst @@ -0,0 +1,14 @@ +To use this module, you need to: + +1. Go to *Settings > Technical > Sequences & Identifier > Manage Sequence Options*. +2. Based on extended module installed, different document types will be listed, i.e., Purchase Order. +3. Activite "Use sequence options" to use, if not, fall back to normal sequence. +4. For each option, provide, + * Name: i.e., Customer Invoice for Cust A., Customer Payment, etc. + * Apply On: a filter domain to test whether a document match this option. + * Sequence: select underlining sequence to perform + +**Note:** + +* If no options matches the document, fall back to normal sequence. +* If there are multiple sequence options that match same document, error will be raised. diff --git a/base_sequence_option/security/ir.model.access.csv b/base_sequence_option/security/ir.model.access.csv new file mode 100644 index 00000000000..8ab27d5850a --- /dev/null +++ b/base_sequence_option/security/ir.model.access.csv @@ -0,0 +1,5 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_sequence_option,access_sequence_option,model_sequence_option,base.group_user,1,0,0,0 +access_sequence_option_system,access_sequence_option_system,model_sequence_option,base.group_system,1,1,1,1 +access_base_sequence_option,access_base_sequence_option,model_base_sequence_option,base.group_user,1,0,0,0 +access_base_sequence_option_system,access_base_sequence_option_system,model_base_sequence_option,base.group_system,1,1,1,1 diff --git a/base_sequence_option/static/description/icon.png b/base_sequence_option/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/base_sequence_option/static/description/index.html b/base_sequence_option/static/description/index.html new file mode 100644 index 00000000000..3922ee59fef --- /dev/null +++ b/base_sequence_option/static/description/index.html @@ -0,0 +1,436 @@ + + + + + + +Base Cron Exclusion + + + +
+

Base Cron Exclusion

+ + +

Production/Stable License: LGPL-3 OCA/server-tools Translate me on Weblate Try me on Runbot

+

This module extends the functionality of scheduled actions to allow you to +select the ones that should not run simultaneously.

+

Table of contents

+ +
+

Usage

+

To use this module, you need to:

+
    +
  1. Go to Settings > Technical > Automation > Scheduled Actions.
  2. +
  3. In the form view go to the tab Mutually Exclusive Scheduled Actions.
  4. +
  5. Fill it with the actions that should be blocked while running the action +you are editing. Note that this is mutual and the selected actions will +block the initial action when running.
  6. +
+
+
+

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

+
    +
  • ForgeFlow
  • +
+
+ +
+

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:

+

LoisRForgeFlow

+

This module is part of the OCA/server-tools project on GitHub.

+

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

+
+
+
+ + diff --git a/base_sequence_option/tests/__init__.py b/base_sequence_option/tests/__init__.py new file mode 100644 index 00000000000..62730016962 --- /dev/null +++ b/base_sequence_option/tests/__init__.py @@ -0,0 +1,5 @@ +# Copyright 2021 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from . import common +from . import test_base_sequence_option diff --git a/base_sequence_option/tests/base_sequence_tester.py b/base_sequence_option/tests/base_sequence_tester.py new file mode 100644 index 00000000000..d9f2a165c0b --- /dev/null +++ b/base_sequence_option/tests/base_sequence_tester.py @@ -0,0 +1,30 @@ +# Copyright 2021 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo import api, fields, models + + +class BaseSequenceTester(models.Model): + _name = "base.sequence.tester" + _description = "Base Sequence Tester" + + name = fields.Char(default="/") + test_type = fields.Selection(selection=[("a", "A"), ("b", "B")]) + + @api.model + def create(self, vals): + seq = self.env["sequence.option"].get_sequence(self.new(vals)) + if seq: # use sequence from sequence.option, instead of base.sequence.tester + self = self.with_context(sequence_option_id=seq.id) + new_seq = self.env["ir.sequence"].next_by_code("base.sequence.tester") + vals["name"] = new_seq + return super().create(vals) + + +class BaseSequenceOption(models.Model): + _inherit = "base.sequence.option" + + model = fields.Selection( + selection_add=[("base.sequence.tester", "base.sequence.tester")], + ondelete={"base.sequence.tester": "cascade"}, + ) diff --git a/base_sequence_option/tests/common.py b/base_sequence_option/tests/common.py new file mode 100644 index 00000000000..a19f002c19f --- /dev/null +++ b/base_sequence_option/tests/common.py @@ -0,0 +1,93 @@ +# Copyright 2021 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo_test_helper import FakeModelLoader + +from odoo.tests import common + + +class CommonBaseSequenceOption(common.SavepointCase): + @classmethod + def setUpClass(cls): + super(CommonBaseSequenceOption, cls).setUpClass() + + cls.loader = FakeModelLoader(cls.env, cls.__module__) + cls.loader.backup_registry() + from .base_sequence_tester import BaseSequenceOption, BaseSequenceTester + + cls.loader.update_registry((BaseSequenceTester, BaseSequenceOption)) + + cls.test_model = cls.env[BaseSequenceTester._name] + + cls.tester_model = cls.env["ir.model"].search( + [("model", "=", "base.sequence.tester")] + ) + + # Access record: + cls.env["ir.model.access"].create( + { + "name": "access.tester", + "model_id": cls.tester_model.id, + "perm_read": 1, + "perm_write": 1, + "perm_create": 1, + "perm_unlink": 1, + } + ) + + # Create sequence for type A and type B + cls.ir_sequence_obj = cls.env["ir.sequence"] + cls.ir_sequence_obj.create( + { + "name": "Default Sequence", + "code": "base.sequence.tester", + "padding": 5, + "prefix": "DEF/", + } + ) + seq_a = cls.ir_sequence_obj.create( + { + "name": "Type A", + "padding": 5, + "prefix": "TYPE-A/", + } + ) + seq_b = cls.ir_sequence_obj.create( + { + "name": "Type B", + "padding": 5, + "prefix": "TYPE-B/", + } + ) + + # Create sequence options for model bsae.sequence.tester: + cls.base_sequence_obj = cls.env["base.sequence.option"] + cls.base_seq = cls.base_sequence_obj.create( + { + "name": "Test Model", + "model": "base.sequence.tester", + "use_sequence_option": True, + } + ) + cls.sequence_obj = cls.env["sequence.option"] + cls.sequence_obj.create( + { + "base_id": cls.base_seq.id, + "name": "Option 1", + "filter_domain": [("test_type", "=", "a")], + "sequence_id": seq_a.id, + } + ) + cls.sequence_obj.create( + { + "base_id": cls.base_seq.id, + "name": "Option 1", + "filter_domain": [("test_type", "=", "b")], + "sequence_id": seq_b.id, + } + ) + + @classmethod + def tearDownClass(cls): + cls.loader.restore_registry() + super(CommonBaseSequenceOption, cls).tearDownClass() diff --git a/base_sequence_option/tests/test_base_sequence_option.py b/base_sequence_option/tests/test_base_sequence_option.py new file mode 100644 index 00000000000..ecbc23e61b3 --- /dev/null +++ b/base_sequence_option/tests/test_base_sequence_option.py @@ -0,0 +1,30 @@ +# Copyright 2021 Ecosoft Co., Ltd. (http://ecosoft.co.th) +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). + +from odoo.tests.common import tagged + +from .common import CommonBaseSequenceOption + + +@tagged("post_install", "-at_install") +class TestBaseSequenceTester(CommonBaseSequenceOption): + def test_sequence_options(self): + """ + Test 3 cases, + 1. Default + 2. Sequence Type A + 3. Sequence Type B + """ + # 1. Default + rec = self.test_model.create({}) + self.assertIn("DEF/", rec.name) + # 2. Type A + rec = self.test_model.create({"test_type": "a"}) + self.assertIn("TYPE-A/", rec.name) + # 3. Type B + rec = self.test_model.create({"test_type": "b"}) + self.assertIn("TYPE-B/", rec.name) + # Not useing the sequence + self.base_seq.use_sequence_option = False + rec = self.test_model.create({"test_type": "b"}) + self.assertIn("DEF/", rec.name) diff --git a/base_sequence_option/views/sequence_option_view.xml b/base_sequence_option/views/sequence_option_view.xml new file mode 100644 index 00000000000..7b1724dd534 --- /dev/null +++ b/base_sequence_option/views/sequence_option_view.xml @@ -0,0 +1,95 @@ + + + + + + + view.base.sequence.option.tree + base.sequence.option + + + + + + + + + + + view.sequence.option.tree + sequence.option + + + + + + + + + + + + + view.base.sequence.option.form + base.sequence.option + +
+

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+ + + Manage Sequence Options + base.sequence.option + tree,form + + + + + +
From 1be82c80258961def6482fa89050bebf21572aee Mon Sep 17 00:00:00 2001 From: Kitti U Date: Sat, 28 Aug 2021 21:08:47 +0700 Subject: [PATCH 2/7] Refactor for multi-company --- base_sequence_option/__manifest__.py | 1 + base_sequence_option/models/__init__.py | 2 +- ...quence_option.py => ir_sequence_option.py} | 39 +++++++++++++++---- .../security/ir.model.access.csv | 8 ++-- .../security/sequence_option_security.xml | 18 +++++++++ base_sequence_option/tests/__init__.py | 2 +- .../tests/base_sequence_tester.py | 6 +-- base_sequence_option/tests/common.py | 10 ++--- ...e_option.py => test_ir_sequence_option.py} | 0 .../views/sequence_option_view.xml | 36 +++++++++-------- 10 files changed, 84 insertions(+), 38 deletions(-) rename base_sequence_option/models/{sequence_option.py => ir_sequence_option.py} (72%) create mode 100644 base_sequence_option/security/sequence_option_security.xml rename base_sequence_option/tests/{test_base_sequence_option.py => test_ir_sequence_option.py} (100%) diff --git a/base_sequence_option/__manifest__.py b/base_sequence_option/__manifest__.py index ad23285b67d..3bbd82f7f45 100644 --- a/base_sequence_option/__manifest__.py +++ b/base_sequence_option/__manifest__.py @@ -13,6 +13,7 @@ "depends": ["base"], "data": [ "security/ir.model.access.csv", + "security/sequence_option_security.xml", "views/sequence_option_view.xml", ], "license": "LGPL-3", diff --git a/base_sequence_option/models/__init__.py b/base_sequence_option/models/__init__.py index 94cb0ad4022..e3f324a793e 100644 --- a/base_sequence_option/models/__init__.py +++ b/base_sequence_option/models/__init__.py @@ -1,5 +1,5 @@ # Copyright 2021 Ecosoft Co., Ltd. (http://ecosoft.co.th) # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). -from . import sequence_option +from . import ir_sequence_option from . import ir_sequence diff --git a/base_sequence_option/models/sequence_option.py b/base_sequence_option/models/ir_sequence_option.py similarity index 72% rename from base_sequence_option/models/sequence_option.py rename to base_sequence_option/models/ir_sequence_option.py index e2197148cc7..c37d05d03be 100644 --- a/base_sequence_option/models/sequence_option.py +++ b/base_sequence_option/models/ir_sequence_option.py @@ -6,9 +6,10 @@ from odoo.tools import safe_eval -class BaseSequenceOption(models.Model): - _name = "base.sequence.option" +class IrSequenceOption(models.Model): + _name = "ir.sequence.option" _description = "Sequence Option Base Model" + _check_company_auto = True name = fields.Char(readonly=True) use_sequence_option = fields.Boolean( @@ -20,21 +21,32 @@ class BaseSequenceOption(models.Model): selection=[], string="Apply On Model", required=True, - readonly=True, + readonly=False, + index=True, ) option_ids = fields.One2many( string="Sequence Options", - comodel_name="sequence.option", + comodel_name="ir.sequence.option.line", inverse_name="base_id", ) + company_id = fields.Many2one( + comodel_name="res.company", + string="Company", + required=True, + readonly=False, + index=True, + default=lambda self: self.env.company, + help="Company related to this sequence option", + ) -class SequenceOption(models.Model): - _name = "sequence.option" - _description = "Sequence Options" +class IrSequenceOptionLine(models.Model): + _name = "ir.sequence.option.line" + _description = "Sequence Option Line" + _check_company_auto = True base_id = fields.Many2one( - comodel_name="base.sequence.option", + comodel_name="ir.sequence.option", index=True, required=True, ondelete="cascade", @@ -61,6 +73,7 @@ class SequenceOption(models.Model): comodel_name="ir.sequence", string="Sequence", required=True, + check_company=True, ) prefix = fields.Char( related="sequence_id.prefix", @@ -77,6 +90,11 @@ class SequenceOption(models.Model): string="Implementation", readonly=True, ) + company_id = fields.Many2one( + comodel_name="res.company", + related="base_id.company_id", + store=True, + ) def get_model_options(self, model): return self.sudo().search( @@ -89,6 +107,11 @@ def get_sequence(self, record, options=False): """ if not options: options = self.get_model_options(record._name) + # multi-company + company = ( + hasattr(record, "company_id") and record.company_id or self.env.company + ) + options = options.filtered(lambda l: l.company_id == company) sequence = self.env["ir.sequence"] for option in options: domain = safe_eval.safe_eval(option.filter_domain) diff --git a/base_sequence_option/security/ir.model.access.csv b/base_sequence_option/security/ir.model.access.csv index 8ab27d5850a..90a101a56e7 100644 --- a/base_sequence_option/security/ir.model.access.csv +++ b/base_sequence_option/security/ir.model.access.csv @@ -1,5 +1,5 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_sequence_option,access_sequence_option,model_sequence_option,base.group_user,1,0,0,0 -access_sequence_option_system,access_sequence_option_system,model_sequence_option,base.group_system,1,1,1,1 -access_base_sequence_option,access_base_sequence_option,model_base_sequence_option,base.group_user,1,0,0,0 -access_base_sequence_option_system,access_base_sequence_option_system,model_base_sequence_option,base.group_system,1,1,1,1 +access_ir_sequence_option_line,access_ir_sequence_option_line,model_ir_sequence_option_line,base.group_user,1,0,0,0 +access_ir_sequence_option_line_system,access_ir_sequence_option_line_system,model_ir_sequence_option_line,base.group_system,1,1,1,1 +access_ir_sequence_option,access_ir_sequence_option,model_ir_sequence_option,base.group_user,1,0,0,0 +access_ir_sequence_option_system,access_ir_sequence_option_system,model_ir_sequence_option,base.group_system,1,1,1,1 diff --git a/base_sequence_option/security/sequence_option_security.xml b/base_sequence_option/security/sequence_option_security.xml new file mode 100644 index 00000000000..14ab82d31bf --- /dev/null +++ b/base_sequence_option/security/sequence_option_security.xml @@ -0,0 +1,18 @@ + + + Sequence Option: multi-company + + + + [('company_id', 'in', company_ids)] + + + + Sequence Option Line: multi-company + + + + [('company_id', 'in', company_ids)] + + + diff --git a/base_sequence_option/tests/__init__.py b/base_sequence_option/tests/__init__.py index 62730016962..118f59c2e7e 100644 --- a/base_sequence_option/tests/__init__.py +++ b/base_sequence_option/tests/__init__.py @@ -2,4 +2,4 @@ # License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html). from . import common -from . import test_base_sequence_option +from . import test_ir_sequence_option diff --git a/base_sequence_option/tests/base_sequence_tester.py b/base_sequence_option/tests/base_sequence_tester.py index d9f2a165c0b..652bcc9a390 100644 --- a/base_sequence_option/tests/base_sequence_tester.py +++ b/base_sequence_option/tests/base_sequence_tester.py @@ -13,7 +13,7 @@ class BaseSequenceTester(models.Model): @api.model def create(self, vals): - seq = self.env["sequence.option"].get_sequence(self.new(vals)) + seq = self.env["ir.sequence.option.line"].get_sequence(self.new(vals)) if seq: # use sequence from sequence.option, instead of base.sequence.tester self = self.with_context(sequence_option_id=seq.id) new_seq = self.env["ir.sequence"].next_by_code("base.sequence.tester") @@ -21,8 +21,8 @@ def create(self, vals): return super().create(vals) -class BaseSequenceOption(models.Model): - _inherit = "base.sequence.option" +class IrSequenceOption(models.Model): + _inherit = "ir.sequence.option" model = fields.Selection( selection_add=[("base.sequence.tester", "base.sequence.tester")], diff --git a/base_sequence_option/tests/common.py b/base_sequence_option/tests/common.py index a19f002c19f..92efc699e79 100644 --- a/base_sequence_option/tests/common.py +++ b/base_sequence_option/tests/common.py @@ -13,9 +13,9 @@ def setUpClass(cls): cls.loader = FakeModelLoader(cls.env, cls.__module__) cls.loader.backup_registry() - from .base_sequence_tester import BaseSequenceOption, BaseSequenceTester + from .base_sequence_tester import BaseSequenceTester, IrSequenceOption - cls.loader.update_registry((BaseSequenceTester, BaseSequenceOption)) + cls.loader.update_registry((BaseSequenceTester, IrSequenceOption)) cls.test_model = cls.env[BaseSequenceTester._name] @@ -60,8 +60,8 @@ def setUpClass(cls): } ) - # Create sequence options for model bsae.sequence.tester: - cls.base_sequence_obj = cls.env["base.sequence.option"] + # Create sequence options for model base.sequence.tester: + cls.base_sequence_obj = cls.env["ir.sequence.option"] cls.base_seq = cls.base_sequence_obj.create( { "name": "Test Model", @@ -69,7 +69,7 @@ def setUpClass(cls): "use_sequence_option": True, } ) - cls.sequence_obj = cls.env["sequence.option"] + cls.sequence_obj = cls.env["ir.sequence.option.line"] cls.sequence_obj.create( { "base_id": cls.base_seq.id, diff --git a/base_sequence_option/tests/test_base_sequence_option.py b/base_sequence_option/tests/test_ir_sequence_option.py similarity index 100% rename from base_sequence_option/tests/test_base_sequence_option.py rename to base_sequence_option/tests/test_ir_sequence_option.py diff --git a/base_sequence_option/views/sequence_option_view.xml b/base_sequence_option/views/sequence_option_view.xml index 7b1724dd534..19b667ae038 100644 --- a/base_sequence_option/views/sequence_option_view.xml +++ b/base_sequence_option/views/sequence_option_view.xml @@ -4,21 +4,22 @@ - - view.base.sequence.option.tree - base.sequence.option + + view.ir.sequence.option.tree + ir.sequence.option - + + - - view.sequence.option.tree - sequence.option + + view.ir.sequence.option.line.tree + ir.sequence.option.line @@ -30,17 +31,18 @@ - - view.base.sequence.option.form - base.sequence.option + + view.ir.sequence.option.form + ir.sequence.option -
+

+ @@ -55,6 +57,7 @@ + @@ -69,6 +72,7 @@ + @@ -77,17 +81,17 @@
- + Manage Sequence Options - base.sequence.option + ir.sequence.option tree,form - + From af25075dfd542b0822078f5cf131c9b6fe733477 Mon Sep 17 00:00:00 2001 From: oca-travis Date: Tue, 23 Nov 2021 12:20:06 +0000 Subject: [PATCH 3/7] [UPD] Update base_sequence_option.pot --- .../i18n/base_sequence_option.pot | 209 ++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 base_sequence_option/i18n/base_sequence_option.pot diff --git a/base_sequence_option/i18n/base_sequence_option.pot b/base_sequence_option/i18n/base_sequence_option.pot new file mode 100644 index 00000000000..9de07ab2ada --- /dev/null +++ b/base_sequence_option/i18n/base_sequence_option.pot @@ -0,0 +1,209 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * base_sequence_option +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.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: base_sequence_option +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option_line__filter_domain +msgid "Apply On" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option__model +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option_line__model +msgid "Apply On Model" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option_line__base_id +msgid "Base" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option__company_id +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option_line__company_id +msgid "Company" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,help:base_sequence_option.field_ir_sequence_option__company_id +#: model:ir.model.fields,help:base_sequence_option.field_ir_sequence_option_line__company_id +msgid "Company related to this sequence option" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option__create_uid +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option_line__create_uid +msgid "Created by" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option__create_date +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option_line__create_date +msgid "Created on" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option_line__name +msgid "Description" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence__display_name +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option__display_name +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option_line__display_name +msgid "Display Name" +msgstr "" + +#. module: base_sequence_option +#: model_terms:ir.ui.view,arch_db:base_sequence_option.view_ir_sequence_option_form +#: model_terms:ir.ui.view,arch_db:base_sequence_option.view_ir_sequence_option_line_tree +msgid "Doctype Sequence" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,help:base_sequence_option.field_ir_sequence_option_line__filter_domain +msgid "Find matching option by document values" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence__id +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option__id +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option_line__id +msgid "ID" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,help:base_sequence_option.field_ir_sequence_option__use_sequence_option +#: model:ir.model.fields,help:base_sequence_option.field_ir_sequence_option_line__use_sequence_option +msgid "" +"If checked, Odoo will try to find the new matching sequence first, if not " +"found, fall back to use the original Odoo sequence." +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option_line__implementation +msgid "Implementation" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence____last_update +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option____last_update +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option_line____last_update +msgid "Last Modified on" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option__write_uid +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option_line__write_uid +msgid "Last Updated by" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option__write_date +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option_line__write_date +msgid "Last Updated on" +msgstr "" + +#. module: base_sequence_option +#: model:ir.actions.act_window,name:base_sequence_option.action_ir_sequence_option +#: model:ir.ui.menu,name:base_sequence_option.menu_ir_sequence_option +#: model_terms:ir.ui.view,arch_db:base_sequence_option.view_ir_sequence_option_tree +msgid "Manage Sequence Options" +msgstr "" + +#. module: base_sequence_option +#: model_terms:ir.ui.view,arch_db:base_sequence_option.view_ir_sequence_option_form +msgid "Matching Domain" +msgstr "" + +#. module: base_sequence_option +#: code:addons/base_sequence_option/models/ir_sequence_option.py:0 +#, python-format +msgid "Multiple optional sequences found for this model!" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option__name +#: model_terms:ir.ui.view,arch_db:base_sequence_option.view_ir_sequence_option_form +msgid "Name" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option_line__prefix +msgid "Prefix" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,help:base_sequence_option.field_ir_sequence_option_line__prefix +msgid "Prefix value of the record for the sequence" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model,name:base_sequence_option.model_ir_sequence +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option_line__sequence_id +msgid "Sequence" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model,name:base_sequence_option.model_ir_sequence_option +msgid "Sequence Option Base Model" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model,name:base_sequence_option.model_ir_sequence_option_line +msgid "Sequence Option Line" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option__option_ids +msgid "Sequence Options" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence__smart_search +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option__smart_search +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option_line__smart_search +msgid "Smart Search" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option_line__suffix +msgid "Suffix" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,help:base_sequence_option.field_ir_sequence_option_line__suffix +msgid "Suffix value of the record for the sequence" +msgstr "" + +#. module: base_sequence_option +#: model_terms:ir.ui.view,arch_db:base_sequence_option.view_ir_sequence_option_form +msgid "Use Sequence" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option__use_sequence_option +#: model:ir.model.fields,field_description:base_sequence_option.field_ir_sequence_option_line__use_sequence_option +msgid "Use sequence options" +msgstr "" + +#. module: base_sequence_option +#: model:ir.model.fields,help:base_sequence_option.field_ir_sequence_option_line__implementation +msgid "" +"While assigning a sequence number to a record, the 'no gap' sequence " +"implementation ensures that each previous sequence number has been assigned " +"already. While this sequence implementation will not skip any sequence " +"number upon assignment, there can still be gaps in the sequence if records " +"are deleted. The 'no gap' implementation is slower than the standard one." +msgstr "" From 212b030140ceb30b0a3e0415a0957909a8bcc45e Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Tue, 23 Nov 2021 12:47:32 +0000 Subject: [PATCH 4/7] [UPD] README.rst --- base_sequence_option/README.rst | 119 ++++++++++++++++++ .../static/description/index.html | 67 +++++++--- 2 files changed, 168 insertions(+), 18 deletions(-) create mode 100644 base_sequence_option/README.rst diff --git a/base_sequence_option/README.rst b/base_sequence_option/README.rst new file mode 100644 index 00000000000..0745017f8bf --- /dev/null +++ b/base_sequence_option/README.rst @@ -0,0 +1,119 @@ +==================== +Base Sequence Option +==================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Alpha-red.png + :target: https://odoo-community.org/page/development-status + :alt: Alpha +.. |badge2| image:: https://img.shields.io/badge/licence-LGPL--3-blue.png + :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html + :alt: License: LGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github + :target: https://github.com/OCA/server-tools/tree/14.0/base_sequence_option + :alt: OCA/server-tools +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/server-tools-14-0/server-tools-14-0-base_sequence_option + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/149/14.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module allow user to add optional sequences to some document model. +On which sequence is used, is based on domain matching with document values +(and original sequence will be bypassed). + +For example, it is now possible to, + +* Avoid using Odoo automatic sequence on invoice and vendor bill with old style sequence. +* Customer payment and vendor payment to run on different sequence. +* Assign different sales order sequence based on customer region. + +This is a base module and does nothing by itself. Following are modules +that will allow managing sequence options for each type of documents, I.e., + +* Purchase Order: purchase_sequence_option +* Invoice / Bill / Refund / Payment: account_sequence_option +* Others: create a new module with few lines of code + +.. IMPORTANT:: + This is an alpha version, the data model and design can change at any time without warning. + Only for development or testing purpose, do not use in production. + `More details on development status `_ + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +To use this module, you need to: + +1. Go to *Settings > Technical > Sequences & Identifier > Manage Sequence Options*. +2. Based on extended module installed, different document types will be listed, i.e., Purchase Order. +3. Activite "Use sequence options" to use, if not, fall back to normal sequence. +4. For each option, provide, + * Name: i.e., Customer Invoice for Cust A., Customer Payment, etc. + * Apply On: a filter domain to test whether a document match this option. + * Sequence: select underlining sequence to perform + +**Note:** + +* If no options matches the document, fall back to normal sequence. +* If there are multiple sequence options that match same document, error will be raised. + +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 +~~~~~~~ + +* Ecosoft + +Contributors +~~~~~~~~~~~~ + +* Kitti U. + +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-kittiu| image:: https://github.com/kittiu.png?size=40px + :target: https://github.com/kittiu + :alt: kittiu + +Current `maintainer `__: + +|maintainer-kittiu| + +This module is part of the `OCA/server-tools `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/base_sequence_option/static/description/index.html b/base_sequence_option/static/description/index.html index 3922ee59fef..bf8088a0f44 100644 --- a/base_sequence_option/static/description/index.html +++ b/base_sequence_option/static/description/index.html @@ -4,7 +4,7 @@ -Base Cron Exclusion +Base Sequence Option -
-

Base Cron Exclusion

+
+

Base Sequence Option

-

Production/Stable License: LGPL-3 OCA/server-tools Translate me on Weblate Try me on Runbot

-

This module extends the functionality of scheduled actions to allow you to -select the ones that should not run simultaneously.

+

Alpha License: LGPL-3 OCA/server-tools Translate me on Weblate Try me on Runbot

+

This module allow user to add optional sequences to some document model. +On which sequence is used, is based on domain matching with document values +(and original sequence will be bypassed).

+

For example, it is now possible to,

+
    +
  • Avoid using Odoo automatic sequence on invoice and vendor bill with old style sequence.
  • +
  • Customer payment and vendor payment to run on different sequence.
  • +
  • Assign different sales order sequence based on customer region.
  • +
+

This is a base module and does nothing by itself. Following are modules +that will allow managing sequence options for each type of documents, I.e.,

+
    +
  • Purchase Order: purchase_sequence_option
  • +
  • Invoice / Bill / Refund / Payment: account_sequence_option
  • +
  • Others: create a new module with few lines of code
  • +
+
+

Important

+

This is an alpha version, the data model and design can change at any time without warning. +Only for development or testing purpose, do not use in production. +More details on development status

+

Table of contents

    @@ -387,19 +407,32 @@

    Base Cron Exclusion

    Usage

    To use this module, you need to:

      -
    1. Go to Settings > Technical > Automation > Scheduled Actions.
    2. -
    3. In the form view go to the tab Mutually Exclusive Scheduled Actions.
    4. -
    5. Fill it with the actions that should be blocked while running the action -you are editing. Note that this is mutual and the selected actions will -block the initial action when running.
    6. +
    7. Go to Settings > Technical > Sequences & Identifier > Manage Sequence Options.
    8. +
    9. Based on extended module installed, different document types will be listed, i.e., Purchase Order.
    10. +
    11. Activite “Use sequence options” to use, if not, fall back to normal sequence.
    12. +
    13. +
      For each option, provide,
      +
        +
      • Name: i.e., Customer Invoice for Cust A., Customer Payment, etc.
      • +
      • Apply On: a filter domain to test whether a document match this option.
      • +
      • Sequence: select underlining sequence to perform
      • +
      +
      +
      +
    +

    Note:

    +
      +
    • If no options matches the document, fall back to normal sequence.
    • +
    • If there are multiple sequence options that match same document, error will be raised.
    • +

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.

@@ -407,15 +440,13 @@

Credits

Authors

    -
  • ForgeFlow
  • +
  • Ecosoft
@@ -426,8 +457,8 @@

Maintainers

mission is to support the collaborative development of Odoo features and promote its widespread use.

Current maintainer:

-

LoisRForgeFlow

-

This module is part of the OCA/server-tools project on GitHub.

+

kittiu

+

This module is part of the OCA/server-tools project on GitHub.

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

From d499fcfc9be8bbca17c8393f2748b62ed306a3dc Mon Sep 17 00:00:00 2001 From: heliaktiv Date: Thu, 4 Aug 2022 10:41:36 +0530 Subject: [PATCH 5/7] [IMP] base_sequence_option: black, isort, prettier --- setup/base_sequence_option/odoo/addons/base_sequence_option | 1 + setup/base_sequence_option/setup.py | 6 ++++++ 2 files changed, 7 insertions(+) create mode 120000 setup/base_sequence_option/odoo/addons/base_sequence_option create mode 100644 setup/base_sequence_option/setup.py diff --git a/setup/base_sequence_option/odoo/addons/base_sequence_option b/setup/base_sequence_option/odoo/addons/base_sequence_option new file mode 120000 index 00000000000..bdf35621335 --- /dev/null +++ b/setup/base_sequence_option/odoo/addons/base_sequence_option @@ -0,0 +1 @@ +../../../../base_sequence_option \ No newline at end of file diff --git a/setup/base_sequence_option/setup.py b/setup/base_sequence_option/setup.py new file mode 100644 index 00000000000..28c57bb6403 --- /dev/null +++ b/setup/base_sequence_option/setup.py @@ -0,0 +1,6 @@ +import setuptools + +setuptools.setup( + setup_requires=['setuptools-odoo'], + odoo_addon=True, +) From 756ac2d4303c95344ddf0dfad607247211de0e33 Mon Sep 17 00:00:00 2001 From: heliaktiv Date: Thu, 4 Aug 2022 10:43:20 +0530 Subject: [PATCH 6/7] [MIG] base_sequence_option: Migration to 15.0 --- base_sequence_option/__manifest__.py | 2 +- .../i18n/base_sequence_option.pot | 2 +- base_sequence_option/tests/common.py | 5 +- .../views/sequence_option_view.xml | 81 ++++++++----------- 4 files changed, 40 insertions(+), 50 deletions(-) diff --git a/base_sequence_option/__manifest__.py b/base_sequence_option/__manifest__.py index 3bbd82f7f45..f07420a9072 100644 --- a/base_sequence_option/__manifest__.py +++ b/base_sequence_option/__manifest__.py @@ -4,7 +4,7 @@ { "name": "Base Sequence Option", "summary": "Alternative sequence options for specific models", - "version": "14.0.1.0.0", + "version": "15.0.1.0.0", "author": "Ecosoft, Odoo Community Association (OCA)", "maintainers": ["kittiu"], "development_status": "Alpha", diff --git a/base_sequence_option/i18n/base_sequence_option.pot b/base_sequence_option/i18n/base_sequence_option.pot index 9de07ab2ada..a33f0ccbd48 100644 --- a/base_sequence_option/i18n/base_sequence_option.pot +++ b/base_sequence_option/i18n/base_sequence_option.pot @@ -4,7 +4,7 @@ # msgid "" msgstr "" -"Project-Id-Version: Odoo Server 14.0\n" +"Project-Id-Version: Odoo Server 15.0\n" "Report-Msgid-Bugs-To: \n" "Last-Translator: \n" "Language-Team: \n" diff --git a/base_sequence_option/tests/common.py b/base_sequence_option/tests/common.py index 92efc699e79..67853a4b2a7 100644 --- a/base_sequence_option/tests/common.py +++ b/base_sequence_option/tests/common.py @@ -9,7 +9,7 @@ class CommonBaseSequenceOption(common.SavepointCase): @classmethod def setUpClass(cls): - super(CommonBaseSequenceOption, cls).setUpClass() + res = super(CommonBaseSequenceOption, cls).setUpClass() cls.loader = FakeModelLoader(cls.env, cls.__module__) cls.loader.backup_registry() @@ -86,8 +86,9 @@ def setUpClass(cls): "sequence_id": seq_b.id, } ) + return res @classmethod def tearDownClass(cls): cls.loader.restore_registry() - super(CommonBaseSequenceOption, cls).tearDownClass() + return super(CommonBaseSequenceOption, cls).tearDownClass() diff --git a/base_sequence_option/views/sequence_option_view.xml b/base_sequence_option/views/sequence_option_view.xml index 19b667ae038..45f44763173 100644 --- a/base_sequence_option/views/sequence_option_view.xml +++ b/base_sequence_option/views/sequence_option_view.xml @@ -2,77 +2,70 @@ - - view.ir.sequence.option.tree ir.sequence.option - - - - - + + + + + - view.ir.sequence.option.line.tree ir.sequence.option.line - - - - - - + + + + + + - view.ir.sequence.option.form ir.sequence.option

- +

- - + + - + - - - - - - - - + + + + + + + + - - - + + + - - + + @@ -80,20 +73,16 @@
- Manage Sequence Options ir.sequence.option tree,form - + - - + name="Manage Sequence Options" + id="menu_ir_sequence_option" + action="action_ir_sequence_option" + parent="base.next_id_5" + sequence="20"/>
From cd85e374a82ccc81049359f3a83bf737baf3431e Mon Sep 17 00:00:00 2001 From: heliaktiv Date: Thu, 4 Aug 2022 11:27:13 +0530 Subject: [PATCH 7/7] [MIG] base_sequence_option: refactor the code --- base_sequence_option/models/ir_sequence.py | 4 +- .../tests/base_sequence_tester.py | 2 +- .../views/sequence_option_view.xml | 70 ++++++++++--------- 3 files changed, 40 insertions(+), 36 deletions(-) diff --git a/base_sequence_option/models/ir_sequence.py b/base_sequence_option/models/ir_sequence.py index c3b54f29277..65dae5940e2 100644 --- a/base_sequence_option/models/ir_sequence.py +++ b/base_sequence_option/models/ir_sequence.py @@ -10,13 +10,13 @@ class IrSequence(models.Model): def next_by_id(self, sequence_date=None): sequence_id = self.env.context.get("sequence_option_id", False) if sequence_id: - self = self.browse(sequence_id) + self.browse(sequence_id) return super().next_by_id(sequence_date=sequence_date) @api.model def next_by_code(self, sequence_code, sequence_date=None): sequence_id = self.env.context.get("sequence_option_id", False) if sequence_id: - self = self.browse(sequence_id) + self.browse(sequence_id) return super().next_by_id(sequence_date=sequence_date) return super().next_by_code(sequence_code, sequence_date=sequence_date) diff --git a/base_sequence_option/tests/base_sequence_tester.py b/base_sequence_option/tests/base_sequence_tester.py index 652bcc9a390..8c582d639fc 100644 --- a/base_sequence_option/tests/base_sequence_tester.py +++ b/base_sequence_option/tests/base_sequence_tester.py @@ -15,7 +15,7 @@ class BaseSequenceTester(models.Model): def create(self, vals): seq = self.env["ir.sequence.option.line"].get_sequence(self.new(vals)) if seq: # use sequence from sequence.option, instead of base.sequence.tester - self = self.with_context(sequence_option_id=seq.id) + self.with_context(sequence_option_id=seq.id) new_seq = self.env["ir.sequence"].next_by_code("base.sequence.tester") vals["name"] = new_seq return super().create(vals) diff --git a/base_sequence_option/views/sequence_option_view.xml b/base_sequence_option/views/sequence_option_view.xml index 45f44763173..720d305b39d 100644 --- a/base_sequence_option/views/sequence_option_view.xml +++ b/base_sequence_option/views/sequence_option_view.xml @@ -7,10 +7,10 @@ ir.sequence.option - - - - + + + + @@ -19,11 +19,11 @@ ir.sequence.option.line - - - - - + + + + + @@ -33,39 +33,42 @@

- +

- - + + - + - - - - - - - - + + + + + + + + - - - + + + - - + + @@ -77,12 +80,13 @@ Manage Sequence Options ir.sequence.option tree,form - + + name="Manage Sequence Options" + id="menu_ir_sequence_option" + action="action_ir_sequence_option" + parent="base.next_id_5" + sequence="20" + />