añadido pos_product_available desde odoo app
https://apps.odoo.com/apps/modules/12.0/pos_product_available/
This commit is contained in:
parent
89d58a2aff
commit
f1c8cf8414
24 changed files with 1030 additions and 0 deletions
35
pos_product_available/README.rst
Normal file
35
pos_product_available/README.rst
Normal file
|
@ -0,0 +1,35 @@
|
|||
.. image:: https://itpp.dev/images/infinity-readme.png
|
||||
:alt: Tested and maintained by IT Projects Labs
|
||||
:target: https://itpp.dev
|
||||
|
||||
.. image:: https://img.shields.io/badge/license-MIT-blue.svg
|
||||
:target: https://opensource.org/licenses/MIT
|
||||
:alt: License: MIT
|
||||
|
||||
=======================
|
||||
POS: show product qty
|
||||
=======================
|
||||
|
||||
Adds available quantity at products in POS
|
||||
|
||||
Module potentialy isn't compatible with modules that overrides `get_price` method in JS
|
||||
|
||||
Questions?
|
||||
==========
|
||||
|
||||
To get an assistance on this module contact us by email :arrow_right: help@itpp.dev
|
||||
|
||||
Contributors
|
||||
============
|
||||
* `Ivan Yelizariev <https://it-projects.info/team/yelizariev>`__
|
||||
|
||||
|
||||
Further information
|
||||
===================
|
||||
|
||||
Odoo Apps Store: https://apps.odoo.com/apps/modules/12.0/pos_product_available/
|
||||
|
||||
|
||||
Notifications on updates: `via Atom <https://github.com/it-projects-llc/pos_addons/commits/12.0/pos_product_available.atom>`_, `by Email <https://blogtrottr.com/?subscribe=https://github.com/it-projects-llc/pos_addons/commits/12.0/pos_product_available.atom>`_
|
||||
|
||||
Tested on `Odoo 12.0 <https://github.com/odoo/odoo/commit/53dcdd5a9e22429a9638f68674264436ce21e42b>`_
|
3
pos_product_available/__init__.py
Normal file
3
pos_product_available/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
# License MIT (https://opensource.org/licenses/MIT).
|
||||
|
||||
from . import models
|
30
pos_product_available/__manifest__.py
Normal file
30
pos_product_available/__manifest__.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
# Copyright 2014-2018 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
|
||||
# Copyright 2017 Gabbasov Dinar <https://it-projects.info/team/GabbasovDinar>
|
||||
# Copyright 2018-2019 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
|
||||
# Copyright 2018 Ildar Nasyrov <https://it-projects.info/team/iledarn>
|
||||
# License MIT (https://opensource.org/licenses/MIT).
|
||||
{
|
||||
"name": """POS: show product qty""",
|
||||
"summary": """Adds available quantity at products in POS""",
|
||||
"category": "Point Of Sale",
|
||||
# "live_test_url": "http://apps.it-projects.info/shop/product/DEMO-URL?version={ODOO_BRANCH}",
|
||||
"images": ["images/pos_product_available.jpg"],
|
||||
"version": "12.0.1.1.1",
|
||||
"application": False,
|
||||
"author": "IT-Projects LLC, Ivan Yelizariev",
|
||||
"support": "apps@itpp.dev",
|
||||
"website": "https://apps.odoo.com/apps/modules/12.0/pos_product_available/",
|
||||
"license": "Other OSI approved licence", # MIT
|
||||
# "price": 9.00,
|
||||
# "currency": "EUR",
|
||||
"depends": ["point_of_sale", "stock"],
|
||||
"external_dependencies": {"python": [], "bin": []},
|
||||
"data": ["data.xml", "views/views.xml"],
|
||||
"qweb": ["static/src/xml/pos.xml"],
|
||||
"post_load": None,
|
||||
"pre_init_hook": None,
|
||||
"post_init_hook": None,
|
||||
"uninstall_hook": None,
|
||||
"auto_install": False,
|
||||
"installable": True,
|
||||
}
|
34
pos_product_available/data.xml
Normal file
34
pos_product_available/data.xml
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!--Copyright 2014-2016 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
|
||||
Copyright 2018 Gabbasov Dinar <https://it-projects.info/team/GabbasovDinar>
|
||||
Copyright 2018 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
|
||||
Copyright 2018 Ildar Nasyrov <https://it-projects.info/team/iledarn>
|
||||
License MIT (https://opensource.org/licenses/MIT). -->
|
||||
<odoo>
|
||||
<template id="assets_backend" name="pos assets" inherit_id="point_of_sale.assets">
|
||||
<xpath expr="." position="inside">
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="/pos_product_available/static/src/js/pos.js"
|
||||
/>
|
||||
</xpath>
|
||||
<xpath expr="//link[@id='pos-stylesheet']" position="after">
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="/pos_product_available/static/src/css/pos.css"
|
||||
/>
|
||||
</xpath>
|
||||
</template>
|
||||
<template
|
||||
id="assets_backend_web"
|
||||
name="pos_product_available_backend_assets"
|
||||
inherit_id="web.assets_backend"
|
||||
>
|
||||
<xpath expr="." position="inside">
|
||||
<script
|
||||
type="text/javascript"
|
||||
src="/pos_product_available/static/src/js/test_pos_quantities.js"
|
||||
/>
|
||||
</xpath>
|
||||
</template>
|
||||
</odoo>
|
46
pos_product_available/doc/changelog.rst
Normal file
46
pos_product_available/doc/changelog.rst
Normal file
|
@ -0,0 +1,46 @@
|
|||
`1.1.1`
|
||||
-------
|
||||
|
||||
- [FIX] product qty available wrong rounding and overrided 'get_price' method in pos.js
|
||||
|
||||
`1.1.0`
|
||||
-------
|
||||
|
||||
- **New:** Added option to show product quantities
|
||||
|
||||
`1.0.7`
|
||||
-------
|
||||
|
||||
- **Fix:** Non rounded long values of quantities
|
||||
|
||||
|
||||
`1.0.6`
|
||||
-------
|
||||
|
||||
- **FIX:** Added compatibility with pos_multi_session
|
||||
|
||||
`1.0.5`
|
||||
-------
|
||||
|
||||
- **FIX:** Product quantities representation according to the set location
|
||||
- **FIX:** Product quantities representation only for stockable products
|
||||
|
||||
`1.0.4`
|
||||
-------
|
||||
|
||||
- [FIX] incorrect products quantity numbers with pos_cache module.
|
||||
|
||||
`1.0.3`
|
||||
-------
|
||||
|
||||
- [FIX] compatibility with pos_cache module. Thanks to MindAndGo.
|
||||
|
||||
`1.0.2`
|
||||
-------
|
||||
|
||||
- [FIX] update product counter when sale via invoice
|
||||
|
||||
`1.0.1`
|
||||
-------
|
||||
|
||||
- Show quantity related to POS's stock location only.
|
8
pos_product_available/doc/index.rst
Normal file
8
pos_product_available/doc/index.rst
Normal file
|
@ -0,0 +1,8 @@
|
|||
=======================
|
||||
POS: show product qty
|
||||
=======================
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
* `Install <https://odoo-development.readthedocs.io/en/latest/odoo/usage/install-module.html>`__ this module in a usual way
|
47
pos_product_available/doc/src/index.html
Normal file
47
pos_product_available/doc/src/index.html
Normal file
|
@ -0,0 +1,47 @@
|
|||
|
||||
<section class="oe_container"><div class="oe_row oe_spaced"> <div class="oe_span12">
|
||||
</div>
|
||||
|
||||
<div class="oe_span6">
|
||||
<div class="oe_demo oe_picture oe_screenshot">
|
||||
<img src="screenshot.png"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_span6">
|
||||
<p class="oe_mt32">
|
||||
Adds available quantity at order panel
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container oe_dark">
|
||||
<div class="oe_row oe_spaced">
|
||||
<div class="oe_span6">
|
||||
<p class="oe_mt32">
|
||||
Adds available quantity at products.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="oe_span6">
|
||||
<div class="oe_demo oe_picture oe_screenshot">
|
||||
<img src="screenshot-2.png"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container">
|
||||
<div class="oe_row oe_spaced">
|
||||
<div class="oe_span12">
|
||||
<h2>Usage</h2>
|
||||
<p class="oe_mt32">
|
||||
There no any settings. Just install the module and start POS.
|
||||
</p>
|
||||
<p class="oe_mt32">
|
||||
Works in offline mode.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
1
pos_product_available/doc/src/info.yaml
Normal file
1
pos_product_available/doc/src/info.yaml
Normal file
|
@ -0,0 +1 @@
|
|||
slogan: Let a cashier know how many products are available
|
72
pos_product_available/i18n/de.po
Normal file
72
pos_product_available/i18n/de.po
Normal file
|
@ -0,0 +1,72 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * pos_product_available
|
||||
#
|
||||
# Translators:
|
||||
# Translation Bot <i18n-bot@it-projects.info>, 2017
|
||||
# Ermin Trevisan <trevi@twanda.com>, 2018
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 10.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2018-04-27 23:49+0000\n"
|
||||
"PO-Revision-Date: 2018-04-27 23:49+0000\n"
|
||||
"Last-Translator: Ermin Trevisan <trevi@twanda.com>, 2018\n"
|
||||
"Language-Team: German (https://www.transifex.com/it-projects-llc/teams/76080/"
|
||||
"de/)\n"
|
||||
"Language: de\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_product_available
|
||||
#. openerp-web
|
||||
#: code:addons/pos_product_available/static/src/xml/pos.xml:21
|
||||
#, python-format
|
||||
msgid "(of"
|
||||
msgstr "(von "
|
||||
|
||||
#. module: pos_product_available
|
||||
#. openerp-web
|
||||
#: code:addons/pos_product_available/static/src/js/test_pos_quantities.js:13
|
||||
#: code:addons/pos_product_available/static/src/js/test_pos_quantities.js:72
|
||||
#, python-format
|
||||
msgid ""
|
||||
"<p>Click to start the point of sale interface. It <b>runs on tablets</b>, "
|
||||
"laptops, or industrial hardware.</p><p>Once the session launched, the system "
|
||||
"continues to run without an internet connection.</p>"
|
||||
msgstr ""
|
||||
"<p>Anklicken, um das POS-System zu starten. Es <b>läuft auf Tablets</b>, "
|
||||
"Laptops, oder industrieller Hardware.</p><p>Sobald eine Sitzung gestartet "
|
||||
"wurde, funktioniert das System auch ohne Internet-Verbindung.</p>"
|
||||
|
||||
#. module: pos_product_available
|
||||
#. openerp-web
|
||||
#: code:addons/pos_product_available/static/src/js/test_pos_quantities.js:48
|
||||
#, python-format
|
||||
msgid "Click the payment method"
|
||||
msgstr ""
|
||||
|
||||
#. module: pos_product_available
|
||||
#. openerp-web
|
||||
#: code:addons/pos_product_available/static/src/js/test_pos_quantities.js:65
|
||||
#: code:addons/pos_product_available/static/src/js/test_pos_quantities.js:68
|
||||
#, python-format
|
||||
msgid "Close POS"
|
||||
msgstr ""
|
||||
|
||||
#. module: pos_product_available
|
||||
#. openerp-web
|
||||
#: code:addons/pos_product_available/static/src/js/test_pos_quantities.js:42
|
||||
#, python-format
|
||||
msgid "Open the payment screen"
|
||||
msgstr ""
|
||||
|
||||
#. module: pos_product_available
|
||||
#. openerp-web
|
||||
#: code:addons/pos_product_available/static/src/js/test_pos_quantities.js:87
|
||||
#: code:addons/pos_product_available/static/src/js/test_pos_quantities.js:92
|
||||
#, python-format
|
||||
msgid "Ready to launch your <b>point of sale</b>? <i>Click here</i>."
|
||||
msgstr "Bereit, Ihren <b>Point of Sale</b>zu starten? <i>Klicken Sie hier</i>."
|
73
pos_product_available/i18n/es.po
Normal file
73
pos_product_available/i18n/es.po
Normal file
|
@ -0,0 +1,73 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * pos_product_available
|
||||
#
|
||||
# Translators:
|
||||
# charles paul requena palomino <rcharles84@gmail.com>, 2018
|
||||
# Alexandr Frrost <alexandr.frrost@gmail.com>, 2018
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 10.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2018-04-27 23:49+0000\n"
|
||||
"PO-Revision-Date: 2018-04-27 23:49+0000\n"
|
||||
"Last-Translator: Alexandr Frrost <alexandr.frrost@gmail.com>, 2018\n"
|
||||
"Language-Team: Spanish (https://www.transifex.com/it-projects-llc/"
|
||||
"teams/76080/es/)\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"
|
||||
|
||||
#. module: pos_product_available
|
||||
#. openerp-web
|
||||
#: code:addons/pos_product_available/static/src/xml/pos.xml:21
|
||||
#, python-format
|
||||
msgid "(of"
|
||||
msgstr ""
|
||||
|
||||
#. module: pos_product_available
|
||||
#. openerp-web
|
||||
#: code:addons/pos_product_available/static/src/js/test_pos_quantities.js:13
|
||||
#: code:addons/pos_product_available/static/src/js/test_pos_quantities.js:72
|
||||
#, python-format
|
||||
msgid ""
|
||||
"<p>Click to start the point of sale interface. It <b>runs on tablets</b>, "
|
||||
"laptops, or industrial hardware.</p><p>Once the session launched, the system "
|
||||
"continues to run without an internet connection.</p>"
|
||||
msgstr ""
|
||||
"<p>Haga clic para iniciar la interfaz del punto de venta. <b>Se ejecuta en "
|
||||
"tabletas</b>, computadoras portátiles o hardware industrial.</p><p> Una vez "
|
||||
"que se inicia la sesión, el sistema continúa ejecutándose sin conexión a "
|
||||
"Internet.</p>"
|
||||
|
||||
#. module: pos_product_available
|
||||
#. openerp-web
|
||||
#: code:addons/pos_product_available/static/src/js/test_pos_quantities.js:48
|
||||
#, python-format
|
||||
msgid "Click the payment method"
|
||||
msgstr ""
|
||||
|
||||
#. module: pos_product_available
|
||||
#. openerp-web
|
||||
#: code:addons/pos_product_available/static/src/js/test_pos_quantities.js:65
|
||||
#: code:addons/pos_product_available/static/src/js/test_pos_quantities.js:68
|
||||
#, python-format
|
||||
msgid "Close POS"
|
||||
msgstr ""
|
||||
|
||||
#. module: pos_product_available
|
||||
#. openerp-web
|
||||
#: code:addons/pos_product_available/static/src/js/test_pos_quantities.js:42
|
||||
#, python-format
|
||||
msgid "Open the payment screen"
|
||||
msgstr ""
|
||||
|
||||
#. module: pos_product_available
|
||||
#. openerp-web
|
||||
#: code:addons/pos_product_available/static/src/js/test_pos_quantities.js:87
|
||||
#: code:addons/pos_product_available/static/src/js/test_pos_quantities.js:92
|
||||
#, python-format
|
||||
msgid "Ready to launch your <b>point of sale</b>? <i>Click here</i>."
|
||||
msgstr "¿Listo para lanzar su <b>punto de venta</b>? <i>Haga clic aquí</i>."
|
BIN
pos_product_available/images/pos_product_available.jpg
Normal file
BIN
pos_product_available/images/pos_product_available.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 241 KiB |
2
pos_product_available/models/__init__.py
Normal file
2
pos_product_available/models/__init__.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
# License MIT (https://opensource.org/licenses/MIT).
|
||||
from . import models
|
12
pos_product_available/models/models.py
Normal file
12
pos_product_available/models/models.py
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Copyright 2019 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
|
||||
# License MIT (https://opensource.org/licenses/MIT).
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class PosConfig(models.Model):
|
||||
_inherit = "pos.config"
|
||||
|
||||
show_qtys = fields.Boolean(
|
||||
"Show Product Qtys", help="Show Product Qtys in POS", default=True
|
||||
)
|
BIN
pos_product_available/static/description/icon.png
Normal file
BIN
pos_product_available/static/description/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
145
pos_product_available/static/description/index.html
Normal file
145
pos_product_available/static/description/index.html
Normal file
|
@ -0,0 +1,145 @@
|
|||
|
||||
<section class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-offset-1 col-md-8 mb64 mt64">
|
||||
<div class="">
|
||||
<h2 class="display-3">POS: show product qty</h2>
|
||||
<h4 class="text-default">Let a cashier know how many products are available</h4>
|
||||
<p class="text-default mt16">Version: v<b>12.0</b>.1.1.1</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 text-right">
|
||||
<p>
|
||||
<img src="https://itpp.dev/images/favicon.png"/>
|
||||
<br/>Tested and maintained by
|
||||
<br/><b>IT Projects Labs</b>
|
||||
<br/>Assitance: <a href="mailto:help@itpp.dev">help@itpp.dev</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
<section class="oe_container"><div class="oe_row oe_spaced"> <div class="oe_span12">
|
||||
</div>
|
||||
|
||||
<div class="oe_span6">
|
||||
<div class="oe_demo oe_picture oe_screenshot">
|
||||
<img src="screenshot.png"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="oe_span6">
|
||||
<p class="oe_mt32">
|
||||
Adds available quantity at order panel
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container oe_dark">
|
||||
<div class="oe_row oe_spaced">
|
||||
<div class="oe_span6">
|
||||
<p class="oe_mt32">
|
||||
Adds available quantity at products.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="oe_span6">
|
||||
<div class="oe_demo oe_picture oe_screenshot">
|
||||
<img src="screenshot-2.png"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="oe_container">
|
||||
<div class="oe_row oe_spaced">
|
||||
<div class="oe_span12">
|
||||
<h2>Usage</h2>
|
||||
<p class="oe_mt32">
|
||||
There no any settings. Just install the module and start POS.
|
||||
</p>
|
||||
<p class="oe_mt32">
|
||||
Works in offline mode.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
|
||||
<section class="container text-center">
|
||||
<div class="mt-4 mb-3">
|
||||
<h2>Let our expertise work for you!</h2>
|
||||
<h4 class="d-none d-md-block">(Doors and windows below are clickable)</h4>
|
||||
<div class="mb32 d-md-none">
|
||||
<ul class="list-unstyled">
|
||||
<li><a target="_blank" href="https://apps.odoo.com/apps/browse?repo_maintainer_id=59928">All modules</a></li>
|
||||
<li><a target="_blank" href="https://apps.odoo.com/apps/browse?price=Free&order=Downloads&repo_maintainer_id=59928">Free Modules</a></li>
|
||||
<li><a target="_blank" href="https://apps.odoo.com/apps/modules/category/Point%20of%20Sale/browse?repo_maintainer_id=59928">All POS modules</a></li>
|
||||
<li><a target="_blank" href="https://apps.odoo.com/apps/modules/category/Discuss/browse?repo_maintainer_id=59928">All Mail modules</a></li>
|
||||
<li><a target="_blank" href="https://apps.odoo.com/apps/modules/category/Website/browse?repo_maintainer_id=59928">All Website modules</a></li>
|
||||
<li><a target="_blank" href="https://apps.odoo.com/apps/modules/category/eCommerce/browse?repo_maintainer_id=59928">All eCommerce modules</a></li>
|
||||
<li><a target="_blank" href="https://apps.odoo.com/apps/modules/browse?search=sync+studio&repo_maintainer_id=59928">Sync Studio</a></li>
|
||||
<li><a target="_blank" href="https://apps.odoo.com/apps/modules/14.0/openapi/">REST API</a></li>
|
||||
<li><a target="_blank" href="https://apps.odoo.com/apps/modules/14.0/base_automation_webhook/">Webhooks</a></li>
|
||||
<li><a target="_blank" href="https://apps.odoo.com/apps/modules/14.0/pos_product_available/">POS: show product qty</a></li>
|
||||
<li><a target="_blank" href="https://apps.odoo.com/apps/modules/14.0/web_login_background/">Web Login Background</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="mb64 d-none d-xl-block">
|
||||
<img class="img img-responsive" src="https://itpp.dev/images/apps/;-)/itpp-labs-1100.jpg" usemap="#itpp-xl" />
|
||||
<map name="itpp-xl">
|
||||
<area alt="Free Modules" target="_blank" href="https://apps.odoo.com/apps/browse?price=Free&order=Downloads&repo_maintainer_id=59928" shape="rect" class="" coords="900,220,1080,625" />
|
||||
<area alt="Sync Studio" target="_blank" href="https://apps.odoo.com/apps/modules/browse?search=sync+studio&repo_maintainer_id=59928" shape="rect" class="" coords="552,186,721,274" />
|
||||
<area alt="REST API" target="_blank" href="https://apps.odoo.com/apps/modules/14.0/openapi/" shape="rect" class="" coords="646,279,720,365" />
|
||||
<area alt="Webhooks" target="_blank" href="https://apps.odoo.com/apps/modules/14.0/base_automation_webhook/" shape="rect" class="" coords="646,370,720,458" />
|
||||
<area alt="POS: show product qty" target="_blank" href="https://apps.odoo.com/apps/modules/14.0/pos_product_available/" shape="rect" class="" coords="82,373,251,459" />
|
||||
<area alt="All modules" target="_blank" href="https://apps.odoo.com/apps/browse?repo_maintainer_id=59928" shape="rect" class="" coords="326,267,381,456" />
|
||||
<area alt="All POS modules" target="_blank" href="https://apps.odoo.com/apps/modules/category/Point%20of%20Sale/browse?repo_maintainer_id=59928" shape="rect" class="" coords="82,191,154,276" />
|
||||
<area alt="All Mail modules" target="_blank" href="https://apps.odoo.com/apps/modules/category/Discuss/browse?repo_maintainer_id=59928" shape="rect" class="" coords="82,282,155,368" />
|
||||
<area alt="All Website modules" target="_blank" href="https://apps.odoo.com/apps/modules/category/Website/browse?repo_maintainer_id=59928" shape="rect" class="" coords="176,282,250,368" />
|
||||
<area alt="All eCommerce modules" target="_blank" href="https://apps.odoo.com/apps/modules/category/eCommerce/browse?repo_maintainer_id=59928" shape="rect" class="" coords="175,189,250,275" />
|
||||
<area alt="Ivan Yelizariev" target="_blank" href="https://apps.odoo.com/apps/modules/browse?search=Ivan+Yelizariev&repo_maintainer_id=59928" shape="rect" class="" coords="554,280,625,456" />
|
||||
<area alt="Web Login Background" target="_blank" href="https://apps.odoo.com/apps/modules/14.0/web_login_background/" shape="rect" class="" coords="420,267,477,456" />
|
||||
</map>
|
||||
</div>
|
||||
<div class="mb64 d-none d-lg-block d-xl-none">
|
||||
<img class="img img-responsive" src="https://itpp.dev/images/apps/;-)/itpp-labs-930.jpg" usemap="#itpp-lg" />
|
||||
<map name="itpp-lg">
|
||||
<area alt="Free Modules" target="_blank" href="https://apps.odoo.com/apps/browse?price=Free&order=Downloads&repo_maintainer_id=59928" shape="rect" class="" coords="760,186,913,528" />
|
||||
<area alt="Sync Studio" target="_blank" href="https://apps.odoo.com/apps/modules/browse?search=sync+studio&repo_maintainer_id=59928" shape="rect" class="" coords="466,157,609,231" />
|
||||
<area alt="REST API" target="_blank" href="https://apps.odoo.com/apps/modules/14.0/openapi/" shape="rect" class="" coords="546,235,608,308" />
|
||||
<area alt="Webhooks" target="_blank" href="https://apps.odoo.com/apps/modules/14.0/base_automation_webhook/" shape="rect" class="" coords="546,312,608,387" />
|
||||
<area alt="POS: show product qty" target="_blank" href="https://apps.odoo.com/apps/modules/14.0/pos_product_available/" shape="rect" class="" coords="69,315,212,388" />
|
||||
<area alt="All modules" target="_blank" href="https://apps.odoo.com/apps/browse?repo_maintainer_id=59928" shape="rect" class="" coords="275,225,322,385" />
|
||||
<area alt="All POS modules" target="_blank" href="https://apps.odoo.com/apps/modules/category/Point%20of%20Sale/browse?repo_maintainer_id=59928" shape="rect" class="" coords="69,161,130,233" />
|
||||
<area alt="All Mail modules" target="_blank" href="https://apps.odoo.com/apps/modules/category/Discuss/browse?repo_maintainer_id=59928" shape="rect" class="" coords="69,238,131,311" />
|
||||
<area alt="All Website modules" target="_blank" href="https://apps.odoo.com/apps/modules/category/Website/browse?repo_maintainer_id=59928" shape="rect" class="" coords="148,238,211,311" />
|
||||
<area alt="All eCommerce modules" target="_blank" href="https://apps.odoo.com/apps/modules/category/eCommerce/browse?repo_maintainer_id=59928" shape="rect" class="" coords="147,159,211,232" />
|
||||
<area alt="Ivan Yelizariev" target="_blank" href="https://apps.odoo.com/apps/modules/browse?search=Ivan+Yelizariev&repo_maintainer_id=59928" shape="rect" class="" coords="468,236,528,385" />
|
||||
<area alt="Web Login Background" target="_blank" href="https://apps.odoo.com/apps/modules/14.0/web_login_background/" shape="rect" class="" coords="355,225,403,385" />
|
||||
</map>
|
||||
</div>
|
||||
<div class="mb64 d-lg-none">
|
||||
<img class="img img-responsive" src="https://itpp.dev/images/apps/;-)/itpp-labs-690.jpg" usemap="#itpp-md" />
|
||||
<map name="itpp-md">
|
||||
<area alt="Free Modules" target="_blank" href="https://apps.odoo.com/apps/browse?price=Free&order=Downloads&repo_maintainer_id=59928" shape="rect" class="" coords="564,138,677,392" />
|
||||
<area alt="Sync Studio" target="_blank" href="https://apps.odoo.com/apps/modules/browse?search=sync+studio&repo_maintainer_id=59928" shape="rect" class="" coords="346,116,452,171" />
|
||||
<area alt="REST API" target="_blank" href="https://apps.odoo.com/apps/modules/14.0/openapi/" shape="rect" class="" coords="405,175,451,228" />
|
||||
<area alt="Webhooks" target="_blank" href="https://apps.odoo.com/apps/modules/14.0/base_automation_webhook/" shape="rect" class="" coords="405,232,451,287" />
|
||||
<area alt="POS: show product qty" target="_blank" href="https://apps.odoo.com/apps/modules/14.0/pos_product_available/" shape="rect" class="" coords="51,233,157,287" />
|
||||
<area alt="All modules" target="_blank" href="https://apps.odoo.com/apps/browse?repo_maintainer_id=59928" shape="rect" class="" coords="204,167,238,286" />
|
||||
<area alt="All POS modules" target="_blank" href="https://apps.odoo.com/apps/modules/category/Point%20of%20Sale/browse?repo_maintainer_id=59928" shape="rect" class="" coords="51,119,96,173" />
|
||||
<area alt="All Mail modules" target="_blank" href="https://apps.odoo.com/apps/modules/category/Discuss/browse?repo_maintainer_id=59928" shape="rect" class="" coords="51,176,97,230" />
|
||||
<area alt="All Website modules" target="_blank" href="https://apps.odoo.com/apps/modules/category/Website/browse?repo_maintainer_id=59928" shape="rect" class="" coords="110,176,156,230" />
|
||||
<area alt="All eCommerce modules" target="_blank" href="https://apps.odoo.com/apps/modules/category/eCommerce/browse?repo_maintainer_id=59928" shape="rect" class="" coords="109,118,156,172" />
|
||||
<area alt="Ivan Yelizariev" target="_blank" href="https://apps.odoo.com/apps/modules/browse?search=Ivan+Yelizariev&repo_maintainer_id=59928" shape="rect" class="" coords="347,175,392,286" />
|
||||
<area alt="Web Login Background" target="_blank" href="https://apps.odoo.com/apps/modules/14.0/web_login_background/" shape="rect" class="" coords="263,167,299,286" />
|
||||
</map>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
BIN
pos_product_available/static/description/screenshot-2.png
Normal file
BIN
pos_product_available/static/description/screenshot-2.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 96 KiB |
BIN
pos_product_available/static/description/screenshot.png
Normal file
BIN
pos_product_available/static/description/screenshot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
24
pos_product_available/static/src/css/pos.css
Normal file
24
pos_product_available/static/src/css/pos.css
Normal file
|
@ -0,0 +1,24 @@
|
|||
.pos .product .qty-tag {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
left: 2px;
|
||||
vertical-align: top;
|
||||
color: white;
|
||||
line-height: 13px;
|
||||
background: #7f82ac;
|
||||
padding: 2px 5px;
|
||||
border-radius: 2px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.pos .product .qty-tag.not-available {
|
||||
background: #d882ac;
|
||||
}
|
||||
|
||||
.pos .order .orderline .qty-info {
|
||||
color: #777;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
.pos .order .orderline .qty-info.not-available {
|
||||
color: red;
|
||||
}
|
233
pos_product_available/static/src/js/pos.js
Normal file
233
pos_product_available/static/src/js/pos.js
Normal file
|
@ -0,0 +1,233 @@
|
|||
/* Copyright 2014-2017 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
|
||||
Copyright 2016 gaelTorrecillas <https://github.com/gaelTorrecillas>
|
||||
Copyright 2016 manawi <https://github.com/manawi>
|
||||
Copyright 2017 Ilmir Karamov <https://it-projects.info/team/ilmir-k>
|
||||
Copyright 2018,2019 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
|
||||
License MIT (https://opensource.org/licenses/MIT). */
|
||||
odoo.define("pos_product_available.PosModel", function(require) {
|
||||
"use strict";
|
||||
|
||||
var rpc = require("web.rpc");
|
||||
var models = require("point_of_sale.models");
|
||||
var field_utils = require("web.field_utils");
|
||||
|
||||
var PosModelSuper = models.PosModel.prototype;
|
||||
models.PosModel = models.PosModel.extend({
|
||||
load_server_data: function() {
|
||||
var self = this;
|
||||
|
||||
var loaded = PosModelSuper.load_server_data.call(this);
|
||||
|
||||
var prod_model = _.find(this.models, function(model) {
|
||||
return model.model === "product.product";
|
||||
});
|
||||
|
||||
if (prod_model) {
|
||||
prod_model.fields.push("qty_available", "type");
|
||||
var context_super = prod_model.context;
|
||||
prod_model.context = function(that) {
|
||||
var ret = context_super(that);
|
||||
ret.location = that.config.stock_location_id[0];
|
||||
return ret;
|
||||
};
|
||||
var loaded_super = prod_model.loaded;
|
||||
prod_model.loaded = function(that, products) {
|
||||
loaded_super(that, products);
|
||||
self.db.product_qtys = products;
|
||||
};
|
||||
return loaded;
|
||||
}
|
||||
|
||||
return loaded.then(function() {
|
||||
return rpc
|
||||
.query({
|
||||
model: "product.product",
|
||||
method: "search_read",
|
||||
args: [],
|
||||
fields: ["qty_available", "type"],
|
||||
domain: [
|
||||
["sale_ok", "=", true],
|
||||
["available_in_pos", "=", true],
|
||||
],
|
||||
context: {location: self.config.stock_location_id[0]},
|
||||
})
|
||||
.then(function(products) {
|
||||
self.db.product_qtys = products;
|
||||
});
|
||||
});
|
||||
},
|
||||
set_product_qty_available: function(product, qty) {
|
||||
product.qty_available = qty;
|
||||
this.refresh_qty_available(product);
|
||||
},
|
||||
update_product_qty_from_order_lines: function(order) {
|
||||
var self = this;
|
||||
order.orderlines.each(function(line) {
|
||||
var product = line.get_product();
|
||||
product.qty_available = Math.round(
|
||||
product.qty_available - line.get_quantity(),
|
||||
{digits: [69, 3]}
|
||||
);
|
||||
self.refresh_qty_available(product);
|
||||
});
|
||||
// Compatibility with pos_multi_session
|
||||
order.trigger("new_updates_to_send");
|
||||
},
|
||||
after_load_server_data: function() {
|
||||
var self = this;
|
||||
var res = PosModelSuper.after_load_server_data.apply(this, arguments);
|
||||
_.each(this.db.product_qtys, function(v) {
|
||||
_.extend(self.db.get_product_by_id(v.id), v);
|
||||
});
|
||||
return res;
|
||||
},
|
||||
refresh_qty_available: function(product) {
|
||||
var $elem = $("[data-product-id='" + product.id + "'] .qty-tag");
|
||||
$elem.html(product.rounded_qty());
|
||||
if (product.qty_available <= 0 && !$elem.hasClass("not-available")) {
|
||||
$elem.addClass("not-available");
|
||||
}
|
||||
},
|
||||
push_order: function(order, opts) {
|
||||
var pushed = PosModelSuper.push_order.call(this, order, opts);
|
||||
if (order) {
|
||||
this.update_product_qty_from_order_lines(order);
|
||||
}
|
||||
return pushed;
|
||||
},
|
||||
push_and_invoice_order: function(order) {
|
||||
var invoiced = PosModelSuper.push_and_invoice_order.call(this, order);
|
||||
|
||||
if (order && order.get_client() && order.orderlines) {
|
||||
this.update_product_qty_from_order_lines(order);
|
||||
}
|
||||
|
||||
return invoiced;
|
||||
},
|
||||
});
|
||||
|
||||
models.Product = models.Product.extend({
|
||||
get_price: function(pricelist, quantity) {
|
||||
var self = this;
|
||||
var date = moment().startOf("day");
|
||||
|
||||
// In case of nested pricelists, it is necessary that all pricelists are made available in
|
||||
// the POS. Display a basic alert to the user in this case.
|
||||
if (pricelist === undefined) {
|
||||
// eslint-disable-next-line
|
||||
alert(
|
||||
"An error occurred when loading product prices. " +
|
||||
"Make sure all pricelists are available in the POS."
|
||||
);
|
||||
}
|
||||
|
||||
var category_ids = [];
|
||||
var category = this.categ;
|
||||
while (category) {
|
||||
category_ids.push(category.id);
|
||||
category = category.parent;
|
||||
}
|
||||
|
||||
/*
|
||||
So, with pos_product_available it doesnt work correctly, cause
|
||||
'item.product_tmpl_id || item.product_tmpl_id[0] === self.product_tmpl_id'
|
||||
in this string are comparing integer with an array of two elements.
|
||||
Changed: 'self.product_tmpl_id -> self.product_tmpl_id[0]',
|
||||
where 'self.product_tmpl_id[0]' product template id.
|
||||
By the way, here's comparing products ids.
|
||||
IMPORTANT: Changed line - (!item.product_tmpl_id || item.product_tmpl_id[0] === self.product_tmpl_id[0]).
|
||||
*/
|
||||
var pricelist_items = _.filter(pricelist.items, function(item) {
|
||||
return (
|
||||
(!item.product_tmpl_id ||
|
||||
item.product_tmpl_id[0] === self.product_tmpl_id[0]) &&
|
||||
(!item.product_id || item.product_id[0] === self.id) &&
|
||||
(!item.categ_id || _.contains(category_ids, item.categ_id[0])) &&
|
||||
(!item.date_start ||
|
||||
moment(item.date_start).isSameOrBefore(date)) &&
|
||||
(!item.date_end || moment(item.date_end).isSameOrAfter(date))
|
||||
);
|
||||
});
|
||||
|
||||
var price = self.lst_price;
|
||||
_.find(pricelist_items, function(rule) {
|
||||
if (rule.min_quantity && quantity < rule.min_quantity) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rule.base === "pricelist") {
|
||||
price = self.get_price(rule.base_pricelist, quantity);
|
||||
} else if (rule.base === "standard_price") {
|
||||
price = self.standard_price;
|
||||
}
|
||||
|
||||
if (rule.compute_price === "fixed") {
|
||||
price = rule.fixed_price;
|
||||
return true;
|
||||
} else if (rule.compute_price === "percentage") {
|
||||
price -= price * (rule.percent_price / 100);
|
||||
return true;
|
||||
}
|
||||
var price_limit = price;
|
||||
price -= price * (rule.price_discount / 100);
|
||||
if (rule.price_round) {
|
||||
// eslint-disable-next-line
|
||||
price = round_pr(price, rule.price_round);
|
||||
}
|
||||
if (rule.price_surcharge) {
|
||||
price += rule.price_surcharge;
|
||||
}
|
||||
if (rule.price_min_margin) {
|
||||
price = Math.max(price, price_limit + rule.price_min_margin);
|
||||
}
|
||||
if (rule.price_max_margin) {
|
||||
price = Math.min(price, price_limit + rule.price_max_margin);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
// This return value has to be rounded with round_di before
|
||||
// being used further. Note that this cannot happen here,
|
||||
// because it would cause inconsistencies with the backend for
|
||||
// pricelist that have base == 'pricelist'.
|
||||
return price;
|
||||
},
|
||||
});
|
||||
|
||||
var OrderlineSuper = models.Orderline;
|
||||
models.Orderline = models.Orderline.extend({
|
||||
export_as_JSON: function() {
|
||||
var data = OrderlineSuper.prototype.export_as_JSON.apply(this, arguments);
|
||||
data.qty_available = this.product.qty_available;
|
||||
return data;
|
||||
},
|
||||
// Compatibility with pos_multi_session
|
||||
apply_ms_data: function(data) {
|
||||
if (OrderlineSuper.prototype.apply_ms_data) {
|
||||
OrderlineSuper.prototype.apply_ms_data.apply(this, arguments);
|
||||
}
|
||||
var product = this.pos.db.get_product_by_id(data.product_id);
|
||||
if (product.qty_available !== data.qty_available) {
|
||||
this.pos.set_product_qty_available(product, data.qty_available);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
models.Product = models.Product.extend({
|
||||
format_float_value: function(val) {
|
||||
var value = parseFloat(val);
|
||||
value = field_utils.format.float(value, {digits: [69, 3]});
|
||||
return String(parseFloat(value));
|
||||
},
|
||||
/*
|
||||
Commented this code, cause it works incorrect
|
||||
Example: "this.format_float_value(2366) === 2"
|
||||
rounded_qty: function() {
|
||||
return this.format_float_value(this.qty_available);
|
||||
},
|
||||
*/
|
||||
rounded_qty: function() {
|
||||
return Math.round(this.qty_available);
|
||||
},
|
||||
});
|
||||
});
|
142
pos_product_available/static/src/js/test_pos_quantities.js
Normal file
142
pos_product_available/static/src/js/test_pos_quantities.js
Normal file
|
@ -0,0 +1,142 @@
|
|||
/* Copyright 2018-2019 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
|
||||
License MIT (https://opensource.org/licenses/MIT). */
|
||||
odoo.define("pos_product_available.tour", function(require) {
|
||||
"use strict";
|
||||
|
||||
var tour = require("web_tour.tour");
|
||||
var core = require("web.core");
|
||||
var _t = core._t;
|
||||
|
||||
function open_pos_neworder() {
|
||||
return [
|
||||
{
|
||||
trigger: ".o_pos_kanban button.oe_kanban_action_button",
|
||||
content: _t(
|
||||
"<p>Click to start the point of sale interface. It <b>runs on tablets</b>, laptops, or industrial hardware.</p><p>Once the session launched, the system continues to run without an internet connection.</p>"
|
||||
),
|
||||
position: "bottom",
|
||||
},
|
||||
{
|
||||
content: "Switch to table or make dummy action",
|
||||
trigger: ".table, .order-button.selected",
|
||||
position: "bottom",
|
||||
timeout: 30000,
|
||||
},
|
||||
{
|
||||
content: "waiting for loading to finish",
|
||||
trigger: ".order-button.neworder-button",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function add_product_to_order(product_name) {
|
||||
return [
|
||||
{
|
||||
content: "buy " + product_name,
|
||||
trigger: '.product-list .product-name:contains("' + product_name + '")',
|
||||
},
|
||||
{
|
||||
content: "the " + product_name + " have been added to the order",
|
||||
trigger: '.orderline:contains("' + product_name + '")',
|
||||
run: function() {
|
||||
// It's a check
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function payment(pay_method) {
|
||||
return [
|
||||
{
|
||||
trigger: ".button.pay",
|
||||
content: _t("Open the payment screen"),
|
||||
},
|
||||
{
|
||||
content: "Choose Administrator like a cashier or make a dummy action",
|
||||
trigger:
|
||||
'.modal-dialog.cashier:not(.oe_hidden) .cashier .selection-item:contains("Mitchell Admin"), .payment-screen:not(.oe_hidden) h1:contains("Payment")',
|
||||
},
|
||||
{
|
||||
trigger: '.button.paymentmethod:contains("' + pay_method + '")',
|
||||
content: _t("Click the payment method"),
|
||||
},
|
||||
{
|
||||
trigger: '.payment-screen .input-button.number-char:contains("2")',
|
||||
content: "Set payment amount",
|
||||
},
|
||||
{
|
||||
trigger: '.button.next.highlight:contains("Validate")',
|
||||
content: "Validate payment",
|
||||
},
|
||||
{
|
||||
extra_trigger: ".pos-sale-ticket",
|
||||
trigger: '.button.next.highlight:contains("Next Order")',
|
||||
content: "Check proceeded validation",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function close_pos() {
|
||||
return [
|
||||
{
|
||||
trigger: '.header-button:contains("Close")',
|
||||
content: _t("Close POS"),
|
||||
},
|
||||
{
|
||||
trigger: '.header-button.confirm:contains("Confirm")',
|
||||
content: _t("Close POS"),
|
||||
},
|
||||
{
|
||||
extra_trigger: ".o_pos_kanban button.oe_kanban_action_button",
|
||||
trigger: ".breadcrumb li.active",
|
||||
content: _t(
|
||||
"<p>Click to start the point of sale interface. It <b>runs on tablets</b>, laptops, or industrial hardware.</p><p>Once the session launched, the system continues to run without an internet connection.</p>"
|
||||
),
|
||||
position: "bottom",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function check_quantity(qty) {
|
||||
return [
|
||||
{
|
||||
content: "check quantity",
|
||||
extra_trigger:
|
||||
'.product-list .product:contains("LED Lamp") .qty-tag:contains(' +
|
||||
String(qty) +
|
||||
"):not(.not-available)",
|
||||
trigger: ".order-button.selected",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
var steps = [
|
||||
tour.STEPS.SHOW_APPS_MENU_ITEM,
|
||||
{
|
||||
trigger: '.o_app[data-menu-xmlid="point_of_sale.menu_point_root"]',
|
||||
content: _t(
|
||||
"Ready to launch your <b>point of sale</b>? <i>Click here</i>."
|
||||
),
|
||||
position: "right",
|
||||
edition: "community",
|
||||
},
|
||||
{
|
||||
trigger: '.o_app[data-menu-xmlid="point_of_sale.menu_point_root"]',
|
||||
content: _t(
|
||||
"Ready to launch your <b>point of sale</b>? <i>Click here</i>."
|
||||
),
|
||||
position: "bottom",
|
||||
edition: "enterprise",
|
||||
},
|
||||
];
|
||||
steps = steps.concat(
|
||||
open_pos_neworder(),
|
||||
add_product_to_order("LED Lamp"),
|
||||
payment("Cash (USD)"),
|
||||
close_pos(),
|
||||
open_pos_neworder(),
|
||||
check_quantity(2)
|
||||
);
|
||||
|
||||
tour.register("tour_pos_product_available", {test: true, url: "/web"}, steps);
|
||||
});
|
34
pos_product_available/static/src/xml/pos.xml
Normal file
34
pos_product_available/static/src/xml/pos.xml
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--Copyright 2014-2015 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
|
||||
Copyright 2018-2019 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
|
||||
License MIT (https://opensource.org/licenses/MIT). -->
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t t-extend="Product">
|
||||
<t t-jquery=".product-img" t-operation="append">
|
||||
<t t-if="widget.pos.config.show_qtys && product.type == 'product'">
|
||||
<span
|
||||
t-attf-class="qty-tag #{product.qty_available lte 0 ? 'not-available':''}"
|
||||
>
|
||||
<t t-esc="product.rounded_qty()" />
|
||||
</span>
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
<t t-extend="Orderline">
|
||||
<t t-jquery=".info-list>t:first-child">
|
||||
this.attr('t-if', "line.get_quantity_str() !== '1' || line.selected || line.get_product().qty_available lt line.quantity ");
|
||||
</t>
|
||||
<t t-jquery="t[t-esc='line.get_quantity_str()']" t-operation="after">
|
||||
<t
|
||||
t-if="widget.pos.config.show_qtys && line.get_product().type == 'product'"
|
||||
>
|
||||
<t t-set='qty_available' t-value='line.get_product().qty_available' />
|
||||
(of <span
|
||||
t-attf-class="qty-info #{qty_available lt line.quantity ? 'not-available':''}"
|
||||
>
|
||||
<t t-esc="line.get_product().rounded_qty()" />
|
||||
</span>)
|
||||
</t>
|
||||
</t>
|
||||
</t>
|
||||
</templates>
|
3
pos_product_available/tests/__init__.py
Normal file
3
pos_product_available/tests/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
# License MIT (https://opensource.org/licenses/MIT).
|
||||
|
||||
from . import test_quantities
|
64
pos_product_available/tests/test_quantities.py
Normal file
64
pos_product_available/tests/test_quantities.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
# Copyright 2018 Ivan Yelizariev <https://it-projects.info/team/yelizariev>
|
||||
# Copyright 2018-2019 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
|
||||
# License MIT (https://opensource.org/licenses/MIT).
|
||||
|
||||
import odoo.tests
|
||||
from odoo import _, tools
|
||||
|
||||
|
||||
@odoo.tests.common.at_install(True)
|
||||
@odoo.tests.common.post_install(True)
|
||||
class TestUi(odoo.tests.HttpCase):
|
||||
def test_pos_product_available(self):
|
||||
# needed because tests are run before the module is marked as
|
||||
# installed. In js web will only load qweb coming from modules
|
||||
# that are returned by the backend in module_boot. Without
|
||||
# this you end up with js, css but no qweb.
|
||||
env = self.env
|
||||
env["ir.module.module"].search(
|
||||
[("name", "=", "pos_product_available")], limit=1
|
||||
).state = "installed"
|
||||
|
||||
product = env["product.product"].search([("name", "=", "LED Lamp")], limit=1)
|
||||
product.product_tmpl_id.write({"type": "product"})
|
||||
|
||||
# updating product qty
|
||||
new_quantity = 3
|
||||
company_user = self.env.user.company_id
|
||||
location = (
|
||||
self.env["stock.warehouse"]
|
||||
.search([("company_id", "=", company_user.id)], limit=1)
|
||||
.lot_stock_id
|
||||
)
|
||||
th_qty = product.qty_available
|
||||
inventory = self.env["stock.inventory"].create(
|
||||
{
|
||||
"name": _("INV: %s") % tools.ustr(product.display_name),
|
||||
"filter": "product",
|
||||
"product_id": product.id,
|
||||
"location_id": location.id,
|
||||
"line_ids": [
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_qty": new_quantity,
|
||||
"location_id": location.id,
|
||||
"product_id": product.id,
|
||||
"product_uom_id": product.uom_id.id,
|
||||
"theoretical_qty": th_qty,
|
||||
},
|
||||
)
|
||||
],
|
||||
}
|
||||
)
|
||||
inventory.action_validate()
|
||||
|
||||
# without a delay there might be problems caused by a not yet loaded button's action
|
||||
self.phantom_js(
|
||||
"/web",
|
||||
"odoo.__DEBUG__.services['web_tour.tour'].run('tour_pos_product_available', 500)",
|
||||
"odoo.__DEBUG__.services['web_tour.tour'].tours.tour_pos_product_available.ready",
|
||||
login="admin",
|
||||
timeout=200,
|
||||
)
|
22
pos_product_available/views/views.xml
Normal file
22
pos_product_available/views/views.xml
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!--Copyright 2019 Kolushov Alexandr <https://it-projects.info/team/KolushovAlexandr>
|
||||
License MIT (https://opensource.org/licenses/MIT).-->
|
||||
<odoo>
|
||||
<record id="view_pos_product_available_negative_config_form" model="ir.ui.view">
|
||||
<field name="name">pos.pin.config.form.view</field>
|
||||
<field name="model">pos.config</field>
|
||||
<field name="inherit_id" ref="point_of_sale.pos_config_view_form" />
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='iface_big_scrollbars']/../.." position="after">
|
||||
<div class="col-xs-12 col-md-6 o_setting_box" id="show_prod_qtys">
|
||||
<div class="o_setting_left_pane">
|
||||
<field name="show_qtys" />
|
||||
</div>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="show_qtys" />
|
||||
</div>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
Loading…
Add table
Reference in a new issue