Browse Source

Jan 08: [ADD] Initial Commit 'pos_product_create_edit'

pull/298/merge
Futu6@G@6m#ts 1 year ago
parent
commit
a18b83ef34
  1. 47
      pos_product_create_edit/README.rst
  2. 21
      pos_product_create_edit/__init__.py
  3. 50
      pos_product_create_edit/__manifest__.py
  4. 6
      pos_product_create_edit/doc/RELEASE_NOTES.md
  5. BIN
      pos_product_create_edit/static/description/assets/icons/check.png
  6. BIN
      pos_product_create_edit/static/description/assets/icons/chevron.png
  7. BIN
      pos_product_create_edit/static/description/assets/icons/cogs.png
  8. BIN
      pos_product_create_edit/static/description/assets/icons/consultation.png
  9. BIN
      pos_product_create_edit/static/description/assets/icons/ecom-black.png
  10. BIN
      pos_product_create_edit/static/description/assets/icons/education-black.png
  11. BIN
      pos_product_create_edit/static/description/assets/icons/hotel-black.png
  12. BIN
      pos_product_create_edit/static/description/assets/icons/license.png
  13. BIN
      pos_product_create_edit/static/description/assets/icons/lifebuoy.png
  14. BIN
      pos_product_create_edit/static/description/assets/icons/manufacturing-black.png
  15. BIN
      pos_product_create_edit/static/description/assets/icons/pos-black.png
  16. BIN
      pos_product_create_edit/static/description/assets/icons/puzzle.png
  17. BIN
      pos_product_create_edit/static/description/assets/icons/restaurant-black.png
  18. BIN
      pos_product_create_edit/static/description/assets/icons/service-black.png
  19. BIN
      pos_product_create_edit/static/description/assets/icons/trading-black.png
  20. BIN
      pos_product_create_edit/static/description/assets/icons/training.png
  21. BIN
      pos_product_create_edit/static/description/assets/icons/update.png
  22. BIN
      pos_product_create_edit/static/description/assets/icons/user.png
  23. BIN
      pos_product_create_edit/static/description/assets/icons/wrench.png
  24. BIN
      pos_product_create_edit/static/description/assets/misc/categories.png
  25. BIN
      pos_product_create_edit/static/description/assets/misc/check-box.png
  26. BIN
      pos_product_create_edit/static/description/assets/misc/compass.png
  27. BIN
      pos_product_create_edit/static/description/assets/misc/corporate.png
  28. BIN
      pos_product_create_edit/static/description/assets/misc/customer-support.png
  29. BIN
      pos_product_create_edit/static/description/assets/misc/cybrosys-logo.png
  30. BIN
      pos_product_create_edit/static/description/assets/misc/features.png
  31. BIN
      pos_product_create_edit/static/description/assets/misc/logo.png
  32. BIN
      pos_product_create_edit/static/description/assets/misc/pictures.png
  33. BIN
      pos_product_create_edit/static/description/assets/misc/pie-chart.png
  34. BIN
      pos_product_create_edit/static/description/assets/misc/right-arrow.png
  35. BIN
      pos_product_create_edit/static/description/assets/misc/star.png
  36. BIN
      pos_product_create_edit/static/description/assets/misc/support.png
  37. BIN
      pos_product_create_edit/static/description/assets/misc/whatsapp.png
  38. BIN
      pos_product_create_edit/static/description/assets/modules/1.png
  39. BIN
      pos_product_create_edit/static/description/assets/modules/2.png
  40. BIN
      pos_product_create_edit/static/description/assets/modules/3.gif
  41. BIN
      pos_product_create_edit/static/description/assets/modules/3.png
  42. BIN
      pos_product_create_edit/static/description/assets/modules/4.png
  43. BIN
      pos_product_create_edit/static/description/assets/modules/5.png
  44. BIN
      pos_product_create_edit/static/description/assets/modules/6.png
  45. BIN
      pos_product_create_edit/static/description/assets/screenshots/1.jpg
  46. BIN
      pos_product_create_edit/static/description/assets/screenshots/2.png
  47. BIN
      pos_product_create_edit/static/description/assets/screenshots/3.png
  48. BIN
      pos_product_create_edit/static/description/assets/screenshots/4.png
  49. BIN
      pos_product_create_edit/static/description/assets/screenshots/hero.gif
  50. BIN
      pos_product_create_edit/static/description/banner.png
  51. BIN
      pos_product_create_edit/static/description/icon.png
  52. 651
      pos_product_create_edit/static/description/index.html
  53. 37
      pos_product_create_edit/static/src/css/ProductList.css
  54. 143
      pos_product_create_edit/static/src/js/ProductCreatePopup.js
  55. 148
      pos_product_create_edit/static/src/js/ProductEditPopup.js
  56. 27
      pos_product_create_edit/static/src/js/ProductLine.js
  57. 64
      pos_product_create_edit/static/src/js/pos_product_screen.js
  58. 88
      pos_product_create_edit/static/src/js/productScreen.js
  59. 10
      pos_product_create_edit/static/src/xml/product_button_templates.xml
  60. 100
      pos_product_create_edit/static/src/xml/product_create_popup_templates.xml
  61. 97
      pos_product_create_edit/static/src/xml/product_edit_popup_templates.xml
  62. 45
      pos_product_create_edit/static/src/xml/product_line_templates.xml
  63. 80
      pos_product_create_edit/static/src/xml/product_list_screen_templates.xml
  64. 14
      pos_product_create_edit/views/assets.xml

47
pos_product_create_edit/README.rst

@ -0,0 +1,47 @@
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
POS Product Create Edit
=================================
This module helps you create products directly from POS, or you can edit the
products from point of sale.
Configuration
=============
* No additional configurations needed
Company
-------
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__
License
-------
General Public License, Version 3 (AGPL v3).
(https://www.gnu.org/licenses/agpl-3.0-standalone.html)
Credits
-------
Developers: (V14) Mruthul Raj,Contact: odoo@cybrosys.com
Contacts
--------
* Mail Contact : odoo@cybrosys.com
* Website : https://cybrosys.com
Bug Tracker
-----------
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported.
Maintainer
==========
.. image:: https://cybrosys.com/images/logo.png
:target: https://cybrosys.com
This module is maintained by Cybrosys Technologies.
For support and more information, please visit `Our Website <https://cybrosys.com/>`__
Further information
===================
HTML Description: `<static/description/index.html>`__

21
pos_product_create_edit/__init__.py

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Mruthul (<https://www.cybrosys.com>)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
#############################################################################

50
pos_product_create_edit/__manifest__.py

@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
#############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Mruthul (<https://www.cybrosys.com>)
#
# You can modify it under the terms of the GNU LESSER
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
#
# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
#
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
# (LGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
#############################################################################
{
'name': 'POS Product Create Edit',
'version': '14.0.1.0.0',
'category': 'Point of Sale',
'summary': 'Create or edit products directly from the Point'
' of Sale interface.',
'description': 'This module allows users to create or edit products '
'directly from the Point of Sale (POS) interface.'
' It provides a convenient way to manage products'
' on the fly without navigating to the backend.',
'author': 'Cybrosys Techno Solutions',
'company': 'Cybrosys Techno Solutions',
'maintainer': 'Cybrosys Techno Solutions',
'website': 'https://www.cybrosys.com',
'depends': ['point_of_sale'],
'data': ['views/assets.xml'],
'qweb': [
'static/src/xml/product_button_templates.xml',
'static/src/xml/product_create_popup_templates.xml',
'static/src/xml/product_edit_popup_templates.xml',
'static/src/xml/product_line_templates.xml',
'static/src/xml/product_list_screen_templates.xml',
],
'images': ['static/description/banner.png'],
'license': 'AGPL-3',
'installable': True,
'auto_install': False,
'application': False,
}

6
pos_product_create_edit/doc/RELEASE_NOTES.md

@ -0,0 +1,6 @@
## Module <pos_product_create_edit>
#### 08.01.2024
#### Version 14.0.1.0.0
#### ADD
- Initial Commit for POS Product Create Edit

BIN
pos_product_create_edit/static/description/assets/icons/check.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
pos_product_create_edit/static/description/assets/icons/chevron.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

BIN
pos_product_create_edit/static/description/assets/icons/cogs.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

BIN
pos_product_create_edit/static/description/assets/icons/consultation.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
pos_product_create_edit/static/description/assets/icons/ecom-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

BIN
pos_product_create_edit/static/description/assets/icons/education-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

BIN
pos_product_create_edit/static/description/assets/icons/hotel-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

BIN
pos_product_create_edit/static/description/assets/icons/license.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
pos_product_create_edit/static/description/assets/icons/lifebuoy.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
pos_product_create_edit/static/description/assets/icons/manufacturing-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

BIN
pos_product_create_edit/static/description/assets/icons/pos-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 B

BIN
pos_product_create_edit/static/description/assets/icons/puzzle.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

BIN
pos_product_create_edit/static/description/assets/icons/restaurant-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

BIN
pos_product_create_edit/static/description/assets/icons/service-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 839 B

BIN
pos_product_create_edit/static/description/assets/icons/trading-black.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 B

BIN
pos_product_create_edit/static/description/assets/icons/training.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 627 B

BIN
pos_product_create_edit/static/description/assets/icons/update.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
pos_product_create_edit/static/description/assets/icons/user.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 988 B

BIN
pos_product_create_edit/static/description/assets/icons/wrench.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
pos_product_create_edit/static/description/assets/misc/categories.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
pos_product_create_edit/static/description/assets/misc/check-box.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
pos_product_create_edit/static/description/assets/misc/compass.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
pos_product_create_edit/static/description/assets/misc/corporate.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
pos_product_create_edit/static/description/assets/misc/customer-support.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
pos_product_create_edit/static/description/assets/misc/cybrosys-logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
pos_product_create_edit/static/description/assets/misc/features.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 B

BIN
pos_product_create_edit/static/description/assets/misc/logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
pos_product_create_edit/static/description/assets/misc/pictures.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
pos_product_create_edit/static/description/assets/misc/pie-chart.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
pos_product_create_edit/static/description/assets/misc/right-arrow.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 967 B

BIN
pos_product_create_edit/static/description/assets/misc/star.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
pos_product_create_edit/static/description/assets/misc/support.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

BIN
pos_product_create_edit/static/description/assets/misc/whatsapp.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
pos_product_create_edit/static/description/assets/modules/1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
pos_product_create_edit/static/description/assets/modules/2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
pos_product_create_edit/static/description/assets/modules/3.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

BIN
pos_product_create_edit/static/description/assets/modules/3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
pos_product_create_edit/static/description/assets/modules/4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
pos_product_create_edit/static/description/assets/modules/5.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
pos_product_create_edit/static/description/assets/modules/6.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
pos_product_create_edit/static/description/assets/screenshots/1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

BIN
pos_product_create_edit/static/description/assets/screenshots/2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

BIN
pos_product_create_edit/static/description/assets/screenshots/3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

BIN
pos_product_create_edit/static/description/assets/screenshots/4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

BIN
pos_product_create_edit/static/description/assets/screenshots/hero.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

BIN
pos_product_create_edit/static/description/banner.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

BIN
pos_product_create_edit/static/description/icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

651
pos_product_create_edit/static/description/index.html

@ -0,0 +1,651 @@
<div style="background-color: #714B67; height: 810px; width: 100%; padding: 15px; position: relative;">
<!-- TITLE BAR -->
<div class="d-flex align-items-center justify-content-between"
style="border-bottom: 1px solid #875A7B; padding: 15px; display: flex; justify-content: space-between; align-items: center;">
<img src="assets/misc/cybrosys-logo.png" width="42" height="42"
style="width: 42px; height: 42px;"/>
<div>
<div
style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
class="mr-2">
<i class="fa fa-check mr-1"></i>Community
</div>
<div
style="color: #875A7B; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
class="mr-2">
<i class="fa fa-check mr-1"></i>Enterprise
</div>
<div
style="color: #017E84; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
class="mr-2">
<i class="fa fa-check mr-1"></i>Odoo.sh
</div>
</div>
</div>
<!-- END OF TITLE BAR -->
<div class="container">
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12">
<!-- APP HERO -->
<h1 style="color: #FFFFFF; font-weight: bolder; font-size: 50px; text-align: center; margin-top: 50px;">
POS Product Create Edit</h1>
<p style="color:#FFFFFF; padding: 8px 15px; text-align: center; font-size: 24px;">
You Can Directly Edit or Create New Product From Point of
Sale.</p>
<!-- END OF APP HERO -->
<img src="assets/screenshots/hero.gif" class="img-responsive"
style="width: 100%; margin-left: auto; margin-right: auto;"/>
</div>
</div>
</div>
</div>
<!-- NAVIGATION SECTION -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px; margin-top: 300px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/compass.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Explore This
Module</h2>
</div>
<div class="row my-4" style="font-family: 'Montserrat', sans-serif;">
<div class="col-sm-12 col-md-6 my-3">
<a href="#overview">
<div class="d-flex justify-content-between align-items-center"
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
<div>
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Overview</span>
<span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">Learn
more about this
module</span>
</div>
<img src="assets/misc/right-arrow.png" width="36" height="36"/>
</div>
</a>
</div>
<div class="col-sm-12 col-md-6 my-3">
<a href="#features">
<div class="d-flex justify-content-between align-items-center"
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
<div>
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Features</span>
<span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">View
features of this
module</span>
</div>
<img src="assets/misc/right-arrow.png" width="36" height="36"/>
</div>
</a>
</div>
<div class="col-sm-12 col-md-6 my-3">
<a href="#screenshots">
<div class="d-flex justify-content-between align-items-center"
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
<div>
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Screenshots</span>
<span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">View
screenshots for this
module</span>
</div>
<img src="assets/misc/right-arrow.png" width="36" height="36"/>
</div>
</a>
</div>
</div>
<!-- END OF NAVIGATION SECTION -->
<!-- OVERVIEW SECTION -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="overview">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/pie-chart.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Overview
</h2>
</div>
<div class="row"
style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;">
<div class="col-sm-12 py-4">
This module helps to create and edit products directly from the pos
</div>
</div>
<!-- END OF OVERVIEW SECTION -->
<!-- FEATURES SECTION -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="features">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/features.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Features
</h2>
</div>
<div class="row"
style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;">
<div class="col-sm-12 col-md-6">
<div class="d-flex align-items-center"
style="margin-top: 40px; margin-bottom: 40px">
<img src="assets/misc/check-box.png" class="mr-2"/>
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Available in Odoo 14.0
Community and Enterprise.</span>
</div>
<div class="d-flex align-items-center"
style="margin-top: 30px; margin-bottom: 30px">
<img src="assets/misc/check-box.png" class="mr-2"/>
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Create new products directly from point of sale.</span>
</div>
</div>
<div class="col-sm-12 col-md-6">
<div class="d-flex align-items-center"
style="margin-top: 30px; margin-bottom: 30px">
<img src="assets/misc/check-box.png" class="mr-2"/>
<span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Edit products directly from point of sale.</span>
</div>
</div>
</div>
<!-- END OF FEATURES SECTION -->
<!-- SCREENSHOTS SECTION -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;"
id="screenshots">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/pictures.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Screenshots
</h2>
</div>
<div class="row">
<div class="col-sm-12">
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
New Product Screen Button
</h3>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
This button will show All products.Form this screen you can
create new product, or you can edit already existing product.
</p>
<img src="assets/screenshots/1.jpg" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Product Edit Button
</h3>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;"></p>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
On the product screen you can see All products Listed. Each
product has an edit button on the right side. By clicking on the
button you can edit the product directly from pos.</p>
<img src="assets/screenshots/2.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Product Edit popup
</h3>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
When you click on the edit button of any product .The product
details will show as a popup.</p>
<img src="assets/screenshots/3.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Create New Product</h3>
<p style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
On the product screen we have a dedicated Create button.
Clicking on the button will show a popup to fill with details of
new product.</p>
<img src="assets/screenshots/4.png" class="img-thumbnail">
</div>
</div>
</div>
<!-- END OF SCREENSHOTS SECTION -->
<!-- SUGGESTED PRODUCTS -->
<div class="row">
<div class="col-lg-12 d-flex flex-column justify-content-center"
style="text-align: center; padding: 2.5rem 1rem !important;">
<h2 style="color: #212529 !important;">Suggested Products</h2>
<hr
style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;"/>
<div id="demo1" class="row carousel slide" data-ride="carousel">
<!-- The slideshow -->
<div class="carousel-inner">
<div class="carousel-item active" style="min-height:0px">
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/14.0/customer_sequence/"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-top-left-radius:10px; border-top-right-radius:10px"
src="./assets/modules/1.png">
</div>
</a>
</div>
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/14.0/barcode_scanning_sale_purchase/"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-top-left-radius:10px; border-top-right-radius:10px"
src="./assets/modules/2.png">
</div>
</a>
</div>
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/14.0/base_accounting_kit/"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-top-left-radius:10px; border-top-right-radius:10px"
src="./assets/modules/3.png">
</div>
</a>
</div>
</div>
<div class="carousel-item" style="min-height:0px">
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/14.0/product_return_pos/"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-top-left-radius:10px; border-top-right-radius:10px"
src="./assets/modules/4.png">
</div>
</a>
</div>
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/14.0/point_of_sale_logo"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-top-left-radius:10px; border-top-right-radius:10px"
src="./assets/modules/5.png">
</div>
</a>
</div>
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/14.0/invoice_format_editor/"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-top-left-radius:10px; border-top-right-radius:10px"
src="./assets/modules/6.png">
</div>
</a>
</div>
</div>
</div>
<!-- Left and right controls -->
<a class="carousel-control-prev" href="#demo1" data-slide="prev"
style="left:-25px;width: 35px;color: #000;"> <span
class="carousel-control-prev-icon"><i
class="fa fa-chevron-left"
style="font-size:24px"></i></span> </a> <a
class="carousel-control-next" href="#demo1"
data-slide="next"
style="right:-25px;width: 35px;color: #000;">
<span class="carousel-control-next-icon"><i
class="fa fa-chevron-right"
style="font-size:24px"></i></span>
</a>
</div>
</div>
</div>
<!-- END OF SUGGESTED PRODUCTS -->
<!-- OUR SERVICES -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/star.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Our Services
</h2>
</div>
<div class="container my-5">
<div class="row">
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #1dd1a1 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/cogs.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Customization</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #ff6b6b !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/wrench.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Implementation</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #6462CD !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/lifebuoy.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Support</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #ffa801 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/user.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Hire
Odoo
Developer</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #54a0ff !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/puzzle.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Integration</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #6d7680 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/update.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Migration</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #786fa6 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/consultation.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Consultancy</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #f8a5c2 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/training.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Implementation</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #e6be26 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/license.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Licensing Consultancy</h6>
</div>
</div>
</div>
<!-- END OF OUR SERVICES -->
<!-- OUR INDUSTRIES -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/corporate.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Our
Industries
</h2>
</div>
<div class="container my-5">
<div class="row">
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/trading-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Trading
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Easily procure
and
sell your products</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/pos-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
POS
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Easy
configuration
and convivial experience</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/education-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Education
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
A platform for
educational management</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/manufacturing-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Manufacturing
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Plan, track and
schedule your operations</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/ecom-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
E-commerce &amp; Website
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Mobile
friendly,
awe-inspiring product pages</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/service-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Service Management
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Keep track of
services and invoice</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/restaurant-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Restaurant
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Run your bar or
restaurant methodically</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/hotel-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Hotel Management
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
An
all-inclusive
hotel management application</p>
</div>
</div>
</div>
</div>
<!-- END OF OUR INDUSTRIES -->
<!-- SUPPORT -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/customer-support.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Support
</h2>
</div>
<div class="container mt-5">
<div class="row">
<div class="col-sm-12 col-md-6">
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;">
<div class="mr-4 d-flex justify-content-center align-items-center"
style="background-color: #714B67; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;">
<img src="assets/misc/support.png" height="48" width="48"
style="width: 42px; height: 42px;"/>
</div>
<div>
<h4>Need Help?</h4>
<p style="line-height: 100%;">Got questions or need help?
Get in touch.</p>
<a href="mailto:odoo@cybrosys.com">
<p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;">
odoo@cybrosys.com</p>
</a>
</div>
</div>
</div>
<div class="col-sm-12 col-md-6">
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;">
<div class="mr-4 d-flex justify-content-center align-items-center"
style="background-color: #2AC44D; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;">
<img src="assets/misc/whatsapp.png" height="52" width="52"
style="width: 52px; height: 52px;"/>
</div>
<div>
<h4>WhatsApp</h4>
<p style="line-height: 100%;">Say hi to us on WhatsApp!</p>
<a href="https://api.whatsapp.com/send?phone=918606827707">
<p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;">
+91 86068
27707</p>
</a>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12 my-5 d-flex justify-content-center align-items-center">
<img src="assets/misc/logo.png" width="144" height="31"
style="width:144px; height: 31px; margin-top: 40px;"/>
</div>
</div>
</div>
<!-- END OF SUPPORT -->

37
pos_product_create_edit/static/src/css/ProductList.css

@ -0,0 +1,37 @@
button.edit_product{
border-radius:5px;
}
i.fa.fa-pencil{
font-size:20px;
}
.full-content{
overflow:scroll;
}
img.product_img {
max-width:60px;
}
label.field_label{
padding:3%;
}
.field_div{
margin-bottom:5px;
}
select.form-control{
text-align: left;
display: inline-block;
overflow: hidden;
background: white;
min-height: 44px;
font-family: "Lato";
font-size: 20px;
color: #444;
padding: 10px;
border-radius: 3px;
border: none;
box-shadow: 0px 0px 0px 1px gainsboro inset;
box-sizing: border-box;
width: 85%;
}
i.fa.fa-plus.create_btn{
margin-right:5px;
}

143
pos_product_create_edit/static/src/js/ProductCreatePopup.js

@ -0,0 +1,143 @@
odoo.define("pos_product_create_edit.ProductCreatePopup", function(require) {
"use strict";
const AbstractAwaitablePopup = require("point_of_sale.AbstractAwaitablePopup");
const Registries = require("point_of_sale.Registries");
const { isRpcError } = require('point_of_sale.utils');
const { useListener } = require('web.custom_hooks');
const { Gui } = require('point_of_sale.Gui');
let img = "";
let base64_img = "";
class CreateProductPopup extends AbstractAwaitablePopup {
setup() {
super.setup();
useListener("change", "#img_field", this._onChangeImgField.bind(this));
}
/**
* Handles the change event of the image field.
* Updates the selected image and displays it in the popup.
* @param {Event} ev - The change event object.
*/
async _onChangeImgField(ev) {
try {
let current = ev.target.files[0];
const reader = new FileReader();
reader.readAsDataURL(current);
reader.onload = async function() {
img = reader.result;
base64_img = reader.result.toString().replace(/^data:(.*,)?/, "");
const myTimeout = setTimeout(() => {
$(ev.target.parentElement.previousElementSibling.childNodes[0]).hide();
let element =
"<img src=" + img + " style='max-width: 150px;max-height: 150px;'/>";
$(ev.target.parentElement.previousElementSibling.childNodes[0].parentElement).append($(element));
}, 100);
};
reader.onerror = function(error) {
console.log(error);
};
} catch (error) {
if (isRpcError(error) && error.message.code < 0) {
Gui.showPopup('ErrorPopup', {
title: this.comp.env._t('Network Error'),
body: this.comp.env._t('Cannot access Product screen if offline.'),
});
Gui.setSyncStatus('error');
} else {
throw error;
}
}
}
/**
* Function for validating number.
*/
async _numberCheck(ev){
ev.target.value = ev.target.value.replace(/[^0-9.]/g, '');
}
/**
* Confirms the creation of the product.
* Sends a create request to the server with the entered product information.
* Reloading the page after successful creation.
*/
async confirm(ev) {
let img = $(ev.target.parentElement.parentElement.previousElementSibling.firstChild.firstElementChild.childNodes[2].children[1]).val();
let name = $(ev.target.parentElement.parentElement.previousElementSibling.firstChild.firstElementChild.childNodes[3].children[1]).val();
let price = $(ev.target.parentElement.parentElement.previousElementSibling.firstChild.firstElementChild.childNodes[4].children[1]).val();
let cost = $(ev.target.parentElement.parentElement.previousElementSibling.firstChild.firstElementChild.childNodes[5].children[1]).val();
let category = $(ev.target.parentElement.parentElement.previousElementSibling.firstChild.firstElementChild.childNodes[8].children[1]).val();
let barcode = $(ev.target.parentElement.parentElement.previousElementSibling.firstChild.firstElementChild.childNodes[6].children[1]).val();
let default_code = $(ev.target.parentElement.parentElement.previousElementSibling.firstChild.firstElementChild.childNodes[7].children[1]).val();
let values = {};
if (base64_img) {
values["image_1920"] = base64_img;
}
if (name) {
values["name"] = name;
}else{
Gui.showPopup('ErrorPopup', {
title: this.env._t('Name Mandatory'),
body: this.env._t('Forgot to add name?'),
});
return false;
}
if (cost) {
values["standard_price"] = cost;
}
if (price) {
values["lst_price"] = price;
}
if (category) {
if (category == 0){
Gui.showPopup('ErrorPopup', {
title: this.env._t('Mismatch Category'),
body: this.env._t('You cannot add to root category.'),
});
return false;
}else{
values["pos_categ_id"] = category;
}
}
if (barcode) {
values["barcode"] = barcode;
}
if (default_code) {
values["default_code"] = default_code;
}
values["available_in_pos"] = true;
try {
const result = await this.rpc({
model: "product.product",
method: "create",
args: [values],
});
if (result) {
Gui.setSyncStatus(_.str.sprintf(this.env._t('%s - Product Created'), values["name"]), 3000);
window.location.reload();
} else {
return False;
}
this.props.resolve({
confirmed: false,
payload: null
});
this.trigger('close-popup');
} catch (error) {
if (isRpcError(error) && error.message.code < 0) {
Gui.showPopup('ErrorPopup', {
title: this.comp.env._t('Network Error'),
body: this.comp.env._t('Cannot access Product screen if offline.'),
});
Gui.setSyncStatus('error');
} else {
throw error;
}
}
}
}
CreateProductPopup.template = "CreateProductPopup";
Registries.Component.add(CreateProductPopup);
return CreateProductPopup;
});

148
pos_product_create_edit/static/src/js/ProductEditPopup.js

@ -0,0 +1,148 @@
odoo.define("pos_product_create_edit.ProductEditPopup", function(require) {
"use strict";
const AbstractAwaitablePopup = require("point_of_sale.AbstractAwaitablePopup");
const Registries = require("point_of_sale.Registries");
const { useListener } = require('web.custom_hooks');
const { isRpcError } = require('point_of_sale.utils');
const { Gui } = require('point_of_sale.Gui');
let base64_img = "";
let img = "";
/**
* EditProductPopup is a popup component used for editing product details in Odoo POS.
*/
class EditProductPopup extends AbstractAwaitablePopup {
setup() {
super.setup();
useListener("change", "#img_field", this._onChangeImgField.bind(this));
}
/**
* Handle the change event of the image field.
* @param {Event} ev - The change event.
*/
async _onChangeImgField(ev) {
try {
let current = ev.target.files[0];
const reader = new FileReader();
reader.readAsDataURL(current);
reader.onload = async function() {
img = reader.result;
base64_img = reader.result.toString().replace(/^data:(.*,)?/, "");
const myTimeout = setTimeout(() => {
$(ev.target.parentElement.previousElementSibling.childNodes[0]).hide();
let element =
"<img src=" +
img +
" style='max-width: 150px;max-height: 150px;'/>";
$(ev.target.parentElement.previousElementSibling.childNodes[0].parentElement).append($(element));
}, 100);
};
reader.onerror = function(error) {
console.log("error", error);
};
} catch (error) {
if (isRpcError(error) && error.message.code < 0) {
Gui.showPopup('ErrorPopup', {
title: this.comp.env._t('Network Error'),
body: this.comp.env._t('Cannot access Product screen if offline.'),
});
Gui.setSyncStatus('error');
} else {
throw error;
}
}
}
/**
* Function for validating number.
*/
async _numberCheck(ev){
ev.target.value = ev.target.value.replace(/[^0-9.]/g, '');
}
/**
* Confirm the changes made to the product.
*/
async confirm(ev) {
let values = {};
if (base64_img) {
values["image_1920"] = base64_img;
}
if ($(ev.target.parentElement.parentElement.previousElementSibling.firstChild.firstElementChild.childNodes[3].childNodes[1]).val() != this.props.product.display_name) {
values["name"] = $(ev.target.parentElement.parentElement.previousElementSibling.firstChild.firstElementChild.childNodes[3].childNodes[1]).val();
}
if ($(ev.target.parentElement.parentElement.previousElementSibling.firstChild.firstElementChild.childNodes[4].childNodes[1]).val() != this.props.product.list_price) {
values["lst_price"] = $(ev.target.parentElement.parentElement.previousElementSibling.firstChild.firstElementChild.childNodes[4].childNodes[1]).val();
}
if ($(ev.target.parentElement.parentElement.previousElementSibling.firstChild.firstElementChild.childNodes[7].childNodes[1]).val()) {
values["pos_categ_id"] = parseInt($(ev.target.parentElement.parentElement.previousElementSibling.firstChild.firstElementChild.childNodes[7].childNodes[1]).val());
}
if ($(ev.target.parentElement.parentElement.previousElementSibling.firstChild.firstElementChild.childNodes[6].childNodes[1]).val()) {
values["barcode"] = $(ev.target.parentElement.parentElement.previousElementSibling.firstChild.firstElementChild.childNodes[6].childNodes[1]).val();
}
if ($(ev.target.parentElement.parentElement.previousElementSibling.firstChild.firstElementChild.childNodes[5].childNodes[1]).val()) {
values["default_code"] = $(ev.target.parentElement.parentElement.previousElementSibling.firstChild.firstElementChild.childNodes[5].childNodes[1]).val();
}
try {
const result = await this.rpc({
model: "product.product",
method: "write",
args: [this.props.product.id, values],
});
if (result) {
if (values['name']) {
this.props.product.display_name = values['name'];
}
if (values['lst_price']) {
this.props.product.lst_price = values['lst_price'];
}
if (values['barcode']) {
this.props.product.lst_price = values['barcode'];
}
if (values['default_code']) {
this.props.product.lst_price = values['default_code'];
}
if (values['pos_categ_id']) {
if (values["pos_categ_id"] == 0) {
Gui.showPopup('ErrorPopup', {
title: this.env._t('Mismatch Category'),
body: this.env._t('You cannot add to root category.'),
});
} else {
this.props.product.pos_categ_id = [
values["pos_categ_id"],
];
}
}
Gui.setSyncStatus(_.str.sprintf(this.env._t('%s - Product Created'), values['name']), 3000);
window.location.reload();
} else {
this.showNotification(_.str.sprintf(this.env._t("%s - Product Update Failed"), values['name']), 3000);
}
this.props.resolve({
confirmed: false,
payload: null
});
this.trigger('close-popup');
} catch (error) {
if (isRpcError(error) && error.message.code < 0) {
Gui.showPopup('ErrorPopup', {
title: this.comp.env._t('Network Error'),
body: this.comp.env._t('Cannot access Product screen if offline.'),
});
Gui.setSyncStatus('error');
} else {
throw error;
}
}
}
/**
* Get the URL of the product image.
* @returns {string} The URL of the product image.
*/
get imageUrl() {
const product = this.props.product;
return `/web/image?model=product.product&field=image_128&id=${product.id}&unique=${product.write_date}`;
}
}
EditProductPopup.template = "EditProductPopup";
Registries.Component.add(EditProductPopup);
return EditProductPopup;
});

27
pos_product_create_edit/static/src/js/ProductLine.js

@ -0,0 +1,27 @@
odoo.define("pos_product_create_edit.ProductLine", function(require) {
"use strict";
const PosComponent = require("point_of_sale.PosComponent");
const Registries = require("point_of_sale.Registries");
class ProductLine extends PosComponent {
/**
* Get the URL of the product image.
* @returns {string} The URL of the product image.
*/
get imageUrl() {
const product = this.props.product;
return `/web/image?model=product.product&field=image_128&id=${product.id}&unique=${product.write_date}`;
}
/**
* Open the EditProductPopup to edit the current product.
*/
async editCurrentProduct() {
await this.showPopup("EditProductPopup", {
product: this.props.product,
});
}
}
ProductLine.template = "ProductLine";
Registries.Component.add(ProductLine);
return ProductLine;
});

64
pos_product_create_edit/static/src/js/pos_product_screen.js

@ -0,0 +1,64 @@
odoo.define("pos_product_create_edit.pos_product_screen", function(require) {
"use strict";
const PosComponent = require("point_of_sale.PosComponent");
const ProductScreen = require("point_of_sale.ProductScreen");
const { useListener } = require('web.custom_hooks');
const Registries = require("point_of_sale.Registries");
const { isRpcError } = require('point_of_sale.utils');
class SetProductListButton extends PosComponent {
/**
* Sets up the component.
* Attaches a click listener to the button.
*/
setup() {
super.setup();
useListener("click", this.onClick);
}
/**
* Retrieves the product list based on the selected category ID.
* @returns {Array} The sorted product list.
*/
get productsList() {
let list = [];
list = this.env.pos.db.get_product_by_category(
this.env.pos.selectedCategoryId
);
return list.sort(function(a, b) {
return a.display_name.localeCompare(b.display_name);
});
}
/**
* Handles the click event of the button.
* Shows the product list screen.
*/
async onClick() {
try {
let list = this.productsList;
const screen = "ProductListScreen";
this.showScreen(screen);
} catch (error) {
if (isRpcError(error) && error.message.code < 0) {
Gui.showPopup('ErrorPopup', {
title: this.comp.env._t('Network Error'),
body: this.comp.env._t('Cannot access Product screen if offline.'),
});
Gui.setSyncStatus('error');
} else {
throw error;
}
}
}
}
/**
* Adds the custom button to the ProductScreen control buttons.
*/
SetProductListButton.template = "SetProductListButton";
ProductScreen.addControlButton({
component: SetProductListButton,
condition: function() {
return true;
},
});
Registries.Component.add(SetProductListButton);
return SetProductListButton;
});

88
pos_product_create_edit/static/src/js/productScreen.js

@ -0,0 +1,88 @@
odoo.define("pos_product_create_edit.productScreen", function (require) {
"use strict";
const Registries = require("point_of_sale.Registries");
const PosComponent = require("point_of_sale.PosComponent");
const { useRef } = owl.hooks;
class ProductListScreen extends PosComponent {
constructor() {
super(...arguments);
this.searchWordInputRef = useRef("search-word-input-product");
this.state = {
search: null,
};
}
/**
* Open the CreateProductPopup to create a new product.
*/
createProduct() {
this.showPopup("CreateProductPopup", {
product: this.props.product,
});
}
/**
* Get the list of products to display.
* @returns {Array} The list of products.
*/
get products() {
let list;
if (this.state.search && this.state.search.trim() !== "") {
list = this.env.pos.db.search_product_in_category(
0,
this.state.search.trim()
);
} else {
list = this.env.pos.db.get_product_by_category(0);
}
return list.sort(function(a, b) {
return a.display_name.localeCompare(b.display_name);
});
}
/**
* Update the product list based on the search input.
* @param {Event} event - The input event.
*/
async updateProductList(event) {
this.state.search = event.target.value;
if (event.code === "Enter") {
await this._onPressEnterKey();
} else {
this.render(true);
}
}
/**
* Handle the press of the Enter key in the search input.
*/
async _onPressEnterKey() {
if (!this.state.search) return;
if (!this.env.pos.isEveryProductLoaded) {
const result = await this.products;
this.showNotification(
_.str.sprintf(
this.env._t('%s Product(s) found for "%s".'),
result.length,
this.state.search
),
3000
);
if (!result.length) this._clearSearch();
}
}
/**
* Clear the search input and reset the search state.
*/
_clearSearch() {
this.searchWordInputRef.el.value = "";
this.state.search = "";
this.render(true);
}
/**
* Go back to the ProductScreen.
*/
back() {
this.showScreen("ProductScreen");
}
}
ProductListScreen.template = "ProductListScreen";
Registries.Component.add(ProductListScreen);
return ProductListScreen;
});

10
pos_product_create_edit/static/src/xml/product_button_templates.xml

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<!-- Template for the SetProductListButton component -->
<t t-name="SetProductListButton" owl="1">
<div class="control-button o_product_list_button">
<i class="fa fa-pencil-square" role="img" aria-label="Products"
title="Products" /> Products
</div>
</t>
</templates>

100
pos_product_create_edit/static/src/xml/product_create_popup_templates.xml

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="CreateProductPopup" owl="1">
<!-- Template for the CreateProductPopup component -->
<div role="dialog" class="modal-dialog">
<div class="popup product-line-popup" style="max-width: 684px;">
<main class="body">
<div class="create-product-popup">
<header>
<h3>
<span>Create Product</span>
<i class="fa fa-times" style="float:right"
t-on-click="cancel"/>
<hr/>
</h3>
<div class="product-img-create-popup">
<!-- Product image -->
<img t-att-src="imageUrl"
id="img_url_tag_create"/>
</div>
<div class="field_div"
style="display:flex; margin-bottom: 15px;">
<label for="img_field" class="field_label"
style="margin-right:10px; margin-top: 10px; width: 120px; display: inline-block; text-align: left;">Image</label>
<input type="file" id="img_field"
class="field_input" name="img_field"
accept="image/*"/>
</div>
<div class="field_div"
style="display:flex; margin-bottom: 15px;">
<label for="display_name" class="field_label"
style="margin-right:10px; margin-top: 10px; width: 120px; display: inline-block; text-align: left;">Name</label>
<input type="text" name="display_name"
required="true"
class="field_input" id="display_name"/>
</div>
<div class="field_div"
style="display:flex; margin-bottom: 15px;">
<label for="list_price" class="field_label"
style="margin-right:10px; margin-top: 10px; width: 120px; display: inline-block; text-align: left;">Price</label>
<input type="text" name="list_price"
t-on-keyup="_numberCheck"
class="field_input" id="list_price"/>
</div>
<div class="field_div"
style="display:flex; margin-bottom: 15px;">
<label for="list_price" class="field_label"
style="margin-right:10px; margin-top: 10px; width: 120px; display: inline-block; text-align: left;">Cost</label>
<input type="text" name="cost_price"
t-on-keyup="_numberCheck"
class="field_input" id="cost_price"/>
</div>
<div class="field_div"
style="display:flex; margin-bottom: 15px;">
<label for="barcode" class="field_label"
style="margin-right:10px; margin-top: 10px; width: 120px; display: inline-block; text-align: left;">Barcode</label>
<input type="text" name="barcode"
class="field_input" id="barcode"/>
</div>
<div class="field_div"
style="display:flex; margin-bottom: 15px;">
<label for="default_code" class="field_label"
style="margin-right:10px; margin-top: 10px; width: 120px; display: inline-block; text-align: left;">Default Code</label>
<input type="text" name="default_code"
class="field_input" id="default_code"/>
</div>
<div class="field_div"
style="display:flex; margin-bottom: 15px;">
<label for="category" class="field_label"
style="margin-right:10px; margin-top: 10px; width: 120px; display: inline-block; text-align: left;">Category</label>
<select name="category" class="form-control"
id="product_category">
<t t-foreach="env.pos.db.category_by_id"
t-as="category"
t-key="env.pos.db.category_by_id[category].id">
<option t-att-value="env.pos.db.category_by_id[category].id"
t-att-title="env.pos.db.category_by_id[category].name">
<t t-esc="env.pos.db.category_by_id[category].name"/>
</option>
</t>
</select>
</div>
</header>
</div>
</main>
<footer class="footer cash-move">
<div>
<a class="button confirm disable highlight"
t-on-click="confirm">
Confirm
</a>
<a class="button cancel" t-on-click="cancel">
Cancel
</a>
</div>
</footer>
</div>
</div>
</t>
</templates>

97
pos_product_create_edit/static/src/xml/product_edit_popup_templates.xml

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<!-- Template for the EditProductPopup component -->
<t t-name="EditProductPopup" owl="1">
<div role="dialog" class="modal-dialog">
<div class="popup product-line-popup" style="max-width: 684px;">
<main class="body">
<div>
<header>
<h3>
<span t-esc="props.product.display_name"/>
<i class="fa fa-times" style="float:right"
t-on-click="cancel"/>
<hr/>
</h3>
<div class="product-img-edit-popup">
<img t-att-src="imageUrl"
t-att-alt="props.product.display_name"
id="img_url_tag_edit"/>
</div>
<div class="field_div"
style="display:flex; margin-bottom: 15px;">
<label for="img_field" class="field_label"
style="margin-right:10px; margin-top: 10px; width: 120px; display: inline-block; text-align: left;">Image</label>
<input type="file" id="img_field"
class="field_input" name="img_field"
accept="image/*"/>
</div>
<div class="field_div"
style="display:flex; margin-bottom: 15px;">
<label for="display_name" class="field_label"
style="margin-right:10px; margin-top: 10px; width: 120px; display: inline-block; text-align: left;">Name</label>
<input type="text" name="display_name"
class="field_input" id="display_name"
t-att-value="props.product.display_name"/>
</div>
<div class="field_div"
style="display:flex; margin-bottom: 15px;">
<label for="list_price" class="field_label"
style="margin-right:10px; margin-top: 10px; width: 120px; display: inline-block; text-align: left;">Price</label>
<input type="text" name="list_price"
t-on-keyup="_numberCheck"
class="field_input" id="list_price"
t-att-value="props.product.lst_price"/>
</div>
<div class="field_div"
style="display:flex; margin-bottom: 15px;">
<label for="default_code" class="field_label"
style="margin-right:10px; margin-top: 10px; width: 120px; display: inline-block; text-align: left;">Default Code</label>
<input type="text" name="default_code"
class="field_input" id="default_code"
t-att-value="props.product.default_code"/>
</div>
<div class="field_div"
style="display:flex; margin-bottom: 15px;">
<label for="barcode" class="field_label"
style="margin-right:10px; margin-top: 10px; width: 120px; display: inline-block; text-align: left;">Barcode</label>
<input type="text" name="barcode"
class="field_input" id="barcode"
t-att-value="props.product.barcode"/>
</div>
<div class="field_div"
style="display:flex; margin-bottom: 15px;">
<label for="category" class="field_label"
style="margin-right:10px; margin-top: 10px; width: 120px; display: inline-block; text-align: left;">Category</label>
<select name="category" class="form-control"
id="product_category">
<t t-foreach="env.pos.db.category_by_id"
t-as="category"
t-key="env.pos.db.category_by_id[category].id">
<option t-att-value="env.pos.db.category_by_id[category].id"
t-att-title="env.pos.db.category_by_id[category].name"
t-att-selected="env.pos.db.category_by_id[category] ? ((env.pos.db.category_by_id[category].id === props.product.pos_categ_id[0]) ? true : undefined):undefined">
<t t-esc="env.pos.db.category_by_id[category].name"/>
</option>
</t>
</select>
</div>
</header>
</div>
</main>
<footer class="footer cash-move">
<div>
<a class="button confirm disable highlight"
t-on-click="confirm">
Confirm
</a>
<a class="button cancel" t-on-click="cancel">
Cancel
</a>
</div>
</footer>
</div>
</div>
</t>
</templates>

45
pos_product_create_edit/static/src/xml/product_line_templates.xml

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<!-- Template for the ProductLine component -->
<t t-name="ProductLine" owl="1">
<tr t-attf-class="client-line" t-att-data-id="props.product.id">
<td>
<div class="product-img">
<img t-att-src="imageUrl" class="product_img" t-att-alt="props.product.display_name"/>
</div>
</td>
<td>
<div>
<t t-esc="props.product.display_name or ''"/>
</div>
</td>
<td t-if="!env.isMobile">
<div>
<t t-esc="props.product.default_code or ''"/>
</div>
</td>
<td t-if="!env.isMobile">
<div>
<t t-esc="props.product.pos_categ_id[1] or ''"/>
</div>
</td>
<td t-if="!env.isMobile">
<div>
<t t-esc="props.product.lst_price or ''"/>
</div>
</td>
<td t-if="!env.isMobile">
<div>
<t t-esc="props.product.barcode or ''"/>
</div>
</td>
<td>
<div>
<button class="edit_product" t-on-click="editCurrentProduct">
<i class="fa fa-pencil" aria-hidden="true"/>
</button>
</div>
</td>
</tr>
</t>
</templates>

80
pos_product_create_edit/static/src/xml/product_list_screen_templates.xml

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="ProductListScreen" owl="1">
<!-- Template for the ProductListScreen component -->
<div class="clientlist-screen screen">
<div class="screen-content">
<div class="top-content">
<div class="button new-customer highlight" role="img"
aria-label="Create"
t-on-click="createProduct"
title="Create">
<i class="fa fa-plus create_btn"/>
<t t-if="!env.isMobile"> Create</t>
</div>
<div class="button back" t-on-click="back">
<i t-if="env.isMobile" class="fa fa-angle-double-left"/>
<t t-if="!env.isMobile"> Discard</t>
</div>
<div class="top-right-buttons">
<div class="searchbox-client top-content-center">
<div class="pos-search-bar">
<i class="fa fa-search" t-on-click="_onPressEnterKey"/>
<input t-ref="search-word-input-product"
placeholder="SearchProducts..." size="1"
t-on-keyup="updateProductList"/>
<i class="fa fa-times" t-on-click="_clearSearch"/>
</div>
</div>
</div>
</div>
<section class="full-content">
<div class="client-window">
<section class="subwindow list">
<div class="subwindow-container">
<div class="subwindow-container-fix scrollable-y">
<table class="client-list">
<thead>
<tr>
<th> </th>
<th>Name</th>
<th t-if="!env.isMobile">Default Code</th>
<th t-if="!env.isMobile" class="client-line-category">Category</th>
<th t-if="!env.isMobile" class="client-line-price">List Price</th>
<th t-if="!env.isMobile" class="client-line-price">Barcode</th>
<th>Edit</th>
</tr>
</thead>
<tbody class="client-list-contents">
<t t-foreach="products" t-as="product"
t-key="product.id">
<ProductLine product="product"/>
</t>
</tbody>
</table>
<div t-if="!products.length" class="no-results-message">
<p t-if="env.pos.isEveryProductLoaded and state.search">
No Product found for <b>"<t t-esc="state.search"/>"</b>.
</p>
<p t-elif="env.pos.isEveryProductLoaded and !state.search">
There are no products.
</p>
<p t-elif="!env.pos.isEveryProductLoaded and !state.search">
There are no loaded products.
</p>
<t t-elif="!env.pos.isEveryProductLoaded and state.search">
<p> No product found for <b>"<t t-esc="state.query"/>"</b>. </p>
<div class="button highlight" t-on-click="_onPressEnterKey">
<i class="fa fa-search"/> Search database
</div>
</t>
</div>
</div>
</div>
</section>
</div>
</section>
</div>
</div>
</t>
</templates>

14
pos_product_create_edit/views/assets.xml

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<template id="asset_backend" inherit_id="point_of_sale.assets">
<!-- Extend the 'point_of_sale.assets' template -->
<xpath expr="." position="inside">
<script type="text/javascript" src='/pos_product_create_edit/static/src/js/pos_product_screen.js'/>
<script type="text/javascript" src='/pos_product_create_edit/static/src/js/productScreen.js'/>
<script type="text/javascript" src='/pos_product_create_edit/static/src/js/ProductCreatePopup.js'/>
<script type="text/javascript" src='/pos_product_create_edit/static/src/js/ProductEditPopup.js'/>
<script type="text/javascript" src='/pos_product_create_edit/static/src/js/ProductLine.js'/>
<link rel="stylesheet" href='/pos_product_create_edit/static/src/css/ProductList.css'/>
</xpath>
</template>
</odoo>
Loading…
Cancel
Save