From db85904a908192c629fbda2c9f56c13e669ef0c6 Mon Sep 17 00:00:00 2001 From: Zurab Kituashvili Date: Fri, 14 Jun 2024 17:33:41 +0400 Subject: [PATCH] [16.0] [MIG] pos_product_template: Migration to 16.0 --- pos_product_template/README.rst | 116 +++++ pos_product_template/__init__.py | 1 + pos_product_template/__manifest__.py | 30 ++ .../demo/product_attribute_value.xml | 31 ++ pos_product_template/demo/product_product.xml | 45 ++ pos_product_template/i18n/es.po | 80 +++ pos_product_template/i18n/fr.po | 76 +++ pos_product_template/i18n/it.po | 71 +++ .../i18n/pos_product_template.pot | 50 ++ pos_product_template/models/__init__.py | 1 + pos_product_template/models/pos_config.py | 19 + pos_product_template/readme/CONTRIBUTORS.rst | 20 + pos_product_template/readme/DESCRIPTION.rst | 11 + pos_product_template/readme/ROADMAP.rst | 1 + pos_product_template/readme/USAGE.rst | 2 + .../static/description/icon.png | Bin 0 -> 4290 bytes .../static/description/index.html | 492 ++++++++++++++++++ pos_product_template/static/src/css/ppt.css | 84 +++ .../img/screenshots/pos_product_template.png | Bin 0 -> 21421 bytes .../static/src/js/SelectVariantPopup.esm.js | 229 ++++++++ .../static/src/js/models.esm.js | 191 +++++++ pos_product_template/static/src/js/ppt.esm.js | 101 ++++ .../static/src/xml/SelectVariantPopup.xml | 78 +++ pos_product_template/static/src/xml/ppt.xml | 53 ++ .../views/pos_config_view.xml | 13 + 25 files changed, 1795 insertions(+) create mode 100644 pos_product_template/README.rst create mode 100644 pos_product_template/__init__.py create mode 100644 pos_product_template/__manifest__.py create mode 100644 pos_product_template/demo/product_attribute_value.xml create mode 100644 pos_product_template/demo/product_product.xml create mode 100644 pos_product_template/i18n/es.po create mode 100644 pos_product_template/i18n/fr.po create mode 100644 pos_product_template/i18n/it.po create mode 100644 pos_product_template/i18n/pos_product_template.pot create mode 100644 pos_product_template/models/__init__.py create mode 100644 pos_product_template/models/pos_config.py create mode 100644 pos_product_template/readme/CONTRIBUTORS.rst create mode 100644 pos_product_template/readme/DESCRIPTION.rst create mode 100644 pos_product_template/readme/ROADMAP.rst create mode 100644 pos_product_template/readme/USAGE.rst create mode 100644 pos_product_template/static/description/icon.png create mode 100644 pos_product_template/static/description/index.html create mode 100644 pos_product_template/static/src/css/ppt.css create mode 100644 pos_product_template/static/src/img/screenshots/pos_product_template.png create mode 100644 pos_product_template/static/src/js/SelectVariantPopup.esm.js create mode 100644 pos_product_template/static/src/js/models.esm.js create mode 100644 pos_product_template/static/src/js/ppt.esm.js create mode 100644 pos_product_template/static/src/xml/SelectVariantPopup.xml create mode 100644 pos_product_template/static/src/xml/ppt.xml create mode 100644 pos_product_template/views/pos_config_view.xml diff --git a/pos_product_template/README.rst b/pos_product_template/README.rst new file mode 100644 index 0000000000..26ae13739f --- /dev/null +++ b/pos_product_template/README.rst @@ -0,0 +1,116 @@ +====================== +POS - Product Template +====================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:db57e93b7dc8c62c24c51e03b823c331eac215f8938027e6c0949f97e7f6e202 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fpos-lightgray.png?logo=github + :target: https://github.com/OCA/pos/tree/15.0/pos_product_template + :alt: OCA/pos +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/pos-15-0/pos-15-0-pos_product_template + :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/pos&target_branch=15.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + + * In Point Of Sale Front End - Products list: + * Display only one product per template; + * Display template name instead of product name; + * Display products quantity instead of price; + * Click on template displays an extra screen to select Variant; + + * In Point Of Sale Front End - Variants list: + * Display all the products of the selected variant; + * Click on a attribute value filters products; + * Click on a product adds it to the current Order or display normal + extra screen if it is a weightable product; + +**Table of contents** + +.. contents:: + :local: + +Usage +===== + +Open the Point of Sale, search an article with variants. +You will see one article instead of all the variants. + +Known issues / Roadmap +====================== + +* Templates with lot of variants are not shown. See https://github.com/OCA/pos/pull/135 + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Akretion + +Contributors +~~~~~~~~~~~~ + +* Sylvain LE GAL (https://twitter.com/legalsylvain) +* Navarromiguel (https://github.com/navarromiguel) +* Damendieta (https://github.com/damendieta) +* Raphaël Reverdy (https://akretion.com) +* Pedro Guirao (https://ingenieriacloud.com) + +* `Ooops `_: + + * Giovanni Serra + +* `Aures Tic `_: + + * Jose Zambudio + +Funders +------- + +The development of this module has been financially supported by: + +* Akretion + +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/pos `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/pos_product_template/__init__.py b/pos_product_template/__init__.py new file mode 100644 index 0000000000..0650744f6b --- /dev/null +++ b/pos_product_template/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/pos_product_template/__manifest__.py b/pos_product_template/__manifest__.py new file mode 100644 index 0000000000..7767677333 --- /dev/null +++ b/pos_product_template/__manifest__.py @@ -0,0 +1,30 @@ +{ + "name": "POS - Product Template", + "version": "16.0.1.0.0", + "category": "Point Of Sale", + "author": "Zurab Kituashvili", + "summary": "Manage Product Template in Front End Point Of Sale", + "website": "https://github.com/OCA/pos", + "license": "AGPL-3", + "depends": [ + "point_of_sale", + ], + "data": [ + "views/pos_config_view.xml", + ], + "assets": { + "web.assets_qweb": ["pos_product_template/static/src/xml/**/*.xml"], + "point_of_sale.assets": [ + "pos_product_template/static/src/**/*.js", + "pos_product_template/static/src/css/ppt.css", + ], + }, + "demo": [ + "demo/product_attribute_value.xml", + "demo/product_product.xml", + ], + "images": [ + "static/src/img/screenshots/pos_product_template.png", + ], + "installable": True, +} diff --git a/pos_product_template/demo/product_attribute_value.xml b/pos_product_template/demo/product_attribute_value.xml new file mode 100644 index 0000000000..bb3b6f0996 --- /dev/null +++ b/pos_product_template/demo/product_attribute_value.xml @@ -0,0 +1,31 @@ + + + + + + + 2.399GHz + + + diff --git a/pos_product_template/demo/product_product.xml b/pos_product_template/demo/product_product.xml new file mode 100644 index 0000000000..5b1ee99c85 --- /dev/null +++ b/pos_product_template/demo/product_product.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pos_product_template/i18n/es.po b/pos_product_template/i18n/es.po new file mode 100644 index 0000000000..44d8b9309f --- /dev/null +++ b/pos_product_template/i18n/es.po @@ -0,0 +1,80 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_product_template +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-12-18 12:01+0000\n" +"PO-Revision-Date: 2023-07-26 13:10+0000\n" +"Last-Translator: Anna Martínez \n" +"Language-Team: \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.17\n" + +#. module: pos_product_template +#: model:product.attribute.value,name:pos_product_template.attribute_wifi_extra +msgid "2.399GHz" +msgstr "2.399GHz" + +#. module: pos_product_template +#. openerp-web +#: code:addons/pos_product_template/static/src/xml/SelectVariantPopup.xml:0 +#, python-format +msgid "Cancel" +msgstr "Cancelar" + +#. module: pos_product_template +#. openerp-web +#: code:addons/pos_product_template/static/src/xml/SelectVariantPopup.xml:0 +#, python-format +msgid "Confirm" +msgstr "Confirmar" + +#. module: pos_product_template +#: model:ir.model.fields,field_description:pos_product_template.field_pos_config__display_name +msgid "Display Name" +msgstr "Nombre a mostrar" + +#. module: pos_product_template +#: model:ir.model.fields,field_description:pos_product_template.field_pos_config__id +msgid "ID" +msgstr "ID" + +#. module: pos_product_template +#: model:ir.model.fields,help:pos_product_template.field_pos_config__iface_product_template_show_variants +msgid "" +"If selected the product variant selection screen will show the variants, " +"else it will only allow to confirm once all the attributes are chosen." +msgstr "" +"Si de marca, la pantalla de selección de productos mostrará las variantes, " +"de lo contrario, solo permitirá confirmar una vez elegidos todos los " +"atributos." + +#. module: pos_product_template +#: model:ir.model.fields,field_description:pos_product_template.field_pos_config____last_update +msgid "Last Modified on" +msgstr "Última Modificación en" + +#. module: pos_product_template +#: model:ir.model,name:pos_product_template.model_pos_config +msgid "Point of Sale Configuration" +msgstr "Configuración del punto de venta" + +#. module: pos_product_template +#: model:ir.model.fields,field_description:pos_product_template.field_pos_config__iface_product_template_show_variants +msgid "Product template show variants" +msgstr "La plantilla de producto mostrará las variantes" + +#, python-format +#~ msgid "Variant Selection of" +#~ msgstr "Seleccina una variante de" + +#, python-format +#~ msgid "Variants" +#~ msgstr "Variantes" diff --git a/pos_product_template/i18n/fr.po b/pos_product_template/i18n/fr.po new file mode 100644 index 0000000000..398648869f --- /dev/null +++ b/pos_product_template/i18n/fr.po @@ -0,0 +1,76 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_product_template +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 8.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-12-18 11:57+0000\n" +"PO-Revision-Date: 2014-12-18 11:57+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: pos_product_template +#: model:product.attribute.value,name:pos_product_template.attribute_wifi_extra +msgid "2.399GHz" +msgstr "" + +#. module: pos_product_template +#. openerp-web +#: code:addons/pos_product_template/static/src/xml/SelectVariantPopup.xml:0 +#, python-format +msgid "Cancel" +msgstr "Annuler" + +#. module: pos_product_template +#. openerp-web +#: code:addons/pos_product_template/static/src/xml/SelectVariantPopup.xml:0 +#, python-format +msgid "Confirm" +msgstr "" + +#. module: pos_product_template +#: model:ir.model.fields,field_description:pos_product_template.field_pos_config__display_name +msgid "Display Name" +msgstr "" + +#. module: pos_product_template +#: model:ir.model.fields,field_description:pos_product_template.field_pos_config__id +msgid "ID" +msgstr "" + +#. module: pos_product_template +#: model:ir.model.fields,help:pos_product_template.field_pos_config__iface_product_template_show_variants +msgid "" +"If selected the product variant selection screen will show the variants, " +"else it will only allow to confirm once all the attributes are chosen." +msgstr "" + +#. module: pos_product_template +#: model:ir.model.fields,field_description:pos_product_template.field_pos_config____last_update +msgid "Last Modified on" +msgstr "" + +#. module: pos_product_template +#: model:ir.model,name:pos_product_template.model_pos_config +msgid "Point of Sale Configuration" +msgstr "" + +#. module: pos_product_template +#: model:ir.model.fields,field_description:pos_product_template.field_pos_config__iface_product_template_show_variants +msgid "Product template show variants" +msgstr "" + +#, python-format +#~ msgid "Variant Selection of" +#~ msgstr "Sélection d'une variante de" + +#, python-format +#~ msgid "Variants" +#~ msgstr "Variantes" diff --git a/pos_product_template/i18n/it.po b/pos_product_template/i18n/it.po new file mode 100644 index 0000000000..f369dbf313 --- /dev/null +++ b/pos_product_template/i18n/it.po @@ -0,0 +1,71 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_product_template +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 14.0\n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: 2023-03-16 13:22+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" + +#. module: pos_product_template +#: model:product.attribute.value,name:pos_product_template.attribute_wifi_extra +msgid "2.399GHz" +msgstr "2.399GHz" + +#. module: pos_product_template +#. openerp-web +#: code:addons/pos_product_template/static/src/xml/SelectVariantPopup.xml:0 +#, python-format +msgid "Cancel" +msgstr "Annulla" + +#. module: pos_product_template +#. openerp-web +#: code:addons/pos_product_template/static/src/xml/SelectVariantPopup.xml:0 +#, python-format +msgid "Confirm" +msgstr "Conferma" + +#. module: pos_product_template +#: model:ir.model.fields,field_description:pos_product_template.field_pos_config__display_name +msgid "Display Name" +msgstr "Nome visualizzato" + +#. module: pos_product_template +#: model:ir.model.fields,field_description:pos_product_template.field_pos_config__id +msgid "ID" +msgstr "ID" + +#. module: pos_product_template +#: model:ir.model.fields,help:pos_product_template.field_pos_config__iface_product_template_show_variants +msgid "" +"If selected the product variant selection screen will show the variants, " +"else it will only allow to confirm once all the attributes are chosen." +msgstr "" +"Se selezionato la schermata di selezione variante prodotto visualizzerà le " +"varianti, altrimenti consentirà solo la confema una volta che tutti gli " +"attributi saranno scelti." + +#. module: pos_product_template +#: model:ir.model.fields,field_description:pos_product_template.field_pos_config____last_update +msgid "Last Modified on" +msgstr "Ultima modifica il" + +#. module: pos_product_template +#: model:ir.model,name:pos_product_template.model_pos_config +msgid "Point of Sale Configuration" +msgstr "Configurazione punto vendita" + +#. module: pos_product_template +#: model:ir.model.fields,field_description:pos_product_template.field_pos_config__iface_product_template_show_variants +msgid "Product template show variants" +msgstr "Visualizza varianti modello prodotto" diff --git a/pos_product_template/i18n/pos_product_template.pot b/pos_product_template/i18n/pos_product_template.pot new file mode 100644 index 0000000000..684ddfa560 --- /dev/null +++ b/pos_product_template/i18n/pos_product_template.pot @@ -0,0 +1,50 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * pos_product_template +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 15.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_product_template +#: model:product.attribute.value,name:pos_product_template.attribute_wifi_extra +msgid "2.399GHz" +msgstr "" + +#. module: pos_product_template +#. openerp-web +#: code:addons/pos_product_template/static/src/xml/SelectVariantPopup.xml:0 +#, python-format +msgid "Cancel" +msgstr "" + +#. module: pos_product_template +#. openerp-web +#: code:addons/pos_product_template/static/src/xml/SelectVariantPopup.xml:0 +#, python-format +msgid "Confirm" +msgstr "" + +#. module: pos_product_template +#: model:ir.model.fields,help:pos_product_template.field_pos_config__iface_product_template_show_variants +msgid "" +"If selected the product variant selection screen will show the variants, " +"else it will only allow to confirm once all the attributes are chosen." +msgstr "" + +#. module: pos_product_template +#: model:ir.model,name:pos_product_template.model_pos_config +msgid "Point of Sale Configuration" +msgstr "" + +#. module: pos_product_template +#: model:ir.model.fields,field_description:pos_product_template.field_pos_config__iface_product_template_show_variants +msgid "Product template show variants" +msgstr "" diff --git a/pos_product_template/models/__init__.py b/pos_product_template/models/__init__.py new file mode 100644 index 0000000000..db8634ade1 --- /dev/null +++ b/pos_product_template/models/__init__.py @@ -0,0 +1 @@ +from . import pos_config diff --git a/pos_product_template/models/pos_config.py b/pos_product_template/models/pos_config.py new file mode 100644 index 0000000000..25aaa81596 --- /dev/null +++ b/pos_product_template/models/pos_config.py @@ -0,0 +1,19 @@ +# Copyright 2022 Akretion (https://www.akretion.com). +# @author Pierrick Brun +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import fields, models + + +class PosConfig(models.Model): + _inherit = "pos.config" + + epson_printer_ip = fields.Char(string="Epson Printer IP") + pos_epson_printer_ip = fields.Char(string="POS Printer IP") + + iface_product_template_show_variants = fields.Boolean( + string="Product template show variants", + default=True, + help="If selected the product variant selection screen will show the variants," + " else it will only allow to confirm once all the attributes are chosen.", + ) diff --git a/pos_product_template/readme/CONTRIBUTORS.rst b/pos_product_template/readme/CONTRIBUTORS.rst new file mode 100644 index 0000000000..ae061bc591 --- /dev/null +++ b/pos_product_template/readme/CONTRIBUTORS.rst @@ -0,0 +1,20 @@ +* Sylvain LE GAL (https://twitter.com/legalsylvain) +* Navarromiguel (https://github.com/navarromiguel) +* Damendieta (https://github.com/damendieta) +* Raphaël Reverdy (https://akretion.com) +* Pedro Guirao (https://ingenieriacloud.com) + +* `Ooops `_: + + * Giovanni Serra + +* `Aures Tic `_: + + * Jose Zambudio + +Funders +------- + +The development of this module has been financially supported by: + +* Akretion diff --git a/pos_product_template/readme/DESCRIPTION.rst b/pos_product_template/readme/DESCRIPTION.rst new file mode 100644 index 0000000000..61b42e59a7 --- /dev/null +++ b/pos_product_template/readme/DESCRIPTION.rst @@ -0,0 +1,11 @@ + * In Point Of Sale Front End - Products list: + * Display only one product per template; + * Display template name instead of product name; + * Display products quantity instead of price; + * Click on template displays an extra screen to select Variant; + + * In Point Of Sale Front End - Variants list: + * Display all the products of the selected variant; + * Click on a attribute value filters products; + * Click on a product adds it to the current Order or display normal + extra screen if it is a weightable product; diff --git a/pos_product_template/readme/ROADMAP.rst b/pos_product_template/readme/ROADMAP.rst new file mode 100644 index 0000000000..1ac53b8f14 --- /dev/null +++ b/pos_product_template/readme/ROADMAP.rst @@ -0,0 +1 @@ +* Templates with lot of variants are not shown. See https://github.com/OCA/pos/pull/135 diff --git a/pos_product_template/readme/USAGE.rst b/pos_product_template/readme/USAGE.rst new file mode 100644 index 0000000000..313300eccf --- /dev/null +++ b/pos_product_template/readme/USAGE.rst @@ -0,0 +1,2 @@ +Open the Point of Sale, search an article with variants. +You will see one article instead of all the variants. diff --git a/pos_product_template/static/description/icon.png b/pos_product_template/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..4e54d92ab092f28d564edf3e8a8da4f9a5f3aee6 GIT binary patch literal 4290 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 literal 0 HcmV?d00001 diff --git a/pos_product_template/static/description/index.html b/pos_product_template/static/description/index.html new file mode 100644 index 0000000000..05a4b428ca --- /dev/null +++ b/pos_product_template/static/description/index.html @@ -0,0 +1,492 @@ + + + + + + +POS - Product Template + + + +
+

POS - Product Template

+ + +

Beta License: AGPL-3 OCA/pos Translate me on Weblate Try me on Runboat

+
+
    +
  • +
    In Point Of Sale Front End - Products list:
    +
      +
    • Display only one product per template;
    • +
    • Display template name instead of product name;
    • +
    • Display products quantity instead of price;
    • +
    • Click on template displays an extra screen to select Variant;
    • +
    +
    +
    +
  • +
  • +
    In Point Of Sale Front End - Variants list:
    +
      +
    • Display all the products of the selected variant;
    • +
    • Click on a attribute value filters products;
    • +
    • Click on a product adds it to the current Order or display normal +extra screen if it is a weightable product;
    • +
    +
    +
    +
  • +
+
+

Table of contents

+ +
+

Usage

+

Open the Point of Sale, search an article with variants. +You will see one article instead of all the variants.

+
+
+

Known issues / Roadmap

+ +
+
+

Bug Tracker

+

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

+

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

+
+
+

Credits

+
+

Authors

+
    +
  • Akretion
  • +
+
+
+

Contributors

+ +
+

Funders

+

The development of this module has been financially supported by:

+
    +
  • Akretion
  • +
+
+
+
+

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

+

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

+
+
+
+ + diff --git a/pos_product_template/static/src/css/ppt.css b/pos_product_template/static/src/css/ppt.css new file mode 100644 index 0000000000..c43605231e --- /dev/null +++ b/pos_product_template/static/src/css/ppt.css @@ -0,0 +1,84 @@ +/* ********* Variant Selector PopUp ************************************** */ +.pos .modal-dialog .select-variant-products { + display: flex; + flex-direction: row; + justify-content: center; + flex-wrap: wrap; + gap: 2px; +} + +.pos .modal-dialog .select-variant-products article { + font-size: 12px; +} + +/* ********* Attribut Display ******************************************** */ +.pos .attribute { + position: relative; + width: 100%; + vertical-align: top; + display: inline-block; +} + +.pos .attribute .attribute-name { + float: left; + font-size: 13px; + width: 20%; + overflow: hidden; +} + +.pos .attribute .value-list-container { + width: 78%; + float: left; +} + +.pos .attribute .selected { + background-color: white; +} + +.attributeValue.unavailable { + color: grey; +} + +.attributeValue.selected { + color: red; +} + +.pos .attribute .attribute-value { + float: left; + width: 150px; + padding-left: 15px; +} + +.pos .attribute .attribute-value .button { + width: 100%; +} + +.pos .attribute .attribute-value .attribute-value-header { + width: 100%; + height: 15px; + text-align: right; +} +.pos .attribute .attribute-value .attribute-value-name { + width: 100%; + height: 25px; + line-height: 25px; + overflow: hidden; + font-size: 10px; + text-align: left; + font-weight: normal; + padding: 2px; +} + +.pos .attribute .attribute-value .variant-quantity { + position: relative; + top: 2px; + right: 0px; + vertical-align: top; + color: #fff; + line-height: 13px; + background: none repeat scroll 0% 0% #7f82ac; + padding: 2px 5px; + border-radius: 2px; + font-size: 9px; + margin-right: 3px; +} diff --git a/pos_product_template/static/src/img/screenshots/pos_product_template.png b/pos_product_template/static/src/img/screenshots/pos_product_template.png new file mode 100644 index 0000000000000000000000000000000000000000..288053e0b4d652afb34718e56b08928d9895ed46 GIT binary patch literal 21421 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 literal 0 HcmV?d00001 diff --git a/pos_product_template/static/src/js/SelectVariantPopup.esm.js b/pos_product_template/static/src/js/SelectVariantPopup.esm.js new file mode 100644 index 0000000000..93c0809162 --- /dev/null +++ b/pos_product_template/static/src/js/SelectVariantPopup.esm.js @@ -0,0 +1,229 @@ +/** @odoo-module **/ +/* Copyright (C) 2020-Today Akretion (https://www.akretion.com) + @author Raphaël Reverdy (https://www.akretion.com) + License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). +*/ + +import AbstractAwaitablePopup from "point_of_sale.AbstractAwaitablePopup"; +import Registries from "point_of_sale.Registries"; +import {useListener} from "web.custom_hooks"; +const {useState} = owl.hooks; + +class SelectVariantPopup extends AbstractAwaitablePopup { + constructor(parent, props) { + super(parent, props); + var template = this.env.pos.db.get_template_by_id(props.template_id); + this.state = useState({ + ptav: [], + attributes: [], + template: template, + products: [], + ptav_id_selected: {}, + ptav_unavailable_ids: [], + all_attributes_chosen: false, + }); + + this._mountPopup(template); + } + + willUpdateProps(nextProp) { + var template = this.env.pos.db.get_template_by_id(nextProp.template_id); + this._mountPopup(template); + super.willUpdateProps(nextProp); + } + + _mountPopup(template) { + this.state.ptav = []; + this.state.attributes = []; + this.state.template = template; + this.state.products = []; + this.state.ptav_id_selected = {}; + + var ptav = Array.from( + new Set( + template.product_template_attribute_value_ids.map((x) => + this.env.pos.db.get_product_template_attribute_value_by_id(x) + ) + ) + ); + + var attributes_by_id = {}; + ptav.forEach((x) => { + var id = x.attribute_id[0]; + var value_id = x.product_attribute_value_id[0]; + attributes_by_id[id] = attributes_by_id[id] || { + attribute: x.attribute_id, + values_id: {}, + ptav: {}, + }; + attributes_by_id[id].values_id[value_id] = true; + attributes_by_id[id].ptav[x.id] = x; + }); + var attributes = Object.values(attributes_by_id).map((x) => { + x.ptav = Object.values(x.ptav); + x.id = x.attribute[0]; + x.name = x.attribute[1]; + return x; + }); + this.all_ptav_id = ptav.map((x) => x.id); + this.all_ptav = {}; + + ptav.forEach((x) => (this.all_ptav[x.id] = x)); + + var products = this.refreshProducts(); + useListener("click-product", this._clickProduct); + useListener("click-attribute-value", this._clickAttributeValue); + + attributes.forEach((attribute) => { + const productAttribute = + this.env.pos.db.product_attribute_by_id[attribute.id]; + attribute.sequence = productAttribute.sequence; + }); + + this.state.ptav = ptav; + this.state.ptav_unavailable_ids = []; + this.state.attributes = attributes.sort((a, b) => + a.sequence > b.sequence ? 1 : b.sequence > a.sequence ? -1 : 0 + ); + this.state.products = products; + } + + async _clickProduct(event) { + this.product_selected = event.detail; + return this.confirm(); + } + async _clickAttributeValue(event) { + var value_id = event.detail.id; + // Init + var ptav = this.state.ptav_id_selected; + ptav[value_id] = ptav[value_id] || false; + // Toggle + ptav[value_id] = !ptav[value_id]; + + var avat = {}; + var attributes_stringify = JSON.parse(JSON.stringify(this.state.attributes)); + _.each(attributes_stringify, function (at) { + _.each(at.ptav, function (av) { + avat[av.id] = at.id; + }); + }); + + var ptav_stringify = JSON.parse(JSON.stringify(this.state.ptav_id_selected)); + _.each(Object.keys(ptav_stringify), function (ptav_s) { + if (parseInt(ptav_s, 10) !== value_id && avat[ptav_s] === avat[value_id]) { + ptav[ptav_s] = false; + } + }); + + this.state.products = this.refreshProducts(); + var self = this; + var selected_ptav_ids = Object.keys(self.state.ptav_id_selected).filter( + (x) => self.state.ptav_id_selected[x] + ); + this.state.ptav_unavailable_ids = this.state.ptav + .filter(function (value) { + // Remove ptav if no available product corresponds + var res = self.state.products.every(function (product) { + return ( + value.ptav_product_variant_ids.includes(product.id) === false + ); + }); + if (res === true) { + // Do not remove ptav if there is already a ptav chosen for the + // attribute and there are products if changed + // This allows to show the possible modifications of choices + selected_ptav_ids.forEach(function (selected_ptav_id) { + const selected_ptav = self.all_ptav[selected_ptav_id]; + if (value.attribute_id[0] === selected_ptav.attribute_id[0]) { + const selected_ptav_test_list = selected_ptav_ids.filter( + function (id) { + // Test if ptav is available if this ptav is not selected + return id !== selected_ptav_id; + } + ); + const product_ids = Array.from( + self._get_product_ids_for_ptav(selected_ptav_test_list) + ); + res = product_ids.every(function (product_id) { + return ( + value.ptav_product_variant_ids.includes( + product_id + ) === false + ); + }); + } + }); + } + return res; + }) + .map(function (value) { + return value.id; + }); + this.state.all_attributes_chosen = + selected_ptav_ids.length === this.state.attributes.length && + this.state.products.length === 1; + } + async click_confirm() { + if (this.state.all_attributes_chosen !== true) { + throw new Error( + "You can only confirm when all attributes are chosen and there is a variant available" + ); + } + this.product_selected = this.state.products[0]; + return this.confirm(); + } + async getPayload() { + return this.product_selected; + } + _get_product_ids_for_ptav(ptav_list) { + function intersection(setA, setB) { + var elements = new Set(); + for (var elem of setB) { + if (setA.has(elem)) { + elements.add(elem); + } + } + return elements; + } + + function union(setA, setB) { + var elements = new Set(setA); + for (var elem of setB) { + elements.add(elem); + } + return elements; + } + let variants_ids = []; + + if (ptav_list.length === 0) { + variants_ids = this.all_ptav_id + .map((ptav) => { + return new Set(this.all_ptav[ptav].ptav_product_variant_ids); + }) + .reduce((a, b) => { + return union(a, b); + }); + } else { + variants_ids = ptav_list + .map((ptav) => { + return new Set(this.all_ptav[ptav].ptav_product_variant_ids); + }) + .reduce((a, b) => { + return intersection(a, b); + }); + } + return variants_ids; + } + refreshProducts() { + var ptav = Object.keys(this.state.ptav_id_selected).filter( + (x) => this.state.ptav_id_selected[x] + ); + var variants_ids = this._get_product_ids_for_ptav(ptav); + return Array.from(variants_ids).map((x) => { + return this.env.pos.db.get_product_by_id(x); + }); + } +} +Registries.Component.add(SelectVariantPopup); +SelectVariantPopup.template = "SelectVariantPopup"; +export default SelectVariantPopup; diff --git a/pos_product_template/static/src/js/models.esm.js b/pos_product_template/static/src/js/models.esm.js new file mode 100644 index 0000000000..6740cb2c74 --- /dev/null +++ b/pos_product_template/static/src/js/models.esm.js @@ -0,0 +1,191 @@ +/** @odoo-module **/ +/* Copyright (C) 2014-Today Akretion (https://www.akretion.com) + @author Sylvain LE GAL (https://twitter.com/legalsylvain) + @author Navarromiguel (https://github.com/navarromiguel) + @author Raphaël Reverdy (https://www.akretion.com) + License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). +*/ + +import PosDB from "point_of_sale.DB"; +import models from "point_of_sale.models"; + +models.PosModel.prototype.models.some(function (model) { + if (model.model !== "product.product") { + return false; + } + // Add name and product_template_attribute_value_ids to list of fields + // to fetch for product.product + ["name", "product_template_attribute_value_ids"].forEach(function (field) { + if (model.fields.indexOf(field) === -1) { + model.fields.push(field); + } + }); + // Exit early the iteration of this.models + return true; +}); + +// Add our new models +models.load_models([ + { + model: "product.template", + fields: [ + "name", + "display_name", + "product_variant_ids", + "product_variant_count", + ], + domain: function () { + return [ + ["sale_ok", "=", true], + ["available_in_pos", "=", true], + ]; + }, + context: function (self) { + return { + pricelist: self.pricelists[0].id, + display_default_code: false, + }; + }, + loaded: function (self, templates) { + // If pos_cache + if (Object.keys(self.db.product_by_id).length > 0) { + self.db.add_templates(templates); + } else { + self.db.raw_templates = templates; + } + }, + }, + { + model: "product.attribute", + fields: ["name", "value_ids", "sequence"], + loaded: function (self, attributes) { + self.db.add_product_attributes(attributes); + }, + }, + { + model: "product.attribute.value", + fields: ["name", "attribute_id"], + loaded: function (self, values) { + self.db.add_product_attribute_values(values); + }, + }, + { + model: "product.template.attribute.value", + fields: [ + "name", + "attribute_id", + "product_tmpl_id", + "product_attribute_value_id", + "ptav_product_variant_ids", + ], + domain: function () { + return [["product_tmpl_id.available_in_pos", "=", true]]; + }, + loaded: function (self, values) { + self.db.add_product_template_attribute_values(values); + }, + }, +]); + +PosDB.include({ + // The maximum number of results returned by a search + product_search_limit: 314159265, + product_display_limit: 10, + // Can't change limit because it's also used in partner search + init: function (options) { + this.template_by_id = {}; + this.product_attribute_by_id = {}; + this.product_attribute_value_by_id = {}; + this.product_template_attribute_value_by_id = {}; + this._super(options); + }, + get_product_by_category: function (category_id) { + // Change the limit only the time of the search + this.product_display_limit = this.limit; + this.limit = this.product_search_limit; + var res = this._super(category_id); + this.limit = this.product_display_limit; + return res; + }, + search_product_in_category: function (category_id, query) { + // Change the limit only the time of the search + this.product_display_limit = this.limit; + this.limit = this.product_search_limit; + var res = this._super(category_id, query); + this.limit = this.product_display_limit; + return res; + }, + add_products: function (products) { + this._super(products); + // If pos_cache is also installed - then products are not available when product.templates are already loaded + // so we have to re add them here + if (this.raw_templates) { + this.add_templates(this.raw_templates); + } + }, + + get_product_template_attribute_value_by_id: function (tmpl_attribute_value_id) { + return this.product_template_attribute_value_by_id[tmpl_attribute_value_id]; + }, + + get_template_by_id: function (id) { + return this.template_by_id[id]; + }, + add_templates: function (templates) { + templates.forEach((template) => { + var product_template_attribute_value_ids = []; + // Store Templates + this.template_by_id[template.id] = template; + + // Update Product information + var tmpl_attribute_value_ids = new Set(); + template.product_variant_ids.forEach((variant_id) => { + var variant = this.get_product_by_id(variant_id); + if ( + variant !== undefined && + variant.product_template_attribute_value_ids + ) { + variant.product_template_attribute_value_ids.forEach( + (tmpl_attr_value_id) => { + tmpl_attribute_value_ids.add( + this.get_product_template_attribute_value_by_id( + tmpl_attr_value_id + ) + ); + + // Add ptav + product_template_attribute_value_ids.push( + tmpl_attr_value_id + ); + } + ); + variant.product_variant_count = template.product_variant_count; + variant.template = template; + } + }); + + template.product_template_attribute_value_ids = + product_template_attribute_value_ids; + }); + }, + + add_product_attributes: function (product_attributes) { + product_attributes.forEach((product_attribute) => { + this.product_attribute_by_id[product_attribute.id] = product_attribute; + }); + }, + + add_product_attribute_values: function (product_attribute_values) { + product_attribute_values.forEach((attribute_value) => { + this.product_attribute_value_by_id[attribute_value.id] = attribute_value; + }); + }, + add_product_template_attribute_values: function ( + product_template_attribute_values + ) { + product_template_attribute_values.forEach((attribute_value) => { + this.product_template_attribute_value_by_id[attribute_value.id] = + attribute_value; + }); + }, +}); diff --git a/pos_product_template/static/src/js/ppt.esm.js b/pos_product_template/static/src/js/ppt.esm.js new file mode 100644 index 0000000000..3a9007851f --- /dev/null +++ b/pos_product_template/static/src/js/ppt.esm.js @@ -0,0 +1,101 @@ +/** @odoo-module **/ +/* Copyright (C) 2014-Today Akretion (https://www.akretion.com) + @author Sylvain LE GAL (https://twitter.com/legalsylvain) + @author Navarromiguel (https://github.com/navarromiguel) + @author Raphaël Reverdy (https://www.akretion.com) + License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). +*/ + +import PosComponent from "point_of_sale.PosComponent"; +import ProductItem from "point_of_sale.ProductItem"; +import ProductScreen from "point_of_sale.ProductScreen"; +import ProductsWidget from "point_of_sale.ProductsWidget"; +import Registries from "point_of_sale.Registries"; +import {useListener} from "web.custom_hooks"; + +/* ******************************************************** + Overload: point_of_sale.ProductListWidget + + - The overload will: + - display only product template; + - Add an extra behaviour on click on a template, if template has many + variant, displaying an extra scren to select the variant; + *********************************************************** */ + +const PPTProductScreen = (ProductScreen) => + class extends ProductScreen { + constructor(parent, props) { + super(parent, props); + useListener("click-product-template", this._clickProductTemplate); + } + async _clickProductTemplate(event) { + // Display our select-variant popup when needed + // chain call to clickProduct + var product = event.detail; + var ret = await this.showPopup("SelectVariantPopup", { + template_id: product.product_tmpl_id, + }); + if (ret.confirmed && ret.payload) + return this._clickProduct({detail: ret.payload}); + } + }; + +const PPTProductsWidget = (ProductsWidget) => + class extends ProductsWidget { + get productsToDisplay() { + var tmpl_seen = []; + var res = super.productsToDisplay + .filter(function (product) { + if (tmpl_seen.indexOf(product.product_tmpl_id) === -1) { + // First time we see it, display it + tmpl_seen.push(product.product_tmpl_id); + return true; + } + return false; + }) + .slice(0, this.env.pos.db.product_display_limit); + return res; + } + }; + +const PPTProductItem = (ProductItem) => + class extends ProductItem { + constructor(parent, props) { + // Reuse ProductItem but change only + // the template for product.template + super(parent, props); + if (props.forceVariant) { + // In order to not recurse indefinitly + } else if (props.product.product_variant_count > 1) { + var qweb = this.env.qweb; + this.__owl__.renderFn = qweb.render.bind(qweb, "ProductTemplateItem"); + } + } + get imageTmpUrl() { + const product = this.props.product; + return `/web/image?model=product.template&field=image_128&id=${product.template.id}&write_date=${product.write_date}&unique=1`; + } + }; + +class AttributeValueItem extends PosComponent { + spaceClickProduct(event) { + if (event.which === 32) { + this.trigger("click-product", this.props.product); + } + } +} + +AttributeValueItem.template = "AttributeValueItem"; + +Registries.Component.add(AttributeValueItem); + +Registries.Component.extend(ProductScreen, PPTProductScreen); +Registries.Component.extend(ProductItem, PPTProductItem); +Registries.Component.extend(ProductsWidget, PPTProductsWidget); + +export default { + PPTProductScreen: PPTProductScreen, + PPTProductItem: PPTProductItem, + PPTProductsWidget: PPTProductsWidget, + AttributeValueItem: AttributeValueItem, +}; diff --git a/pos_product_template/static/src/xml/SelectVariantPopup.xml b/pos_product_template/static/src/xml/SelectVariantPopup.xml new file mode 100644 index 0000000000..ad2c7beac4 --- /dev/null +++ b/pos_product_template/static/src/xml/SelectVariantPopup.xml @@ -0,0 +1,78 @@ + + + diff --git a/pos_product_template/static/src/xml/ppt.xml b/pos_product_template/static/src/xml/ppt.xml new file mode 100644 index 0000000000..4c044d037f --- /dev/null +++ b/pos_product_template/static/src/xml/ppt.xml @@ -0,0 +1,53 @@ + + + diff --git a/pos_product_template/views/pos_config_view.xml b/pos_product_template/views/pos_config_view.xml new file mode 100644 index 0000000000..5b6fe71f5b --- /dev/null +++ b/pos_product_template/views/pos_config_view.xml @@ -0,0 +1,13 @@ + + + + pos.config.form.view + pos.config + + + + + + + +