Wolfgang Pichler
4 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 1283 additions and 0 deletions
-
91pos_product_template/README.rst
-
20pos_product_template/__init__.py
-
27pos_product_template/__manifest__.py
-
31pos_product_template/demo/product_attribute_value.xml
-
45pos_product_template/demo/product_product.xml
-
44pos_product_template/i18n/es.po
-
44pos_product_template/i18n/fr.po
-
42pos_product_template/i18n/pos_product_template.pot
-
6pos_product_template/readme/CONTRIBUTORS.rst
-
3pos_product_template/readme/CREDITS.rst
-
11pos_product_template/readme/DESCRIPTION.rst
-
1pos_product_template/readme/ROADMAP.rst
-
8pos_product_template/readme/USAGE.rst
-
BINpos_product_template/static/description/icon.png
-
202pos_product_template/static/src/css/ppt.css
-
BINpos_product_template/static/src/img/screenshots/pos_product_template.png
-
575pos_product_template/static/src/js/ppt.js
-
119pos_product_template/static/src/xml/ppt.xml
-
14pos_product_template/view/view.xml
@ -0,0 +1,91 @@ |
|||
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.png |
|||
:target: https://www.gnu.org/licenses/agpl |
|||
:alt: License: AGPL-3 |
|||
|
|||
==================== |
|||
POS Product Template |
|||
==================== |
|||
|
|||
|
|||
* 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; |
|||
|
|||
|
|||
Usage |
|||
===== |
|||
|
|||
Open the Point of Sale, search an article with variants. |
|||
You will see one article instead of all the variants. |
|||
|
|||
#. Go to ... |
|||
|
|||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas |
|||
:alt: Try me on Runbot |
|||
:target: https://runbot.odoo-community.org/runbot/pos/11.0 |
|||
|
|||
|
|||
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 |
|||
<https://github.com/OCA/pos/issues>`_. In case of trouble, please |
|||
check there if your issue has already been reported. If you spotted it first, |
|||
help us smash it by providing detailed and welcomed feedback. |
|||
|
|||
Credits |
|||
======= |
|||
|
|||
Images |
|||
------ |
|||
|
|||
* Odoo Community Association: `Icon <https://odoo-community.org/logo.png>`_. |
|||
|
|||
Contributors |
|||
------------ |
|||
|
|||
* Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
* Navarromiguel (https://github.com/navarromiguel) |
|||
* Damendieta (https://github.com/damendieta) |
|||
* Raphaël Reverdy (https://akretion.com) |
|||
* Hugo Santos (https://factorlibre.com) |
|||
|
|||
|
|||
Do not contact contributors directly about support or help with technical issues. |
|||
|
|||
Funders |
|||
------- |
|||
|
|||
The development of this module has been financially supported by: |
|||
|
|||
* Akretion |
|||
|
|||
|
|||
Maintainer |
|||
---------- |
|||
|
|||
.. image:: https://odoo-community.org/logo.png |
|||
:alt: Odoo Community Association |
|||
:target: https://odoo-community.org |
|||
|
|||
This module is maintained by the OCA. |
|||
|
|||
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. |
|||
|
|||
To contribute to this module, please visit https://odoo-community.org. |
@ -0,0 +1,20 @@ |
|||
############################################################################## |
|||
# |
|||
# Point Of Sale - Product Template module for Odoo |
|||
# Copyright (C) 2014-Today Akretion (http://www.akretion.com) |
|||
# @author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
@ -0,0 +1,27 @@ |
|||
{ |
|||
'name': 'POS - Product Template', |
|||
'version': '12.0.1.0.0', |
|||
'category': 'Point Of Sale', |
|||
'author': "Akretion,Odoo Community Association (OCA)", |
|||
'summary': 'Manage Product Template in Front End Point Of Sale', |
|||
'website': 'http://www.akretion.com', |
|||
'license': 'AGPL-3', |
|||
'depends': [ |
|||
'point_of_sale', |
|||
'pos_fix_search_limit', |
|||
], |
|||
'data': [ |
|||
'view/view.xml', |
|||
], |
|||
'qweb': [ |
|||
'static/src/xml/ppt.xml', |
|||
], |
|||
'demo': [ |
|||
'demo/product_attribute_value.xml', |
|||
'demo/product_product.xml', |
|||
], |
|||
'images': [ |
|||
'static/src/img/screenshots/pos_product_template.png', |
|||
], |
|||
'installable': True, |
|||
} |
@ -0,0 +1,31 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- |
|||
############################################################################## |
|||
# |
|||
# Point Of Sale - Product Template module for Odoo |
|||
# Copyright (C) 2014-Today Akretion (http://www.akretion.com) |
|||
# @author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
--> |
|||
<odoo> |
|||
|
|||
<record id="attribute_wifi_extra" model="product.attribute.value"> |
|||
<field name="attribute_id" eval="ref('product.product_attribute_3')"/> |
|||
<field name="name">2.399GHz</field> |
|||
</record> |
|||
|
|||
</odoo> |
@ -0,0 +1,45 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- |
|||
############################################################################## |
|||
# |
|||
# Point Of Sale - Product Template module for Odoo |
|||
# Copyright (C) 2014-Today Akretion (http://www.akretion.com) |
|||
# @author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
# |
|||
# This program is free software: you can redistribute it and/or modify |
|||
# it under the terms of the GNU Affero General Public License as |
|||
# published by the Free Software Foundation, either version 3 of the |
|||
# License, or (at your option) any later version. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU Affero General Public License for more details. |
|||
# |
|||
# You should have received a copy of the GNU Affero General Public License |
|||
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
--> |
|||
<odoo> |
|||
|
|||
<record id="product.product_product_4" model="product.product"> |
|||
<field name="available_in_pos" eval="True"/> |
|||
</record> |
|||
|
|||
<record id="product.product_product_4b" model="product.product"> |
|||
<field name="available_in_pos" eval="True"/> |
|||
</record> |
|||
|
|||
<record id="product.product_product_4c" model="product.product"> |
|||
<field name="available_in_pos" eval="True"/> |
|||
</record> |
|||
|
|||
<record id="product.product_product_11" model="product.product"> |
|||
<field name="available_in_pos" eval="True"/> |
|||
</record> |
|||
|
|||
<record id="product.product_product_11b" model="product.product"> |
|||
<field name="available_in_pos" eval="True"/> |
|||
</record> |
|||
</odoo> |
@ -0,0 +1,44 @@ |
|||
# 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: 2014-12-18 12:01+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/ppt.xml:13 |
|||
#, python-format |
|||
msgid "Cancel" |
|||
msgstr "Cancelar" |
|||
|
|||
#. module: pos_product_template |
|||
#. openerp-web |
|||
#: code:addons/pos_product_template/static/src/xml/ppt.xml:11 |
|||
#, python-format |
|||
msgid "Variant Selection of" |
|||
msgstr "Seleccina una variante de" |
|||
|
|||
#. module: pos_product_template |
|||
#. openerp-web |
|||
#: code:addons/pos_product_template/static/src/xml/ppt.xml:39 |
|||
#: code:addons/pos_product_template/static/src/xml/ppt.xml:77 |
|||
#, python-format |
|||
msgid "Variants" |
|||
msgstr "Variantes" |
@ -0,0 +1,44 @@ |
|||
# 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/ppt.xml:13 |
|||
#, python-format |
|||
msgid "Cancel" |
|||
msgstr "Annuler" |
|||
|
|||
#. module: pos_product_template |
|||
#. openerp-web |
|||
#: code:addons/pos_product_template/static/src/xml/ppt.xml:11 |
|||
#, python-format |
|||
msgid "Variant Selection of" |
|||
msgstr "Sélection d'une variante de" |
|||
|
|||
#. module: pos_product_template |
|||
#. openerp-web |
|||
#: code:addons/pos_product_template/static/src/xml/ppt.xml:39 |
|||
#: code:addons/pos_product_template/static/src/xml/ppt.xml:77 |
|||
#, python-format |
|||
msgid "Variants" |
|||
msgstr "Variantes" |
@ -0,0 +1,42 @@ |
|||
# Translation of Odoo Server. |
|||
# This file contains the translation of the following modules: |
|||
# * pos_product_template |
|||
# |
|||
msgid "" |
|||
msgstr "" |
|||
"Project-Id-Version: Odoo Server 10.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/ppt.xml:13 |
|||
#, python-format |
|||
msgid "Cancel" |
|||
msgstr "" |
|||
|
|||
#. module: pos_product_template |
|||
#. openerp-web |
|||
#: code:addons/pos_product_template/static/src/xml/ppt.xml:11 |
|||
#, python-format |
|||
msgid "Variant Selection of" |
|||
msgstr "" |
|||
|
|||
#. module: pos_product_template |
|||
#. openerp-web |
|||
#: code:addons/pos_product_template/static/src/xml/ppt.xml:39 |
|||
#: code:addons/pos_product_template/static/src/xml/ppt.xml:77 |
|||
#, python-format |
|||
msgid "Variants" |
|||
msgstr "" |
|||
|
@ -0,0 +1,6 @@ |
|||
* Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
* Navarromiguel (https://github.com/navarromiguel) |
|||
* Damendieta (https://github.com/damendieta) |
|||
* Raphaël Reverdy (https://akretion.com) |
|||
* Hugo Santos (https://factorlibre.com) |
|||
* Wolfgang Pichler (https://www.callino.at) |
@ -0,0 +1,3 @@ |
|||
The development of this module has been financially supported by: |
|||
|
|||
* Akretion |
@ -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; |
@ -0,0 +1 @@ |
|||
* Templates with lot of variants are not shown. See https://github.com/OCA/pos/pull/135 |
@ -0,0 +1,8 @@ |
|||
Open the Point of Sale, search an article with variants. |
|||
You will see one article instead of all the variants. |
|||
|
|||
#. Go to ... |
|||
|
|||
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas |
|||
:alt: Try me on Runbot |
|||
:target: https://runbot.odoo-community.org/runbot/pos/12.0 |
After Width: 64 | Height: 64 | Size: 4.2 KiB |
@ -0,0 +1,202 @@ |
|||
/****************************************************************************** |
|||
Point Of Sale - Product Template module for Odoo |
|||
Copyright (C) 2014-Today Akretion (http://www.akretion.com) |
|||
@author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
|
|||
Some part of code from Odoo Project, |
|||
Copyright (C) 2004-Today Odoo SA. (<http://odoo.com>). |
|||
|
|||
This program is free software: you can redistribute it and/or modify |
|||
it under the terms of the GNU Affero General Public License as |
|||
published by the Free Software Foundation, either version 3 of the |
|||
License, or (at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU Affero General Public License for more details. |
|||
|
|||
You should have received a copy of the GNU Affero General Public License |
|||
along with this program. If not, see <http://www.gnu.org/licenses/>. |
|||
******************************************************************************/ |
|||
|
|||
/* ********* Variant Selector PopUp ************************************** */ |
|||
.pos .modal-dialog .popup-select-variant{ |
|||
margin-left:0; |
|||
margin-top:0; |
|||
left:5%; |
|||
width: 90%; |
|||
top:5%; |
|||
height:85%; |
|||
} |
|||
|
|||
.pos .modal-dialog .popup-select-variant .variant-title{ |
|||
height: 8%; |
|||
} |
|||
|
|||
.pos .modal-dialog .popup-select-variant .container-attribute-list{ |
|||
width:100%; |
|||
height:40%; |
|||
overflow: hidden; |
|||
overflow-y: auto; |
|||
border-bottom: 1px dashed #444; |
|||
-webkit-overflow-scrolling: touch; |
|||
} |
|||
|
|||
.pos .modal-dialog .popup-select-variant .container-variant-list{ |
|||
width:100%; |
|||
height:50%; |
|||
overflow: hidden; |
|||
overflow-y: auto; |
|||
|
|||
-webkit-overflow-scrolling: touch; |
|||
} |
|||
|
|||
.pos .variant-list { |
|||
padding: 10px; |
|||
text-align: left; |
|||
-webkit-transform: translate3d(0,0,0); |
|||
} |
|||
|
|||
/* ********* 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; |
|||
} |
|||
|
|||
.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; |
|||
} |
|||
|
|||
|
|||
/* ********* Variant Display ********************************************* */ |
|||
/* This part is a copy paste from Odoo Project, with some values changed */ |
|||
.pos .variant { |
|||
position:relative; |
|||
vertical-align: top; |
|||
display: inline-block; |
|||
line-height: 100px; |
|||
font-size: 11px; |
|||
margin: 5px !important; |
|||
width: 240px; |
|||
height:60px; |
|||
background:#fff; |
|||
border: 1px solid #e2e2e2; |
|||
border-radius: 3px; |
|||
border-bottom-width: 3px; |
|||
overflow: hidden; |
|||
cursor: pointer; |
|||
} |
|||
|
|||
.pos .variant .variant-header { |
|||
position: relative; |
|||
width: 240px; |
|||
height: 30px; |
|||
background: white; |
|||
text-align: center; |
|||
} |
|||
|
|||
.pos .variant .price-tag { |
|||
position: absolute; |
|||
top: 2px; |
|||
right: 2px; |
|||
vertical-align: top; |
|||
color: white; |
|||
line-height: 13px; |
|||
background: #7f82ac; |
|||
padding: 2px 5px; |
|||
border-radius: 2px; |
|||
} |
|||
|
|||
.pos .variant .variant-name { |
|||
font-weight: normal; |
|||
position: absolute; |
|||
-webkit-box-sizing: border-box; |
|||
-moz-box-sizing: border-box; |
|||
-ms-box-sizing: border-box; |
|||
box-sizing: border-box; |
|||
bottom:0; |
|||
top:auto; |
|||
line-height: 14px; |
|||
width:100%; |
|||
overflow: hidden; |
|||
text-overflow: ellipsis; |
|||
background: -webkit-linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1)); |
|||
background: -moz-linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1)); |
|||
background: -ms-linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1)); |
|||
/* troublesome in latest webkit |
|||
background: linear-gradient(-90deg,rgba(255,255,255,0),rgba(255,255,255,1), rgba(255,255,255,1)); |
|||
*/ |
|||
/*background:#FFF;*/ |
|||
padding: 3px; |
|||
padding-top:15px; |
|||
} |
|||
|
|||
/*.pos .variant-list-scroller{*/ |
|||
/* -webkit-box-sizing: border-box;*/ |
|||
/* -moz-box-sizing: border-box;*/ |
|||
/* -ms-box-sizing: border-box;*/ |
|||
/* box-sizing: border-box;*/ |
|||
/* width:50%;*/ |
|||
/* height:50%;*/ |
|||
/* overflow: hidden;*/ |
|||
/* overflow-y: auto;*/ |
|||
/* -webkit-overflow-scrolling: touch;*/ |
|||
/* -webkit-transform: translate3d(0,0,0);*/ |
|||
|
|||
/*}*/ |
After Width: 1212 | Height: 383 | Size: 21 KiB |
@ -0,0 +1,575 @@ |
|||
/* 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).
|
|||
*/ |
|||
|
|||
odoo.define("pos_product_template.pos_product_template", function(require){ |
|||
"use strict"; |
|||
|
|||
var screens = require("point_of_sale.screens"); |
|||
var popups = require("point_of_sale.popups"); |
|||
var models = require('point_of_sale.models'); |
|||
var chrome = require('point_of_sale.chrome'); |
|||
var gui = require('point_of_sale.gui'); |
|||
var PosDB = require("point_of_sale.DB"); |
|||
var PosBaseWidget = require('point_of_sale.BaseWidget'); |
|||
|
|||
var core = require('web.core'); |
|||
var utils = require('web.utils'); |
|||
|
|||
var QWeb = core.qweb; |
|||
var _t = core._t; |
|||
|
|||
/* ******************************************************** |
|||
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; |
|||
*********************************************************** */ |
|||
var _render_product_ = screens.ProductListWidget.prototype.render_product; |
|||
|
|||
screens.ProductScreenWidget.include({ |
|||
click_product: function(product) { |
|||
if (product.product_variant_count > 1) { |
|||
this.gui.show_popup('select-variant-popup', product.product_tmpl_id); |
|||
} else { |
|||
this._super(product); |
|||
} |
|||
} |
|||
}); |
|||
screens.ProductListWidget.include({ |
|||
|
|||
set_product_list: function(product_list) { |
|||
/* ************************************************ |
|||
Overload: 'set_product_list' |
|||
|
|||
'set_product_list' is a function called before displaying Products. |
|||
(at the beginning, after a category selection, after a research, etc. |
|||
we just remove all products that are not the 'primary variant' |
|||
*/ |
|||
var list = product_list.filter(function(product) { |
|||
return product.is_primary_variant; |
|||
}); |
|||
this._super(list); |
|||
}, |
|||
|
|||
render_product: function(product){ |
|||
var self = this; |
|||
|
|||
if (product.product_variant_count === 1){ |
|||
// Normal Display
|
|||
return this._super(product); |
|||
} |
|||
if (!product.is_primary_variant) { |
|||
//because screens.js:556: renderElement is called
|
|||
//once before set_product_list
|
|||
//So we get product.is_primary_variant
|
|||
//which are not to be displayed
|
|||
//
|
|||
//Here we return mock element for
|
|||
//products which will not be displayed
|
|||
return document.createElement('div'); |
|||
} |
|||
//TODO reuse upper function
|
|||
var cached = this.product_cache.get_node(product.id); |
|||
if(!cached) { |
|||
var image_url = this.get_product_image_url(product); |
|||
var product_html = QWeb.render('Template',{ |
|||
widget: this, |
|||
product: product, |
|||
image_url: this.get_product_image_url(product), |
|||
}); |
|||
var product_node = document.createElement('div'); |
|||
product_node.innerHTML = product_html; |
|||
product_node = product_node.childNodes[1]; |
|||
this.product_cache.cache_node(product.id,product_node); |
|||
return product_node; |
|||
} |
|||
return cached; |
|||
}, |
|||
}); |
|||
|
|||
/* ******************************************************** |
|||
Overload: point_of_sale.PosWidget |
|||
|
|||
- Add a new PopUp 'SelectVariantPopupWidget'; |
|||
************************************************************/ |
|||
chrome.Chrome.include({ |
|||
/* Overload Section */ |
|||
build_widgets: function(){ |
|||
this._super(); |
|||
this.select_variant_popup = new SelectVariantPopupWidget(this, {}); |
|||
this.select_variant_popup.appendTo($(this.$el)); |
|||
|
|||
// Hide the popup because all pop up are displayed at the
|
|||
// beginning by default
|
|||
this.select_variant_popup.hide(); |
|||
}, |
|||
}); |
|||
|
|||
/* ******************************************************** |
|||
Define : pos_product_template.SelectVariantPopupWidget |
|||
|
|||
- This widget that display a pop up to select a variant of a Template; |
|||
***********************************************************/ |
|||
var SelectVariantPopupWidget = popups.extend({ |
|||
template:'SelectVariantPopupWidget', |
|||
|
|||
start: function(){ |
|||
var self = this; |
|||
// Define Variant Widget
|
|||
this.variant_list_widget = new VariantListWidget(this,{}); |
|||
this.variant_list_widget.replace(this.$('.placeholder-VariantListWidget')); |
|||
|
|||
// Define Attribute Widget
|
|||
this.attribute_list_widget = new AttributeListWidget(this,{}); |
|||
this.attribute_list_widget.replace(this.$('.placeholder-AttributeListWidget')); |
|||
|
|||
// Add behaviour on Cancel Button
|
|||
this.$('#variant-popup-cancel').off('click').click(function(){ |
|||
self.hide(); |
|||
}); |
|||
}, |
|||
|
|||
show: function(product_tmpl_id){ |
|||
var self = this; |
|||
var template = this.pos.db.template_by_id[product_tmpl_id]; |
|||
|
|||
// Display Name of Template
|
|||
this.$('#variant-title-name').html(template.name); |
|||
|
|||
// Render Variants
|
|||
var variant_ids = this.pos.db.template_by_id[product_tmpl_id].product_variant_ids; |
|||
var variant_list = variant_ids.map(function (variant) { |
|||
return this.pos.db.get_product_by_id(variant); |
|||
}, this); |
|||
this.variant_list_widget.filters = {} |
|||
this.variant_list_widget.set_variant_list(variant_list); |
|||
|
|||
// Render Attributes
|
|||
var attribute_ids = this.pos.db.attribute_by_template_id(template.id); |
|||
var attribute_list = attribute_ids.map(function (attribute) { |
|||
return this.pos.db.get_product_attribute_by_id(attribute); |
|||
}, this); |
|||
this.attribute_list_widget.set_attribute_list(attribute_list, template); |
|||
|
|||
if(this.$el){ |
|||
this.$el.removeClass('oe_hidden'); |
|||
} |
|||
}, |
|||
}); |
|||
gui.define_popup({name:'select-variant-popup', widget: SelectVariantPopupWidget}); |
|||
|
|||
/* ******************************************************** |
|||
Define: pos_product_template.VariantListWidget |
|||
|
|||
- This widget will display a list of Variants; |
|||
- This widget has some part of code that come from point_of_sale.ProductListWidget; |
|||
***********************************************************/ |
|||
var VariantListWidget = PosBaseWidget.extend({ |
|||
template:'VariantListWidget', |
|||
|
|||
init: function(parent, options) { |
|||
var self = this; |
|||
this._super(parent, options); |
|||
this.variant_list = []; |
|||
this.filter_variant_list = []; |
|||
this.filters = {}; |
|||
this.click_variant_handler = function(event){ |
|||
var variant = self.pos.db.get_product_by_id(this.dataset['variantId']); |
|||
if(variant.to_weight && self.pos.config.iface_electronic_scale){ |
|||
self.__parentedParent.hide(); |
|||
self.pos_widget.screen_selector.set_current_screen('scale',{product: variant}); |
|||
}else{ |
|||
self.__parentedParent.hide(); |
|||
self.pos.get('selectedOrder').add_product(variant); |
|||
} |
|||
}; |
|||
}, |
|||
|
|||
replace: function($target){ |
|||
this.renderElement(); |
|||
var target = $target[0]; |
|||
target.parentNode.replaceChild(this.el,target); |
|||
}, |
|||
|
|||
set_filter: function(attribute_id, value_id){ |
|||
this.filters[attribute_id] = value_id; |
|||
this.filter_variant(); |
|||
}, |
|||
|
|||
reset_filter: function(attribute_id){ |
|||
if (attribute_id in this.filters){ |
|||
delete this.filters[attribute_id]; |
|||
} |
|||
this.filter_variant(); |
|||
}, |
|||
|
|||
filter_variant: function(){ |
|||
var value_list = []; |
|||
for (var item in this.filters){ |
|||
value_list.push(parseInt(this.filters[item], 10)); |
|||
} |
|||
this.filter_variant_list = []; |
|||
for (var index in this.variant_list){ |
|||
var variant = this.variant_list[index]; |
|||
var found = true; |
|||
for (var i = 0; i < value_list.length; i++){ |
|||
found = found && (variant.attribute_value_ids.indexOf(value_list[i]) !== -1); |
|||
} |
|||
if (found){ |
|||
this.filter_variant_list.push(variant); |
|||
} |
|||
} |
|||
this.renderElement(); |
|||
}, |
|||
|
|||
_get_active_pricelist: function(){ |
|||
var current_order = this.pos.get_order(); |
|||
var current_pricelist = this.pos.default_pricelist; |
|||
|
|||
if (current_order) { |
|||
current_pricelist = current_order.pricelist; |
|||
} |
|||
|
|||
return current_pricelist; |
|||
}, |
|||
|
|||
set_variant_list: function(variant_list){ |
|||
this.variant_list = variant_list; |
|||
this.filter_variant_list = variant_list; |
|||
this.renderElement(); |
|||
}, |
|||
|
|||
render_variant: function(variant){ |
|||
var current_pricelist = this._get_active_pricelist(); |
|||
var variant_html = QWeb.render('VariantWidget', { |
|||
pricelist: current_pricelist, |
|||
widget: this, |
|||
variant: variant, |
|||
}); |
|||
var variant_node = document.createElement('div'); |
|||
variant_node.innerHTML = variant_html; |
|||
variant_node = variant_node.childNodes[1]; |
|||
return variant_node; |
|||
}, |
|||
|
|||
renderElement: function() { |
|||
var self = this; |
|||
var el_html = core.qweb.render(this.template, {widget: this}); |
|||
var el_node = document.createElement('div'); |
|||
el_node.innerHTML = el_html; |
|||
el_node = el_node.childNodes[1]; |
|||
if(this.el && this.el.parentNode){ |
|||
this.el.parentNode.replaceChild(el_node,this.el); |
|||
} |
|||
this.el = el_node; |
|||
var list_container = el_node.querySelector('.variant-list'); |
|||
for(var i = 0, len = this.filter_variant_list.length; i < len; i++){ |
|||
var variant_node = this.render_variant(this.filter_variant_list[i]); |
|||
variant_node.addEventListener('click',this.click_variant_handler); |
|||
list_container.appendChild(variant_node); |
|||
} |
|||
}, |
|||
|
|||
}); |
|||
|
|||
|
|||
/* ******************************************************** |
|||
Define: pos_product_template.AttributeListWidget |
|||
|
|||
- This widget will display a list of Attribute; |
|||
***********************************************************/ |
|||
var AttributeListWidget = PosBaseWidget.extend({ |
|||
template:'AttributeListWidget', |
|||
|
|||
init: function(parent, options) { |
|||
var self = this; |
|||
this.attribute_list = []; |
|||
this.product_template = null; |
|||
this.click_set_attribute_handler = function(event){ |
|||
//TODO: Refactor this function with elegant DOM manipulation
|
|||
// remove selected item
|
|||
parent = this.parentElement.parentElement.parentElement; |
|||
parent.children[0].classList.remove('selected'); |
|||
for (var i = 0 ; i < parent.children[1].children[0].children.length; i ++){ |
|||
var elem = parent.children[1].children[0].children[i]; |
|||
elem.children[0].classList.remove('selected'); |
|||
} |
|||
// add selected item
|
|||
this.children[0].classList.add('selected'); |
|||
self.__parentedParent.variant_list_widget.set_filter(this.dataset['attributeId'], this.dataset['attributeValueId']); |
|||
}; |
|||
this.click_reset_attribute_handler = function(event){ |
|||
//TODO: Refactor this function with elegant DOM manipulation
|
|||
// remove selected item
|
|||
parent = this.parentElement; |
|||
parent.children[0].classList.remove('selected'); |
|||
for (var i = 0 ; i < parent.children[1].children[0].children.length; i ++){ |
|||
var elem = parent.children[1].children[0].children[i]; |
|||
elem.children[0].classList.remove('selected'); |
|||
} |
|||
// add selected item
|
|||
this.classList.add('selected'); |
|||
self.__parentedParent.variant_list_widget.reset_filter(this.dataset['attributeId']); |
|||
}; |
|||
this._super(parent, options); |
|||
}, |
|||
|
|||
replace: function($target){ |
|||
this.renderElement(); |
|||
var target = $target[0]; |
|||
target.parentNode.replaceChild(this.el,target); |
|||
}, |
|||
|
|||
set_attribute_list: function(attribute_list, product_template){ |
|||
this.attribute_list = attribute_list; |
|||
this.product_template = product_template; |
|||
this.renderElement(); |
|||
}, |
|||
|
|||
render_attribute: function(attribute){ |
|||
var attribute_html = QWeb.render('AttributeWidget',{ |
|||
widget: this, |
|||
attribute: attribute, |
|||
}); |
|||
var attribute_node = document.createElement('div'); |
|||
attribute_node.innerHTML = attribute_html; |
|||
attribute_node = attribute_node.childNodes[1]; |
|||
|
|||
var list_container = attribute_node.querySelector('.value-list'); |
|||
for(var i = 0, len = attribute.value_ids.length; i < len; i++){ |
|||
var value = this.pos.db.get_product_attribute_value_by_id(attribute.value_ids[i]); |
|||
var product_list = this.pos.db.get_product_by_ids(this.product_template.product_variant_ids); |
|||
var subproduct_list = this.pos.db.get_product_by_value_and_products(value.id, product_list); |
|||
var variant_qty = subproduct_list.length; |
|||
// Hide product attribute value if there is no product associated to it
|
|||
if (variant_qty !== 0) { |
|||
var value_node = this.render_value(value, variant_qty); |
|||
value_node.addEventListener('click', this.click_set_attribute_handler); |
|||
list_container.appendChild(value_node); |
|||
} |
|||
}; |
|||
return attribute_node; |
|||
}, |
|||
|
|||
render_value: function(value, variant_qty){ |
|||
var value_html = QWeb.render('AttributeValueWidget',{ |
|||
widget: this, |
|||
value: value, |
|||
variant_qty: variant_qty, |
|||
}); |
|||
var value_node = document.createElement('div'); |
|||
value_node.innerHTML = value_html; |
|||
value_node = value_node.childNodes[1]; |
|||
return value_node; |
|||
}, |
|||
|
|||
renderElement: function() { |
|||
var self = this; |
|||
var el_html = core.qweb.render(this.template, {widget: this}); |
|||
var el_node = document.createElement('div'); |
|||
el_node.innerHTML = el_html; |
|||
el_node = el_node.childNodes[1]; |
|||
if(this.el && this.el.parentNode){ |
|||
this.el.parentNode.replaceChild(el_node,this.el); |
|||
} |
|||
this.el = el_node; |
|||
|
|||
var list_container = el_node.querySelector('.attribute-list'); |
|||
for(var i = 0, len = this.attribute_list.length; i < len; i++){ |
|||
var attribute_node = this.render_attribute(this.attribute_list[i]); |
|||
attribute_node.querySelector('.attribute-name').addEventListener('click', this.click_reset_attribute_handler); |
|||
list_container.appendChild(attribute_node); |
|||
}; |
|||
}, |
|||
|
|||
}); |
|||
|
|||
/* ******************************************************** |
|||
Overload: point_of_sale.PosDB |
|||
|
|||
- Add to local storage Product Templates Data. |
|||
- Link Product Variants to Product Templates. |
|||
- Add an extra field 'is_primary_variant' on product object. the product |
|||
will be display on product list, only if it is the primary variant; |
|||
Otherwise, the product will be displayed only on Template Screen. |
|||
- Add an extra field 'product_variant_count' on product object that |
|||
indicates the number of variant of the template of the product. |
|||
********************************************************** */ |
|||
PosDB.include({ |
|||
init: function(options){ |
|||
this.template_by_id = {}; |
|||
this.product_attribute_by_id = {}; |
|||
this.product_attribute_value_by_id = {}; |
|||
this._super(options); |
|||
}, |
|||
|
|||
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_by_value_and_products: function(value_id, products){ |
|||
var list = []; |
|||
for (var i = 0, len = products.length; i < len; i++) { |
|||
if (products[i].attribute_value_ids.indexOf(value_id) !== -1){ |
|||
list.push(products[i]); |
|||
} |
|||
} |
|||
return list; |
|||
}, |
|||
|
|||
get_product_attribute_by_id: function(attribute_id){ |
|||
return this.product_attribute_by_id[attribute_id]; |
|||
}, |
|||
|
|||
get_product_attribute_value_by_id: function(attribute_value_id){ |
|||
return this.product_attribute_value_by_id[attribute_value_id]; |
|||
}, |
|||
|
|||
get_product_by_ids: function(product_ids){ |
|||
var list = []; |
|||
for (var i = 0, len = product_ids.length; i < len; i++) { |
|||
list.push(this.product_by_id[product_ids[i]]); |
|||
} |
|||
return list; |
|||
}, |
|||
|
|||
|
|||
attribute_by_template_id: function(template_id){ |
|||
var template = this.template_by_id[template_id]; |
|||
return this.attribute_by_attribute_value_ids(template.attribute_value_ids); |
|||
}, |
|||
|
|||
attribute_by_attribute_value_ids: function(value_ids){ |
|||
var attribute_ids = []; |
|||
for (var i = 0; i < value_ids.length; i++){ |
|||
var value = this.product_attribute_value_by_id[value_ids[i]]; |
|||
if (attribute_ids.indexOf(value.attribute_id[0])===-1){ |
|||
attribute_ids.push(value.attribute_id[0]); |
|||
} |
|||
} |
|||
return attribute_ids; |
|||
}, |
|||
|
|||
add_templates: function(templates){ |
|||
for(var i=0 ; i < templates.length; i++){ |
|||
var attribute_value_ids = []; |
|||
// store Templates
|
|||
this.template_by_id[templates[i].id] = templates[i]; |
|||
|
|||
// Update Product information
|
|||
for (var j = 0; j <templates[i].product_variant_ids.length; j++){ |
|||
var product = this.product_by_id[templates[i].product_variant_ids[j]] |
|||
for (var k = 0; k < product.attribute_value_ids.length; k++){ |
|||
if (attribute_value_ids.indexOf(product.attribute_value_ids[k])===-1){ |
|||
attribute_value_ids.push(product.attribute_value_ids[k]); |
|||
} |
|||
} |
|||
product.product_variant_count = templates[i].product_variant_count; |
|||
product.is_primary_variant = (j===0); |
|||
} |
|||
this.template_by_id[templates[i].id].attribute_value_ids = attribute_value_ids; |
|||
} |
|||
}, |
|||
|
|||
add_product_attributes: function(product_attributes){ |
|||
for(var i=0 ; i < product_attributes.length; i++){ |
|||
// store Product Attributes
|
|||
this.product_attribute_by_id[product_attributes[i].id] = product_attributes[i]; |
|||
} |
|||
}, |
|||
|
|||
add_product_attribute_values: function(product_attribute_values){ |
|||
for(var i=0 ; i < product_attribute_values.length; i++){ |
|||
// store Product Attribute Values
|
|||
this.product_attribute_value_by_id[product_attribute_values[i].id] = product_attribute_values[i]; |
|||
} |
|||
}, |
|||
}); |
|||
|
|||
/********************************************************* |
|||
Overload: point_of_sale.PosModel |
|||
|
|||
- Overload module.PosModel.initialize function to load extra-data |
|||
- Load 'name' field of model product.product; |
|||
- Load product.template model; |
|||
*********************************************************** */ |
|||
// change product.product fields - add name and attribute_value_ids
|
|||
models.PosModel.prototype.models.some(function (model) { |
|||
if (model.model !== 'product.product') { |
|||
return false; |
|||
} |
|||
// add name and attribute_value_ids to list of fields
|
|||
// to fetch for product.product
|
|||
['name', 'attribute_value_ids'].forEach(function (field) { |
|||
if (model.fields.indexOf(field) === -1) { |
|||
model.fields.push(field); |
|||
} |
|||
}); |
|||
return true; //exit early the iteration of this.models
|
|||
}); |
|||
|
|||
//Add our new models
|
|||
models.load_models([{ |
|||
model: 'product.template', |
|||
fields: [ |
|||
'name', |
|||
'display_name', |
|||
'product_variant_ids', |
|||
'product_variant_count', |
|||
], |
|||
domain: function(self){ |
|||
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 (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', |
|||
], |
|||
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); |
|||
}, |
|||
}]); |
|||
|
|||
return { |
|||
'SelectVariantPopupWidget': SelectVariantPopupWidget, |
|||
'VariantListWidget': VariantListWidget, |
|||
'AttributeListWidget': AttributeListWidget, |
|||
}; |
|||
}); |
@ -0,0 +1,119 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- Copyright (C) 2014-Today Akretion (https://www.akretion.com) |
|||
@author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). --> |
|||
<template> |
|||
|
|||
<!-- Pop Up Widget --> |
|||
<t t-name="SelectVariantPopupWidget"> |
|||
<div class="modal-dialog"> |
|||
<div class="popup popup-select-variant"> |
|||
<div class="variant-title"> |
|||
Variant Selection of <span id="variant-title-name" /> |
|||
<span id="variant-popup-cancel" class="button"> |
|||
Cancel |
|||
</span> |
|||
|
|||
</div> |
|||
<div class="content-container container-attribute-list"> |
|||
<span class="placeholder-AttributeListWidget" /> |
|||
</div> |
|||
<div class="content-container container-variant-list"> |
|||
<span class="placeholder-VariantListWidget" /> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</t> |
|||
|
|||
<!-- Product Template Widget --> |
|||
<!-- This code come from Odoo Project --> |
|||
<!-- Changes: |
|||
* Display 'name' field instead of display_name field; |
|||
* Display variant quantity instead of price; |
|||
--> |
|||
<t t-name="Template"> |
|||
<span class='product' t-att-data-product-id="product.id"> |
|||
<div class="product-img"> |
|||
<img t-att-src='image_url' /> |
|||
<span class="price-tag"> |
|||
<t t-esc="product.product_variant_count"/> Variants |
|||
</span> |
|||
</div> |
|||
<div class="product-name"> |
|||
<t t-esc="product.name"/> |
|||
</div> |
|||
</span> |
|||
</t> |
|||
|
|||
<!-- Attribute and Attributes list Widgets --> |
|||
<t t-name="AttributeListWidget"> |
|||
<div class='attribute-list-container'> |
|||
<div class="attribute-list-scroller touch-scrollable"> |
|||
<div class="attribute-list"> |
|||
</div> |
|||
</div> |
|||
<span class="placeholder-ScrollbarWidget" /> |
|||
</div> |
|||
</t> |
|||
|
|||
<t t-name="AttributeWidget"> |
|||
<span class='attribute' t-att-data-attribute-id="attribute.id"> |
|||
<div class="attribute-name button selected" t-att-data-attribute-id="attribute.id"> |
|||
<t t-esc="attribute.name"/> |
|||
</div> |
|||
<div class='value-list-container'> |
|||
<div class="value-list"> |
|||
</div> |
|||
|
|||
</div> |
|||
</span> |
|||
</t> |
|||
|
|||
<t t-name="AttributeValueWidget"> |
|||
<span class='attribute-value' t-att-data-attribute-id="value.attribute_id[0]" t-att-data-attribute-value-id="value.id"> |
|||
<div class="button"> |
|||
<div class="attribute-value-header"> |
|||
<span class="variant-quantity"> |
|||
<t t-esc="variant_qty"/> Variants |
|||
</span> |
|||
</div> |
|||
<div class="attribute-value-name"> |
|||
<t t-esc="value.name"/> |
|||
</div> |
|||
</div> |
|||
</span> |
|||
</t> |
|||
|
|||
|
|||
<!-- Variant and Variants List Widgets --> |
|||
<t t-name="VariantListWidget"> |
|||
<div class='variant-list-container'> |
|||
<div class="variant-list-scroller touch-scrollable"> |
|||
<div class="variant-list"> |
|||
</div> |
|||
</div> |
|||
<span class="placeholder-ScrollbarWidget" /> |
|||
</div> |
|||
</t> |
|||
|
|||
<t t-name="VariantWidget"> |
|||
<span class='variant' t-att-data-variant-id="variant.id"> |
|||
<div class="variant-header"> |
|||
<t t-if="!variant.to_weight"> |
|||
<span class="price-tag"> |
|||
<t t-esc="widget.format_currency(variant.get_price(pricelist, 1), 'Product Price')"/> |
|||
</span> |
|||
</t> |
|||
<t t-if="variant.to_weight"> |
|||
<span class="price-tag"> |
|||
<t t-esc="widget.format_currency(variant.get_price(pricelist, 1), 'Product Price')+'/Kg'"/> |
|||
</span> |
|||
</t> |
|||
</div> |
|||
<div class="variant-name"> |
|||
<t t-esc="variant.display_name"/> |
|||
</div> |
|||
</span> |
|||
</t> |
|||
|
|||
</template> |
@ -0,0 +1,14 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<!-- Copyright (C) 2014-Today Akretion (https://www.akretion.com) |
|||
@author Sylvain LE GAL (https://twitter.com/legalsylvain) |
|||
License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl). --> |
|||
<odoo> |
|||
<template id="index" name="pos_product_template assets" inherit_id="point_of_sale.assets"> |
|||
<xpath expr="//link[@id='pos-stylesheet']" position="after"> |
|||
<link rel="stylesheet" href="/pos_product_template/static/src/css/ppt.css" id="pos_product_template-stylesheet"/> |
|||
</xpath> |
|||
<xpath expr="." position="inside"> |
|||
<script type="text/javascript" src="/pos_product_template/static/src/js/ppt.js"></script> |
|||
</xpath> |
|||
</template> |
|||
</odoo> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue