From bcd2f6aa19776088f33f5a0f45818ce21ec7b315 Mon Sep 17 00:00:00 2001 From: Ilyas Date: Tue, 22 Nov 2022 22:03:46 +0500 Subject: [PATCH 01/16] [ADD] pos_operating_unit_access --- pos_operating_unit/README.rst | 0 pos_operating_unit/__init__.py | 1 + pos_operating_unit/__manifest__.py | 13 ++ pos_operating_unit/models/__init__.py | 4 + pos_operating_unit/models/pos_config.py | 11 ++ pos_operating_unit/models/pos_order.py | 40 ++++++ pos_operating_unit/models/pos_payment.py | 21 +++ pos_operating_unit/models/pos_session.py | 18 +++ pos_operating_unit/readme/CONTRIBUTORS.rst | 3 + pos_operating_unit/readme/DESCRIPTION.rst | 5 + pos_operating_unit/readme/ROADMAP.rst | 3 + pos_operating_unit/readme/USAGE.rst | 1 + pos_operating_unit/security/pos_security.xml | 75 ++++++++++ .../static/description/icon.png | Bin 0 -> 9455 bytes pos_operating_unit/tests/__init__.py | 1 + pos_operating_unit/tests/test_module.py | 136 ++++++++++++++++++ pos_operating_unit/views/pos_views.xml | 72 ++++++++++ 17 files changed, 404 insertions(+) create mode 100644 pos_operating_unit/README.rst create mode 100644 pos_operating_unit/__init__.py create mode 100644 pos_operating_unit/__manifest__.py create mode 100644 pos_operating_unit/models/__init__.py create mode 100644 pos_operating_unit/models/pos_config.py create mode 100644 pos_operating_unit/models/pos_order.py create mode 100644 pos_operating_unit/models/pos_payment.py create mode 100644 pos_operating_unit/models/pos_session.py create mode 100644 pos_operating_unit/readme/CONTRIBUTORS.rst create mode 100644 pos_operating_unit/readme/DESCRIPTION.rst create mode 100644 pos_operating_unit/readme/ROADMAP.rst create mode 100644 pos_operating_unit/readme/USAGE.rst create mode 100644 pos_operating_unit/security/pos_security.xml create mode 100644 pos_operating_unit/static/description/icon.png create mode 100644 pos_operating_unit/tests/__init__.py create mode 100644 pos_operating_unit/tests/test_module.py create mode 100644 pos_operating_unit/views/pos_views.xml diff --git a/pos_operating_unit/README.rst b/pos_operating_unit/README.rst new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pos_operating_unit/__init__.py b/pos_operating_unit/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/pos_operating_unit/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/pos_operating_unit/__manifest__.py b/pos_operating_unit/__manifest__.py new file mode 100644 index 0000000000..17bf915eb4 --- /dev/null +++ b/pos_operating_unit/__manifest__.py @@ -0,0 +1,13 @@ +{ + "name": "POS Operating Unit Access", + "version": "14.0.1.0.0", + "author": "Ilyas, Ooops404, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/operating-unit", + "category": "Point of sale", + "depends": ["point_of_sale", "operating_unit"], + "license": "LGPL-3", + "data": [ + "security/pos_security.xml", + "views/pos_views.xml", + ], +} diff --git a/pos_operating_unit/models/__init__.py b/pos_operating_unit/models/__init__.py new file mode 100644 index 0000000000..55d2bb6794 --- /dev/null +++ b/pos_operating_unit/models/__init__.py @@ -0,0 +1,4 @@ +from . import pos_config +from . import pos_order +from . import pos_session +from . import pos_payment diff --git a/pos_operating_unit/models/pos_config.py b/pos_operating_unit/models/pos_config.py new file mode 100644 index 0000000000..3717d2665f --- /dev/null +++ b/pos_operating_unit/models/pos_config.py @@ -0,0 +1,11 @@ +from odoo import fields, models + + +class POSConfig(models.Model): + _inherit = "pos.config" + + operating_unit_ids = fields.Many2many( + "operating.unit", + "pos_config_operating_unit_rel", + string="Operating Units", + ) diff --git a/pos_operating_unit/models/pos_order.py b/pos_operating_unit/models/pos_order.py new file mode 100644 index 0000000000..0c19571c9e --- /dev/null +++ b/pos_operating_unit/models/pos_order.py @@ -0,0 +1,40 @@ +from odoo import api, fields, models + + +class POSOrder(models.Model): + _inherit = "pos.order" + + operating_unit_ids = fields.Many2many( + "operating.unit", + "pos_order_operating_unit_rel", + string="Operating Units", + ) + config_id = fields.Many2one(related="session_id.config_id", readonly=True) + + @api.model + def create(self, vals): + session_id = self.env["pos.session"].sudo().browse(vals.get("session_id")) + if session_id.config_id: + vals["operating_unit_ids"] = [ + (6, 0, session_id.config_id.operating_unit_ids.ids) + ] + return super(POSOrder, self).create(vals) + + +class POSOrderLine(models.Model): + _inherit = "pos.order.line" + + operating_unit_ids = fields.Many2many( + "operating.unit", + "pos_order_line_operating_unit_rel", + string="Operating Units", + ) + + @api.model + def create(self, vals): + order_id = self.env["pos.order"].sudo().browse(vals.get("order_id")) + if order_id.config_id: + vals["operating_unit_ids"] = [ + (6, 0, order_id.config_id.operating_unit_ids.ids) + ] + return super(POSOrderLine, self).create(vals) diff --git a/pos_operating_unit/models/pos_payment.py b/pos_operating_unit/models/pos_payment.py new file mode 100644 index 0000000000..5f7098d4f8 --- /dev/null +++ b/pos_operating_unit/models/pos_payment.py @@ -0,0 +1,21 @@ +from odoo import api, fields, models + + +class POSPayment(models.Model): + _inherit = "pos.payment" + + operating_unit_ids = fields.Many2many( + "operating.unit", + "pos_payment_operating_unit_rel", + string="Operating Units", + ) + config_id = fields.Many2one(related="session_id.config_id", readonly=True) + + @api.model + def create(self, vals): + pos_order_id = self.env["pos.order"].sudo().browse(vals.get("pos_order_id")) + if pos_order_id.config_id: + vals["operating_unit_ids"] = [ + (6, 0, pos_order_id.config_id.operating_unit_ids.ids) + ] + return super(POSPayment, self).create(vals) diff --git a/pos_operating_unit/models/pos_session.py b/pos_operating_unit/models/pos_session.py new file mode 100644 index 0000000000..734235265d --- /dev/null +++ b/pos_operating_unit/models/pos_session.py @@ -0,0 +1,18 @@ +from odoo import api, fields, models + + +class POSSession(models.Model): + _inherit = "pos.session" + + operating_unit_ids = fields.Many2many( + "operating.unit", + "pos_session_operating_unit_rel", + string="Operating Units", + ) + + @api.model + def create(self, vals): + config_id = self.env["pos.config"].sudo().browse(vals.get("config_id")) + if config_id: + vals["operating_unit_ids"] = [(6, 0, config_id.operating_unit_ids.ids)] + return super(POSSession, self).create(vals) diff --git a/pos_operating_unit/readme/CONTRIBUTORS.rst b/pos_operating_unit/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..6f583d7f26 --- /dev/null +++ b/pos_operating_unit/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +* Ooops404 + + * Ilyas diff --git a/pos_operating_unit/readme/DESCRIPTION.rst b/pos_operating_unit/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..1e3c3a5ca8 --- /dev/null +++ b/pos_operating_unit/readme/DESCRIPTION.rst @@ -0,0 +1,5 @@ +This module adds a field "operating unit" in POS with the only goal of restricting visibility (therefore access) to users with same OU allowed. + +This also applies to sessions, orders and payments in POS. + +A "Point of sale" field is added to orders and payments for clarity. diff --git a/pos_operating_unit/readme/ROADMAP.rst b/pos_operating_unit/readme/ROADMAP.rst new file mode 100644 index 0000000000..16377349b4 --- /dev/null +++ b/pos_operating_unit/readme/ROADMAP.rst @@ -0,0 +1,3 @@ +This module only manages visibility of POS and related orders. If a more complete +"pos_operating_unit" is proposed and merged, then it should cover features of this +module which can be discontinued. diff --git a/pos_operating_unit/readme/USAGE.rst b/pos_operating_unit/readme/USAGE.rst new file mode 100644 index 0000000000..67c5e78a22 --- /dev/null +++ b/pos_operating_unit/readme/USAGE.rst @@ -0,0 +1 @@ +In POS config, set operating unit(s) allowed to see this POS. diff --git a/pos_operating_unit/security/pos_security.xml b/pos_operating_unit/security/pos_security.xml new file mode 100644 index 0000000000..36630438bd --- /dev/null +++ b/pos_operating_unit/security/pos_security.xml @@ -0,0 +1,75 @@ + + + + + ['|', ('operating_unit_ids', '=', False), + ('operating_unit_ids', 'in', user.operating_unit_ids.ids)] + POS Config allowed operating units + + + + + + + + + + ['|', ('operating_unit_ids', '=', False), + ('operating_unit_ids', 'in', user.operating_unit_ids.ids)] + POS Session allowed operating units + + + + + + + + + + ['|', ('operating_unit_ids', '=', False), + ('operating_unit_ids', 'in', user.operating_unit_ids.ids)] + POS Order allowed operating units + + + + + + + + + + ['|', ('operating_unit_ids', '=', False), + ('operating_unit_ids', 'in', user.operating_unit_ids.ids)] + POS Order Line allowed operating units + + + + + + + + + + ['|', ('operating_unit_ids', '=', False), + ('operating_unit_ids', 'in', user.operating_unit_ids.ids)] + POS Payment allowed operating units + + + + + + + + + + ['|', ('config_id.operating_unit_ids', '=', False), + ('config_id.operating_unit_ids', 'in', user.operating_unit_ids.ids)] + POS Order Report allowed operating units + + + + + + + + diff --git a/pos_operating_unit/static/description/icon.png b/pos_operating_unit/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/pos_operating_unit/tests/__init__.py b/pos_operating_unit/tests/__init__.py new file mode 100644 index 0000000000..d9b96c4fa5 --- /dev/null +++ b/pos_operating_unit/tests/__init__.py @@ -0,0 +1 @@ +from . import test_module diff --git a/pos_operating_unit/tests/test_module.py b/pos_operating_unit/tests/test_module.py new file mode 100644 index 0000000000..cb181e4e9a --- /dev/null +++ b/pos_operating_unit/tests/test_module.py @@ -0,0 +1,136 @@ +from odoo import fields +from odoo.exceptions import AccessError +from odoo.tests.common import TransactionCase + + +class TestModule(TransactionCase): + def setUp(self): + super(TestModule, self).setUp() + self.ResUsers = self.env["res.users"] + self.PosOrder = self.env["pos.order"] + self.pos_product = self.env.ref("point_of_sale.whiteboard_pen") + self.pricelist = self.env.ref("product.list0") + + # Create a new pos config and open it + self.pos_config = self.env.ref("point_of_sale.pos_config_main").copy() + + # company + self.company = self.env.ref("base.main_company") + # group + self.group_user = self.env.ref("base.group_user") + self.group_pos_manager = self.env.ref("point_of_sale.group_pos_manager") + # Main Operating Unit + self.ou1 = self.env.ref("operating_unit.main_operating_unit") + # B2B Operating Unit + self.b2b = self.env.ref("operating_unit.b2b_operating_unit") + + self.pos_config.operating_unit_ids = [(6, 0, [self.ou1.id])] + self.pos_config.open_session_cb() + + # Create users + self.user1_id = self._create_user( + "user_1", + [self.group_user, self.group_pos_manager], + self.company, + [self.ou1, self.b2b], + ) + self.user2_id = self._create_user( + "user_2", + [self.group_user, self.group_pos_manager], + self.company, + [self.b2b], + ) + + def test_operating_unit_access_config(self): + config1_ids = self.env["pos.config"].with_user(self.user1_id).search([]) + self.assertIn(self.pos_config, config1_ids) + config2_ids = self.env["pos.config"].with_user(self.user2_id).search([]) + self.assertNotIn(self.pos_config, config2_ids) + + def test_operating_unit_access_session(self): + self.pos_config.current_session_id.with_user(self.user1_id).read() + with self.assertRaises(AccessError): + self.pos_config.current_session_id.with_user(self.user2_id).read() + + def test_operating_unit_access_order_and_line_and_payment(self): + order = self._create_order() + order.with_user(self.user1_id).read() + order.lines.with_user(self.user1_id).read() + with self.assertRaises(AccessError): + order.with_user(self.user2_id).read() + with self.assertRaises(AccessError): + order.lines.with_user(self.user2_id).read() + order.payment_ids.with_user(self.user1_id).read() + with self.assertRaises(AccessError): + order.payment_ids.with_user(self.user2_id).read() + + def _create_order(self): + # Create order + account_id = self.env.user.partner_id.property_account_receivable_id.id + order_data = { + "id": "0006-001-0010", + "to_invoice": False, + "data": { + "pricelist_id": self.pricelist.id, + "user_id": 1, + "name": "Order 0006-001-0010", + "partner_id": False, + "amount_paid": 1000, + "pos_session_id": self.pos_config.current_session_id.id, + "lines": [ + [ + 0, + 0, + { + "product_id": self.pos_product.id, + "qty": 1, + "price_subtotal": 1000, + "price_subtotal_incl": 1000, + }, + ] + ], + "statement_ids": [ + [ + 0, + 0, + { + "payment_method_id": self.pos_config.payment_method_ids[ + 0 + ].id, + "amount": 1000, + "name": fields.Datetime.now(), + "account_id": account_id, + "session_id": self.pos_config.current_session_id.id, + }, + ] + ], + "creation_date": "2022-11-27 15:51:03", + "amount_tax": 0, + "fiscal_position_id": False, + "uid": "00001-001-0001", + "amount_return": 0, + "sequence_number": 1, + "amount_total": 1000.0, + "session_id": self.pos_config.current_session_id.id, + }, + } + result = self.PosOrder.create_from_ui([order_data]) + order = self.PosOrder.browse(result[0].get("id")) + return order + + def _create_user(self, login, groups, company, operating_units): + """Create a user.""" + group_ids = [group.id for group in groups] + user = self.ResUsers.with_context({"no_reset_password": True}).create( + { + "name": "Chicago Purchase User", + "login": login, + "password": "demo", + "email": "chicago@yourcompany.com", + "company_id": company.id, + "company_ids": [(4, company.id)], + "operating_unit_ids": [(4, ou.id) for ou in operating_units], + "groups_id": [(6, 0, group_ids)], + } + ) + return user.id diff --git a/pos_operating_unit/views/pos_views.xml b/pos_operating_unit/views/pos_views.xml new file mode 100644 index 0000000000..824b7153e8 --- /dev/null +++ b/pos_operating_unit/views/pos_views.xml @@ -0,0 +1,72 @@ + + + + pos.config.form.inherit.ou + pos.config + + + +
+
+
+
+
+
+
+ + + + + + pos.order.form.inherit.ou + pos.order + + + + + + + + + + pos.order.tree.inherit.ou + pos.order + + + + + + + + + + pos.payment.form.inherit.ou + pos.payment + + + + + + + + + + pos.payment.tree.inherit.ou + pos.payment + + + + + + + + + From ad0a4edf6c207dd8ce76bcfd0ebc8c2f76d392a7 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Tue, 10 Jan 2023 09:44:14 +0000 Subject: [PATCH 02/16] [UPD] README.rst --- pos_operating_unit/README.rst | 92 ++++ .../static/description/index.html | 437 ++++++++++++++++++ 2 files changed, 529 insertions(+) create mode 100644 pos_operating_unit/static/description/index.html diff --git a/pos_operating_unit/README.rst b/pos_operating_unit/README.rst index e69de29bb2..ef2b361ceb 100644 --- a/pos_operating_unit/README.rst +++ b/pos_operating_unit/README.rst @@ -0,0 +1,92 @@ +========================= +POS Operating Unit Access +========================= + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! 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-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%2Foperating--unit-lightgray.png?logo=github + :target: https://github.com/OCA/operating-unit/tree/14.0/pos_operating_unit + :alt: OCA/operating-unit +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/operating-unit-14-0/operating-unit-14-0-pos_operating_unit + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/213/14.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +This module adds a field "operating unit" in POS with the only goal of restricting visibility (therefore access) to users with same OU allowed. + +This also applies to sessions, orders and payments in POS. + +A "Point of sale" field is added to orders and payments for clarity. + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +In POS config, set operating unit(s) allowed to see this POS. + +Known issues / Roadmap +====================== + +This module only manages visibility of POS and related orders. If a more complete +"pos_operating_unit" is proposed and merged, then it should cover features of this +module which can be discontinued. + +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 +~~~~~~~ + +* Ilyas +* Ooops404 + +Contributors +~~~~~~~~~~~~ + +* Ooops404 + + * Ilyas + +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/operating-unit `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/pos_operating_unit/static/description/index.html b/pos_operating_unit/static/description/index.html new file mode 100644 index 0000000000..6f9cf3daef --- /dev/null +++ b/pos_operating_unit/static/description/index.html @@ -0,0 +1,437 @@ + + + + + + +POS Operating Unit Access + + + +
+

POS Operating Unit Access

+ + +

Beta License: LGPL-3 OCA/operating-unit Translate me on Weblate Try me on Runbot

+

This module adds a field “operating unit” in POS with the only goal of restricting visibility (therefore access) to users with same OU allowed.

+

This also applies to sessions, orders and payments in POS.

+

A “Point of sale” field is added to orders and payments for clarity.

+

Table of contents

+ +
+

Usage

+

In POS config, set operating unit(s) allowed to see this POS.

+
+
+

Known issues / Roadmap

+

This module only manages visibility of POS and related orders. If a more complete +“pos_operating_unit” is proposed and merged, then it should cover features of this +module which can be discontinued.

+
+
+

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

+
    +
  • Ilyas
  • +
  • Ooops404
  • +
+
+
+

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/operating-unit project on GitHub.

+

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

+
+
+
+ + From 88a3878905bb01051a9ee60edf9e7852f900966e Mon Sep 17 00:00:00 2001 From: oca-ci Date: Tue, 17 Jan 2023 15:30:48 +0000 Subject: [PATCH 03/16] [UPD] Update pos_operating_unit.pot --- .../i18n/pos_operating_unit.pot | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 pos_operating_unit/i18n/pos_operating_unit.pot diff --git a/pos_operating_unit/i18n/pos_operating_unit.pot b/pos_operating_unit/i18n/pos_operating_unit.pot new file mode 100644 index 0000000000..c22a67993f --- /dev/null +++ b/pos_operating_unit/i18n/pos_operating_unit.pot @@ -0,0 +1,87 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_operating_unit +# +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: pos_operating_unit +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_config__display_name +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order__display_name +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order_line__display_name +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment__display_name +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_session__display_name +msgid "Display Name" +msgstr "" + +#. module: pos_operating_unit +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_config__id +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order__id +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order_line__id +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment__id +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_session__id +msgid "ID" +msgstr "" + +#. module: pos_operating_unit +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_config____last_update +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order____last_update +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order_line____last_update +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment____last_update +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_session____last_update +msgid "Last Modified on" +msgstr "" + +#. module: pos_operating_unit +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_config__operating_unit_ids +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order__operating_unit_ids +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order_line__operating_unit_ids +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment__operating_unit_ids +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_session__operating_unit_ids +msgid "Operating Units" +msgstr "" + +#. module: pos_operating_unit +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order__config_id +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment__config_id +msgid "Point of Sale" +msgstr "" + +#. module: pos_operating_unit +#: model:ir.model,name:pos_operating_unit.model_pos_config +msgid "Point of Sale Configuration" +msgstr "" + +#. module: pos_operating_unit +#: model:ir.model,name:pos_operating_unit.model_pos_order_line +msgid "Point of Sale Order Lines" +msgstr "" + +#. module: pos_operating_unit +#: model:ir.model,name:pos_operating_unit.model_pos_order +msgid "Point of Sale Orders" +msgstr "" + +#. module: pos_operating_unit +#: model:ir.model,name:pos_operating_unit.model_pos_payment +msgid "Point of Sale Payments" +msgstr "" + +#. module: pos_operating_unit +#: model:ir.model,name:pos_operating_unit.model_pos_session +msgid "Point of Sale Session" +msgstr "" + +#. module: pos_operating_unit +#: model:ir.model.fields,help:pos_operating_unit.field_pos_order__config_id +#: model:ir.model.fields,help:pos_operating_unit.field_pos_payment__config_id +msgid "The physical point of sale you will use." +msgstr "" From d68adf2c5aaa5ebc43ba35d92a53b02bfdf6a54e Mon Sep 17 00:00:00 2001 From: Francesco Foresti Date: Wed, 18 Jan 2023 08:47:56 +0000 Subject: [PATCH 04/16] Added translation using Weblate (Italian) --- pos_operating_unit/i18n/it.po | 88 +++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 pos_operating_unit/i18n/it.po diff --git a/pos_operating_unit/i18n/it.po b/pos_operating_unit/i18n/it.po new file mode 100644 index 0000000000..708212e1eb --- /dev/null +++ b/pos_operating_unit/i18n/it.po @@ -0,0 +1,88 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_operating_unit +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: it\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: pos_operating_unit +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_config__display_name +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order__display_name +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order_line__display_name +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment__display_name +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_session__display_name +msgid "Display Name" +msgstr "" + +#. module: pos_operating_unit +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_config__id +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order__id +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order_line__id +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment__id +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_session__id +msgid "ID" +msgstr "" + +#. module: pos_operating_unit +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_config____last_update +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order____last_update +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order_line____last_update +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment____last_update +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_session____last_update +msgid "Last Modified on" +msgstr "" + +#. module: pos_operating_unit +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_config__operating_unit_ids +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order__operating_unit_ids +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order_line__operating_unit_ids +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment__operating_unit_ids +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_session__operating_unit_ids +msgid "Operating Units" +msgstr "" + +#. module: pos_operating_unit +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order__config_id +#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment__config_id +msgid "Point of Sale" +msgstr "" + +#. module: pos_operating_unit +#: model:ir.model,name:pos_operating_unit.model_pos_config +msgid "Point of Sale Configuration" +msgstr "" + +#. module: pos_operating_unit +#: model:ir.model,name:pos_operating_unit.model_pos_order_line +msgid "Point of Sale Order Lines" +msgstr "" + +#. module: pos_operating_unit +#: model:ir.model,name:pos_operating_unit.model_pos_order +msgid "Point of Sale Orders" +msgstr "" + +#. module: pos_operating_unit +#: model:ir.model,name:pos_operating_unit.model_pos_payment +msgid "Point of Sale Payments" +msgstr "" + +#. module: pos_operating_unit +#: model:ir.model,name:pos_operating_unit.model_pos_session +msgid "Point of Sale Session" +msgstr "" + +#. module: pos_operating_unit +#: model:ir.model.fields,help:pos_operating_unit.field_pos_order__config_id +#: model:ir.model.fields,help:pos_operating_unit.field_pos_payment__config_id +msgid "The physical point of sale you will use." +msgstr "" From 9b90540b685139c6aa5f6a1637bb120048cd98e6 Mon Sep 17 00:00:00 2001 From: Francesco Foresti Date: Wed, 18 Jan 2023 08:49:03 +0000 Subject: [PATCH 05/16] Translated using Weblate (Italian) Currently translated at 100.0% (11 of 11 strings) Translation: operating-unit-14.0/operating-unit-14.0-pos_operating_unit Translate-URL: https://translation.odoo-community.org/projects/operating-unit-14-0/operating-unit-14-0-pos_operating_unit/it/ --- pos_operating_unit/i18n/it.po | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/pos_operating_unit/i18n/it.po b/pos_operating_unit/i18n/it.po index 708212e1eb..6cff132c5a 100644 --- a/pos_operating_unit/i18n/it.po +++ b/pos_operating_unit/i18n/it.po @@ -6,13 +6,15 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 14.0\n" "Report-Msgid-Bugs-To: \n" -"Last-Translator: Automatically generated\n" +"PO-Revision-Date: 2023-01-18 11:45+0000\n" +"Last-Translator: Francesco Foresti \n" "Language-Team: none\n" "Language: it\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 4.14.1\n" #. module: pos_operating_unit #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_config__display_name @@ -21,7 +23,7 @@ msgstr "" #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment__display_name #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_session__display_name msgid "Display Name" -msgstr "" +msgstr "Nome visualizzato" #. module: pos_operating_unit #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_config__id @@ -30,7 +32,7 @@ msgstr "" #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment__id #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_session__id msgid "ID" -msgstr "" +msgstr "ID" #. module: pos_operating_unit #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_config____last_update @@ -39,7 +41,7 @@ msgstr "" #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment____last_update #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_session____last_update msgid "Last Modified on" -msgstr "" +msgstr "Ultima modifica il" #. module: pos_operating_unit #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_config__operating_unit_ids @@ -48,41 +50,41 @@ msgstr "" #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment__operating_unit_ids #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_session__operating_unit_ids msgid "Operating Units" -msgstr "" +msgstr "Unità operative" #. module: pos_operating_unit #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order__config_id #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment__config_id msgid "Point of Sale" -msgstr "" +msgstr "Punto vendita" #. module: pos_operating_unit #: model:ir.model,name:pos_operating_unit.model_pos_config msgid "Point of Sale Configuration" -msgstr "" +msgstr "Configurazione punto vendita" #. module: pos_operating_unit #: model:ir.model,name:pos_operating_unit.model_pos_order_line msgid "Point of Sale Order Lines" -msgstr "" +msgstr "Righe ordine punto vendita" #. module: pos_operating_unit #: model:ir.model,name:pos_operating_unit.model_pos_order msgid "Point of Sale Orders" -msgstr "" +msgstr "Ordini punto vendita" #. module: pos_operating_unit #: model:ir.model,name:pos_operating_unit.model_pos_payment msgid "Point of Sale Payments" -msgstr "" +msgstr "Pagamenti punto vendita" #. module: pos_operating_unit #: model:ir.model,name:pos_operating_unit.model_pos_session msgid "Point of Sale Session" -msgstr "" +msgstr "Sessione punto vendita" #. module: pos_operating_unit #: model:ir.model.fields,help:pos_operating_unit.field_pos_order__config_id #: model:ir.model.fields,help:pos_operating_unit.field_pos_payment__config_id msgid "The physical point of sale you will use." -msgstr "" +msgstr "Il punto vendita fisico che userai." From 5c332c0c1ddb1d54980aeaf815562f58dc0bee33 Mon Sep 17 00:00:00 2001 From: OCA-git-bot Date: Sun, 3 Sep 2023 14:49:32 +0000 Subject: [PATCH 06/16] [UPD] README.rst --- pos_operating_unit/README.rst | 15 ++++--- .../static/description/index.html | 42 ++++++++++--------- 2 files changed, 31 insertions(+), 26 deletions(-) diff --git a/pos_operating_unit/README.rst b/pos_operating_unit/README.rst index ef2b361ceb..4ae5f188fa 100644 --- a/pos_operating_unit/README.rst +++ b/pos_operating_unit/README.rst @@ -2,10 +2,13 @@ POS Operating Unit Access ========================= -.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! This file is generated by oca-gen-addon-readme !! !! changes will be overwritten. !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:8fb92e5f7aea276b3cf26d223c0ead05b42f63f12ca8d2e9f45285951f3245bb + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! .. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png :target: https://odoo-community.org/page/development-status @@ -19,11 +22,11 @@ POS Operating Unit Access .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png :target: https://translation.odoo-community.org/projects/operating-unit-14-0/operating-unit-14-0-pos_operating_unit :alt: Translate me on Weblate -.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png - :target: https://runbot.odoo-community.org/runbot/213/14.0 - :alt: Try me on Runbot +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/operating-unit&target_branch=14.0 + :alt: Try me on Runboat -|badge1| |badge2| |badge3| |badge4| |badge5| +|badge1| |badge2| |badge3| |badge4| |badge5| This module adds a field "operating unit" in POS with the only goal of restricting visibility (therefore access) to users with same OU allowed. @@ -53,7 +56,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 +If you spotted it first, help us to smash it by providing a detailed and welcomed `feedback `_. Do not contact contributors directly about support or help with technical issues. diff --git a/pos_operating_unit/static/description/index.html b/pos_operating_unit/static/description/index.html index 6f9cf3daef..d7b20b35e5 100644 --- a/pos_operating_unit/static/description/index.html +++ b/pos_operating_unit/static/description/index.html @@ -1,20 +1,20 @@ - + - + POS Operating Unit Access -
-

POS Operating Unit Access

+
+

POS with Operating Units

Beta License: LGPL-3 OCA/operating-unit Translate me on Weblate Try me on Runboat

This module adds a field “operating unit” in POS with the only goal of From 6fb824c25d1894b9d325df1df650d54587dc30e5 Mon Sep 17 00:00:00 2001 From: Weblate Date: Thu, 29 Aug 2024 18:42:43 +0000 Subject: [PATCH 13/16] Update translation files Updated by "Update PO files to match POT (msgmerge)" hook in Weblate. Translation: operating-unit-17.0/operating-unit-17.0-pos_operating_unit Translate-URL: https://translation.odoo-community.org/projects/operating-unit-17-0/operating-unit-17-0-pos_operating_unit/ --- pos_operating_unit/i18n/es.po | 53 +++++++++++++++-------------------- pos_operating_unit/i18n/it.po | 53 +++++++++++++++-------------------- 2 files changed, 46 insertions(+), 60 deletions(-) diff --git a/pos_operating_unit/i18n/es.po b/pos_operating_unit/i18n/es.po index 53d729c2ce..0d0af125c3 100644 --- a/pos_operating_unit/i18n/es.po +++ b/pos_operating_unit/i18n/es.po @@ -17,31 +17,9 @@ msgstr "" "X-Generator: Weblate 4.17\n" #. module: pos_operating_unit -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_config__display_name -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order__display_name -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order_line__display_name -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment__display_name -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_session__display_name -msgid "Display Name" -msgstr "Mostrar Nombre" - -#. module: pos_operating_unit -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_config__id -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order__id -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order_line__id -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment__id -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_session__id -msgid "ID" -msgstr "ID" - -#. module: pos_operating_unit -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_config____last_update -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order____last_update -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order_line____last_update -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment____last_update -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_session____last_update -msgid "Last Modified on" -msgstr "Última Modificación el" +#: model:ir.model,name:pos_operating_unit.model_res_config_settings +msgid "Config Settings" +msgstr "" #. module: pos_operating_unit #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_config__operating_unit_ids @@ -49,9 +27,18 @@ msgstr "Última Modificación el" #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order_line__operating_unit_ids #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment__operating_unit_ids #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_session__operating_unit_ids +#: model:ir.model.fields,field_description:pos_operating_unit.field_res_config_settings__pos_operating_unit_ids +#: model_terms:ir.ui.view,arch_db:pos_operating_unit.pos_config_view_form_inherit_ou +#: model_terms:ir.ui.view,arch_db:pos_operating_unit.res_config_settings_view_form msgid "Operating Units" msgstr "Unidades Operativas" +#. module: pos_operating_unit +#: model_terms:ir.ui.view,arch_db:pos_operating_unit.pos_config_view_form_inherit_ou +#: model_terms:ir.ui.view,arch_db:pos_operating_unit.res_config_settings_view_form +msgid "Operating units used for this POS" +msgstr "" + #. module: pos_operating_unit #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order__config_id #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment__config_id @@ -83,8 +70,14 @@ msgstr "Pagos en el Punto de Venta" msgid "Point of Sale Session" msgstr "Sesión del Punto de Venta" -#. module: pos_operating_unit -#: model:ir.model.fields,help:pos_operating_unit.field_pos_order__config_id -#: model:ir.model.fields,help:pos_operating_unit.field_pos_payment__config_id -msgid "The physical point of sale you will use." -msgstr "El punto de venta físico que usted utilizará." +#~ msgid "Display Name" +#~ msgstr "Mostrar Nombre" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "Last Modified on" +#~ msgstr "Última Modificación el" + +#~ msgid "The physical point of sale you will use." +#~ msgstr "El punto de venta físico que usted utilizará." diff --git a/pos_operating_unit/i18n/it.po b/pos_operating_unit/i18n/it.po index 6cff132c5a..677e63e025 100644 --- a/pos_operating_unit/i18n/it.po +++ b/pos_operating_unit/i18n/it.po @@ -17,31 +17,9 @@ msgstr "" "X-Generator: Weblate 4.14.1\n" #. module: pos_operating_unit -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_config__display_name -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order__display_name -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order_line__display_name -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment__display_name -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_session__display_name -msgid "Display Name" -msgstr "Nome visualizzato" - -#. module: pos_operating_unit -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_config__id -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order__id -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order_line__id -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment__id -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_session__id -msgid "ID" -msgstr "ID" - -#. module: pos_operating_unit -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_config____last_update -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order____last_update -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order_line____last_update -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment____last_update -#: model:ir.model.fields,field_description:pos_operating_unit.field_pos_session____last_update -msgid "Last Modified on" -msgstr "Ultima modifica il" +#: model:ir.model,name:pos_operating_unit.model_res_config_settings +msgid "Config Settings" +msgstr "" #. module: pos_operating_unit #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_config__operating_unit_ids @@ -49,9 +27,18 @@ msgstr "Ultima modifica il" #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order_line__operating_unit_ids #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment__operating_unit_ids #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_session__operating_unit_ids +#: model:ir.model.fields,field_description:pos_operating_unit.field_res_config_settings__pos_operating_unit_ids +#: model_terms:ir.ui.view,arch_db:pos_operating_unit.pos_config_view_form_inherit_ou +#: model_terms:ir.ui.view,arch_db:pos_operating_unit.res_config_settings_view_form msgid "Operating Units" msgstr "Unità operative" +#. module: pos_operating_unit +#: model_terms:ir.ui.view,arch_db:pos_operating_unit.pos_config_view_form_inherit_ou +#: model_terms:ir.ui.view,arch_db:pos_operating_unit.res_config_settings_view_form +msgid "Operating units used for this POS" +msgstr "" + #. module: pos_operating_unit #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order__config_id #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_payment__config_id @@ -83,8 +70,14 @@ msgstr "Pagamenti punto vendita" msgid "Point of Sale Session" msgstr "Sessione punto vendita" -#. module: pos_operating_unit -#: model:ir.model.fields,help:pos_operating_unit.field_pos_order__config_id -#: model:ir.model.fields,help:pos_operating_unit.field_pos_payment__config_id -msgid "The physical point of sale you will use." -msgstr "Il punto vendita fisico che userai." +#~ msgid "Display Name" +#~ msgstr "Nome visualizzato" + +#~ msgid "ID" +#~ msgstr "ID" + +#~ msgid "Last Modified on" +#~ msgstr "Ultima modifica il" + +#~ msgid "The physical point of sale you will use." +#~ msgstr "Il punto vendita fisico che userai." From c4dda6158709a540bc51c10302dd0c9954c25a7a Mon Sep 17 00:00:00 2001 From: mymage Date: Fri, 30 Aug 2024 11:52:50 +0000 Subject: [PATCH 14/16] Translated using Weblate (Italian) Currently translated at 100.0% (9 of 9 strings) Translation: operating-unit-17.0/operating-unit-17.0-pos_operating_unit Translate-URL: https://translation.odoo-community.org/projects/operating-unit-17-0/operating-unit-17-0-pos_operating_unit/it/ --- pos_operating_unit/i18n/it.po | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pos_operating_unit/i18n/it.po b/pos_operating_unit/i18n/it.po index 677e63e025..dde87bde06 100644 --- a/pos_operating_unit/i18n/it.po +++ b/pos_operating_unit/i18n/it.po @@ -6,20 +6,20 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 14.0\n" "Report-Msgid-Bugs-To: \n" -"PO-Revision-Date: 2023-01-18 11:45+0000\n" -"Last-Translator: Francesco Foresti \n" +"PO-Revision-Date: 2024-08-30 14:06+0000\n" +"Last-Translator: mymage \n" "Language-Team: none\n" "Language: it\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 4.14.1\n" +"X-Generator: Weblate 5.6.2\n" #. module: pos_operating_unit #: model:ir.model,name:pos_operating_unit.model_res_config_settings msgid "Config Settings" -msgstr "" +msgstr "Impostazioni configurazione" #. module: pos_operating_unit #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_config__operating_unit_ids @@ -37,7 +37,7 @@ msgstr "Unità operative" #: model_terms:ir.ui.view,arch_db:pos_operating_unit.pos_config_view_form_inherit_ou #: model_terms:ir.ui.view,arch_db:pos_operating_unit.res_config_settings_view_form msgid "Operating units used for this POS" -msgstr "" +msgstr "Unità operative utilizzate per questo POS" #. module: pos_operating_unit #: model:ir.model.fields,field_description:pos_operating_unit.field_pos_order__config_id From 246ac16a6af033888522a4236178eef19a63e4cc Mon Sep 17 00:00:00 2001 From: Cristiam Carreno Date: Tue, 2 Sep 2025 14:03:03 -0500 Subject: [PATCH 15/16] [IMP] pos_operating_unit: pre-commit auto fixes --- pos_operating_unit/security/pos_security.xml | 4 +--- pos_operating_unit/views/pos_views.xml | 2 -- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/pos_operating_unit/security/pos_security.xml b/pos_operating_unit/security/pos_security.xml index e2ce66e1f0..d69cad9fc9 100644 --- a/pos_operating_unit/security/pos_security.xml +++ b/pos_operating_unit/security/pos_security.xml @@ -1,5 +1,4 @@ - ['|', ('operating_unit_ids', '=', False), @@ -36,7 +35,7 @@ - + ['|', ('operating_unit_ids', '=', False), ('operating_unit_ids', 'in', operating_unit_ids)] @@ -71,5 +70,4 @@ - diff --git a/pos_operating_unit/views/pos_views.xml b/pos_operating_unit/views/pos_views.xml index 145f3c82e2..3d88829fd3 100644 --- a/pos_operating_unit/views/pos_views.xml +++ b/pos_operating_unit/views/pos_views.xml @@ -1,5 +1,4 @@ - pos.config.form.inherit.ou pos.config @@ -92,5 +91,4 @@ - From 5553c6f7043b743cbf8dc81fe8bbd101ea615cef Mon Sep 17 00:00:00 2001 From: Cristiam Carreno Date: Mon, 1 Sep 2025 10:41:50 -0500 Subject: [PATCH 16/16] [18.0][MIG] pos_operating_unit: migrate to 18.0 --- pos_operating_unit/README.rst | 18 +- pos_operating_unit/__manifest__.py | 2 +- pos_operating_unit/readme/CONTRIBUTORS.md | 7 +- .../static/description/index.html | 14 +- pos_operating_unit/tests/__init__.py | 2 + .../tests/test_pos_operating_unit.py | 177 ++++++++++++------ .../tests/test_pos_operating_unit_basic.py | 80 ++++++++ .../tests/test_pos_operating_unit_rules.py | 72 +++++++ 8 files changed, 297 insertions(+), 75 deletions(-) create mode 100644 pos_operating_unit/tests/test_pos_operating_unit_basic.py create mode 100644 pos_operating_unit/tests/test_pos_operating_unit_rules.py diff --git a/pos_operating_unit/README.rst b/pos_operating_unit/README.rst index f362641d22..6441dce708 100644 --- a/pos_operating_unit/README.rst +++ b/pos_operating_unit/README.rst @@ -17,13 +17,13 @@ POS with Operating Units :target: http://www.gnu.org/licenses/lgpl-3.0-standalone.html :alt: License: LGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Foperating--unit-lightgray.png?logo=github - :target: https://github.com/OCA/operating-unit/tree/17.0/pos_operating_unit + :target: https://github.com/OCA/operating-unit/tree/18.0/pos_operating_unit :alt: OCA/operating-unit .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/operating-unit-17-0/operating-unit-17-0-pos_operating_unit + :target: https://translation.odoo-community.org/projects/operating-unit-18-0/operating-unit-18-0-pos_operating_unit :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/operating-unit&target_branch=17.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/operating-unit&target_branch=18.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| @@ -58,7 +58,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -74,9 +74,13 @@ Authors Contributors ------------ -- Ooops404 +- Ooops404 https://ooops404.com - - Ilyas + - Ilyas irazor147@gmail.com + +- Nybble Group https://www.nybblegroup.com + + - Cristiam Carreño cristiamcarreno@gmail.com Maintainers ----------- @@ -91,6 +95,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/operating-unit `_ project on GitHub. +This module is part of the `OCA/operating-unit `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/pos_operating_unit/__manifest__.py b/pos_operating_unit/__manifest__.py index 9a4a89fd63..66ed46b605 100644 --- a/pos_operating_unit/__manifest__.py +++ b/pos_operating_unit/__manifest__.py @@ -1,6 +1,6 @@ { "name": "POS with Operating Units", - "version": "17.0.1.0.0", + "version": "18.0.1.0.0", "author": "Ilyas, Ooops404, Odoo Community Association (OCA)", "website": "https://github.com/OCA/operating-unit", "category": "Point of sale", diff --git a/pos_operating_unit/readme/CONTRIBUTORS.md b/pos_operating_unit/readme/CONTRIBUTORS.md index dbafc0aad9..4f05caa05d 100644 --- a/pos_operating_unit/readme/CONTRIBUTORS.md +++ b/pos_operating_unit/readme/CONTRIBUTORS.md @@ -1,2 +1,5 @@ -- Ooops404 \<\> - - Ilyas \<\> +- Ooops404 + - Ilyas + +- Nybble Group + - Cristiam Carreño diff --git a/pos_operating_unit/static/description/index.html b/pos_operating_unit/static/description/index.html index 7ef7c86231..09c88aa79b 100644 --- a/pos_operating_unit/static/description/index.html +++ b/pos_operating_unit/static/description/index.html @@ -369,7 +369,7 @@

POS with Operating Units

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:ff2417b3a2178379e4a963b4b7fed6282bfb952b07931806cec94e7806d49d61 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: LGPL-3 OCA/operating-unit Translate me on Weblate Try me on Runboat

+

Beta License: LGPL-3 OCA/operating-unit Translate me on Weblate Try me on Runboat

This module adds a field “operating unit” in POS with the only goal of restricting visibility (therefore access) to users with same OU allowed.

This also applies to sessions, orders and payments in POS.

@@ -403,7 +403,7 @@

Bug Tracker

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

+feedback.

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

@@ -418,8 +418,12 @@

Authors

Contributors

diff --git a/pos_operating_unit/tests/__init__.py b/pos_operating_unit/tests/__init__.py index b66281b776..f4c3bbf52d 100644 --- a/pos_operating_unit/tests/__init__.py +++ b/pos_operating_unit/tests/__init__.py @@ -1 +1,3 @@ +from . import test_pos_operating_unit_basic +from . import test_pos_operating_unit_rules from . import test_pos_operating_unit diff --git a/pos_operating_unit/tests/test_pos_operating_unit.py b/pos_operating_unit/tests/test_pos_operating_unit.py index d8de6c0ef8..1c0e1f0e72 100644 --- a/pos_operating_unit/tests/test_pos_operating_unit.py +++ b/pos_operating_unit/tests/test_pos_operating_unit.py @@ -1,33 +1,69 @@ +# Copyright 2024 ForgeFlow, S.L. +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) + from odoo import fields from odoo.exceptions import AccessError -from odoo.models import Command +from odoo.fields import Command +from odoo.tests import tagged from odoo.addons.operating_unit.tests.common import OperatingUnitCommon +@tagged("post_install", "-at_install") class TestPOSOperatingUnit(OperatingUnitCommon): + """Test Point of Sale Operating Unit access controls and functionality.""" + @classmethod def setUpClass(cls): super().setUpClass() + + # Setup models cls.PosOrder = cls.env["pos.order"] - cls.pos_product = cls.env.ref("point_of_sale.whiteboard_pen") - cls.pricelist = cls.env["product.pricelist"].search([], limit=1) + cls.PosConfig = cls.env["pos.config"] + cls.PosSession = cls.env["pos.session"] + + # Setup product for testing + cls.pos_product = cls.env["product.product"].create( + { + "name": "Test POS Product", + "available_in_pos": True, + "list_price": 1000.0, + } + ) - # Create a new pos config and open it - cls.pos_config = cls.env.ref("point_of_sale.pos_config_main").copy() + # Setup pricelist + cls.pricelist = cls.env["product.pricelist"].create( + { + "name": "Test POS Pricelist", + "currency_id": cls.env.company.currency_id.id, + } + ) + + # Setup groups cls.group_pos_manager = cls.env.ref("point_of_sale.group_pos_manager") cls.group_account_invoice = cls.env.ref("account.group_account_invoice") - cls.pos_config.operating_unit_ids = [Command.set([cls.ou1.id])] + # Create POS config with operating unit + cls.pos_config = cls.env["pos.config"].create( + { + "name": "Test POS Config", + "operating_unit_ids": [Command.set([cls.ou1.id])], + "available_pricelist_ids": [Command.set([cls.pricelist.id])], + "pricelist_id": cls.pricelist.id, + } + ) + + # Open session cls.pos_config.open_ui() + # Configure users with proper groups and operating units cls.user1.write( { "groups_id": [ Command.link(cls.group_pos_manager.id), Command.link(cls.group_account_invoice.id), ], - "operating_unit_ids": [Command.link(cls.b2b.id)], + "operating_unit_ids": [Command.link(cls.ou1.id)], } ) cls.user2.write( @@ -41,80 +77,101 @@ def setUpClass(cls): ) def test_operating_unit_access_config(self): - config1_ids = self.env["pos.config"].with_user(self.user1).search([]) + """Test that users can only access POS configs for their operating units.""" + # User1 has access to ou1 (same as pos_config) + config1_ids = self.PosConfig.with_user(self.user1).search([]) self.assertIn(self.pos_config, config1_ids) - config2_ids = self.env["pos.config"].with_user(self.user2).search([]) + + # User2 has access to b2b (different from pos_config) + config2_ids = self.PosConfig.with_user(self.user2).search([]) self.assertNotIn(self.pos_config, config2_ids) def test_operating_unit_access_session(self): + """Test that users can only access sessions for their operating units.""" + # User1 should be able to read the session self.pos_config.current_session_id.with_user(self.user1).read() + + # User2 should not have access with self.assertRaises(AccessError): self.pos_config.current_session_id.with_user(self.user2).read() def test_operating_unit_access_order_and_line_and_payment(self): + """Test that users can only access orders for their operating units.""" order = self._create_order() + + # User1 should have access to order and related records order.with_user(self.user1).read() order.lines.with_user(self.user1).read() + order.payment_ids.with_user(self.user1).read() + + # User2 should not have access with self.assertRaises(AccessError): order.with_user(self.user2).read() with self.assertRaises(AccessError): order.lines.with_user(self.user2).read() - order.payment_ids.with_user(self.user1).read() with self.assertRaises(AccessError): order.payment_ids.with_user(self.user2).read() def _create_order(self): - # Create order - account_id = self.env.user.partner_id.property_account_receivable_id.id + """Create a test POS order using the modern Odoo 18 approach.""" + # Create order using sync_from_ui method order_data = { "id": "0006-001-0010", "to_invoice": False, - "data": { - "date_order": fields.Datetime.to_string(fields.Datetime.now()), - "pricelist_id": self.pricelist.id, - "user_id": 1, - "name": "Order 0006-001-0010", - "partner_id": False, - "amount_paid": 1000, - "pos_session_id": self.pos_config.current_session_id.id, - "lines": [ - [ - 0, - 0, - { - "product_id": self.pos_product.id, - "qty": 1, - "price_unit": 1000, - "price_subtotal": 1000, - "price_subtotal_incl": 1000, - }, - ] - ], - "statement_ids": [ - [ - 0, - 0, - { - "payment_method_id": self.pos_config.payment_method_ids[ - 0 - ].id, - "amount": 1000, - "name": fields.Datetime.now(), - "account_id": account_id, - "session_id": self.pos_config.current_session_id.id, - }, - ] - ], - "creation_date": "2022-11-27 15:51:03", - "amount_tax": 0, - "fiscal_position_id": False, - "uid": "00001-001-0001", - "amount_return": 0, - "sequence_number": 1, - "amount_total": 1000.0, - "session_id": self.pos_config.current_session_id.id, - }, + "session_id": self.pos_config.current_session_id.id, + "date_order": fields.Datetime.to_string(fields.Datetime.now()), + "pricelist_id": self.pricelist.id, + "user_id": self.env.user.id, + "name": "Order 0006-001-0010", + "partner_id": False, + "amount_paid": 1000.0, + "amount_total": 1000.0, + "amount_tax": 0.0, + "amount_return": 0.0, + "fiscal_position_id": False, + "sequence_number": 1, + "uuid": "00001-001-0001", + "lines": [ + [ + 0, + 0, + { + "product_id": self.pos_product.id, + "qty": 1.0, + "price_unit": 1000.0, + "price_subtotal": 1000.0, + "price_subtotal_incl": 1000.0, + "discount": 0.0, + }, + ] + ], + "payment_ids": [ + [ + 0, + 0, + { + "payment_method_id": self.pos_config.payment_method_ids[0].id, + "amount": 1000.0, + }, + ] + ], } - result = self.PosOrder.create_from_ui([order_data]) - order = self.PosOrder.browse(result[0].get("id")) - return order + + # Create the order + result = self.PosOrder.sync_from_ui([order_data]) + if not result or "pos.order" not in result: + raise ValueError("Failed to create POS order") + + # Get order data from result + pos_orders = result["pos.order"] + if not pos_orders: + raise ValueError("No order data in result") + + # Extract order ID from the first order data + order_data_dict = pos_orders[0] if pos_orders else {} + order_id = order_data_dict.get("id") + + if not order_id: + raise ValueError("Failed to get order ID from result") + + return self.PosOrder.browse(order_id) diff --git a/pos_operating_unit/tests/test_pos_operating_unit_basic.py b/pos_operating_unit/tests/test_pos_operating_unit_basic.py new file mode 100644 index 0000000000..a7ef5dabd6 --- /dev/null +++ b/pos_operating_unit/tests/test_pos_operating_unit_basic.py @@ -0,0 +1,80 @@ +# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl.html) +from odoo.fields import Command +from odoo.tests import tagged + +from odoo.addons.operating_unit.tests.common import OperatingUnitCommon + + +@tagged("post_install", "-at_install") +class TestPOSOperatingUnitBasic(OperatingUnitCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.company = cls.env.ref("base.main_company") + # create partner and OU for the test to satisfy partner_id not-null + partner = cls.env["res.partner"].create({"name": "OU Test Partner"}) + cls.ou = cls.env["operating.unit"].create( + { + "name": "OU Test", + "code": "OUT", + "company_id": cls.company.id, + "partner_id": partner.id, + } + ) + + def test_fields_and_assign(self): + """Test POS configuration and session for operating units.""" + self.assertIn("operating_unit_ids", self.env["pos.config"]._fields) + self.assertIn("operating_unit_ids", self.env["pos.session"]._fields) + cfg = self.env["pos.config"].create( + { + "name": "POS Test", + "company_id": self.company.id, + "operating_unit_ids": [Command.set([self.ou.id])], + } + ) + self.assertIn(self.ou, cfg.operating_unit_ids) + + def test_operating_unit_assignment_via_write(self): + """Ensure operating_unit_ids can be set via write and read back correctly.""" + cfg = self.env["pos.config"].create( + {"name": "POS Write Test", "company_id": self.company.id} + ) + self.assertFalse(cfg.operating_unit_ids) + cfg.write({"operating_unit_ids": [Command.set([self.ou.id])]}) + self.assertIn(self.ou, cfg.operating_unit_ids) + + def test_operating_unit_unset_via_write(self): + """Ensure operating_unit_ids can be unset via write.""" + cfg = self.env["pos.config"].create( + { + "name": "POS Unset Test", + "company_id": self.company.id, + "operating_unit_ids": [Command.set([self.ou.id])], + } + ) + self.assertIn(self.ou, cfg.operating_unit_ids) + cfg.write({"operating_unit_ids": [Command.set([])]}) + self.assertFalse(cfg.operating_unit_ids) + + def test_assign_multiple_operating_units(self): + """Assign multiple operating units to a config and verify both are present.""" + partner2 = self.env["res.partner"].create({"name": "OU2 Partner"}) + ou2 = self.env["operating.unit"].create( + { + "name": "OU 2", + "code": "OU2", + "company_id": self.company.id, + "partner_id": partner2.id, + } + ) + cfg = self.env["pos.config"].create( + { + "name": "POS Multi OU", + "company_id": self.company.id, + "operating_unit_ids": [Command.set([self.ou.id, ou2.id])], + } + ) + self.assertIn(self.ou, cfg.operating_unit_ids) + self.assertIn(ou2, cfg.operating_unit_ids) + self.assertEqual(len(cfg.operating_unit_ids), 2) diff --git a/pos_operating_unit/tests/test_pos_operating_unit_rules.py b/pos_operating_unit/tests/test_pos_operating_unit_rules.py new file mode 100644 index 0000000000..e7e33c3e16 --- /dev/null +++ b/pos_operating_unit/tests/test_pos_operating_unit_rules.py @@ -0,0 +1,72 @@ +from odoo.fields import Command +from odoo.tests import tagged + +from odoo.addons.operating_unit.tests.common import OperatingUnitCommon + + +@tagged("post_install", "-at_install") +class TestPOSOperatingUnitRules(OperatingUnitCommon): + @classmethod + def setUpClass(cls): + super().setUpClass() + company = cls.env.ref("base.main_company") + # create partners for operating units to satisfy NOT NULL partner_id + partner_a = cls.env["res.partner"].create({"name": "OU A Partner"}) + partner_b = cls.env["res.partner"].create({"name": "OU B Partner"}) + cls.ou_a = cls.env["operating.unit"].create( + { + "name": "OU A", + "code": "OUA", + "company_id": company.id, + "partner_id": partner_a.id, + } + ) + cls.ou_b = cls.env["operating.unit"].create( + { + "name": "OU B", + "code": "OUB", + "company_id": company.id, + "partner_id": partner_b.id, + } + ) + cls.user = cls.env["res.users"].create( + { + "name": "User A", + "login": "user_a@example.com", + "email": "user_a@example.com", + "company_id": company.id, + "operating_unit_ids": [(6, 0, [cls.ou_a.id])], + "groups_id": [ + ( + 6, + 0, + [ + cls.env.ref("point_of_sale.group_pos_user").id, + ], + ) + ], + } + ) + # Sesión en OU_B (no autorizada para el user) + cfg_b = cls.env["pos.config"].create( + { + "name": "POS B", + "company_id": company.id, + "operating_unit_ids": [Command.set([cls.ou_b.id])], + } + ) + cls.session_b = cls.env["pos.session"].create( + { + "config_id": cfg_b.id, + "user_id": cls.env.ref("base.user_admin").id, + } + ) + + def test_record_rule_hides_other_ou_sessions(self): + """Test that the record rule hides POS sessions from other operating units.""" + sess = ( + self.env["pos.session"] + .with_user(self.user) + .search([("id", "=", self.session_b.id)]) + ) + self.assertFalse(sess, "User with OU_A must not see POS sessions from OU_B")