Browse Source

Jan 17 [ADD] : Initial Commit 'all_in_one_pos_kit'

pull/302/head
AjmalCybro 1 year ago
parent
commit
bf938faeac
  1. 45
      all_in_one_pos_kit/README.rst
  2. 24
      all_in_one_pos_kit/__init__.py
  3. 101
      all_in_one_pos_kit/__manifest__.py
  4. 23
      all_in_one_pos_kit/controllers/__init__.py
  5. 42
      all_in_one_pos_kit/controllers/all_in_one_pos_kit.py
  6. 57
      all_in_one_pos_kit/controllers/xlsx_report.py
  7. 7
      all_in_one_pos_kit/doc/RELEASE_NOTES.md
  8. 35
      all_in_one_pos_kit/models/__init__.py
  9. 80
      all_in_one_pos_kit/models/account_move.py
  10. 73
      all_in_one_pos_kit/models/meals_planning.py
  11. 92
      all_in_one_pos_kit/models/mrp_production.py
  12. 46
      all_in_one_pos_kit/models/multi_barcode_product.py
  13. 81
      all_in_one_pos_kit/models/pos_config.py
  14. 51
      all_in_one_pos_kit/models/pos_greetings.py
  15. 264
      all_in_one_pos_kit/models/pos_order.py
  16. 438
      all_in_one_pos_kit/models/pos_report.py
  17. 108
      all_in_one_pos_kit/models/pos_session.py
  18. 58
      all_in_one_pos_kit/models/product_product.py
  19. 66
      all_in_one_pos_kit/models/product_template.py
  20. 146
      all_in_one_pos_kit/models/res_config_settings.py
  21. 47
      all_in_one_pos_kit/models/res_users.py
  22. 58
      all_in_one_pos_kit/models/stock_lot.py
  23. 22
      all_in_one_pos_kit/report/__init__.py
  24. 42
      all_in_one_pos_kit/report/all_in_one_pos_kit_report.py
  25. 432
      all_in_one_pos_kit/report/all_in_one_pos_kit_templates.xml
  26. 43
      all_in_one_pos_kit/security/all_in_one_pos_kit_security.xml
  27. 8
      all_in_one_pos_kit/security/ir.model.access.csv
  28. BIN
      all_in_one_pos_kit/static/description/assets/icons/check.png
  29. BIN
      all_in_one_pos_kit/static/description/assets/icons/chevron.png
  30. BIN
      all_in_one_pos_kit/static/description/assets/icons/cogs.png
  31. BIN
      all_in_one_pos_kit/static/description/assets/icons/consultation.png
  32. BIN
      all_in_one_pos_kit/static/description/assets/icons/ecom-black.png
  33. BIN
      all_in_one_pos_kit/static/description/assets/icons/education-black.png
  34. BIN
      all_in_one_pos_kit/static/description/assets/icons/hotel-black.png
  35. BIN
      all_in_one_pos_kit/static/description/assets/icons/license.png
  36. BIN
      all_in_one_pos_kit/static/description/assets/icons/lifebuoy.png
  37. BIN
      all_in_one_pos_kit/static/description/assets/icons/manufacturing-black.png
  38. BIN
      all_in_one_pos_kit/static/description/assets/icons/pos-black.png
  39. BIN
      all_in_one_pos_kit/static/description/assets/icons/puzzle.png
  40. BIN
      all_in_one_pos_kit/static/description/assets/icons/restaurant-black.png
  41. BIN
      all_in_one_pos_kit/static/description/assets/icons/service-black.png
  42. BIN
      all_in_one_pos_kit/static/description/assets/icons/trading-black.png
  43. BIN
      all_in_one_pos_kit/static/description/assets/icons/training.png
  44. BIN
      all_in_one_pos_kit/static/description/assets/icons/update.png
  45. BIN
      all_in_one_pos_kit/static/description/assets/icons/user.png
  46. BIN
      all_in_one_pos_kit/static/description/assets/icons/wrench.png
  47. BIN
      all_in_one_pos_kit/static/description/assets/misc/categories.png
  48. BIN
      all_in_one_pos_kit/static/description/assets/misc/check-box.png
  49. BIN
      all_in_one_pos_kit/static/description/assets/misc/compass.png
  50. BIN
      all_in_one_pos_kit/static/description/assets/misc/corporate.png
  51. BIN
      all_in_one_pos_kit/static/description/assets/misc/customer-support.png
  52. BIN
      all_in_one_pos_kit/static/description/assets/misc/cybrosys-logo.png
  53. BIN
      all_in_one_pos_kit/static/description/assets/misc/features.png
  54. BIN
      all_in_one_pos_kit/static/description/assets/misc/logo.png
  55. BIN
      all_in_one_pos_kit/static/description/assets/misc/pictures.png
  56. BIN
      all_in_one_pos_kit/static/description/assets/misc/pie-chart.png
  57. BIN
      all_in_one_pos_kit/static/description/assets/misc/right-arrow.png
  58. BIN
      all_in_one_pos_kit/static/description/assets/misc/star.png
  59. BIN
      all_in_one_pos_kit/static/description/assets/misc/support.png
  60. BIN
      all_in_one_pos_kit/static/description/assets/misc/whatsapp.png
  61. BIN
      all_in_one_pos_kit/static/description/assets/modules/1.gif
  62. BIN
      all_in_one_pos_kit/static/description/assets/modules/2.png
  63. BIN
      all_in_one_pos_kit/static/description/assets/modules/3.png
  64. BIN
      all_in_one_pos_kit/static/description/assets/modules/4.png
  65. BIN
      all_in_one_pos_kit/static/description/assets/modules/5.png
  66. BIN
      all_in_one_pos_kit/static/description/assets/modules/6.png
  67. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/1.png
  68. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/10.png
  69. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/11.png
  70. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/12.png
  71. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/13.png
  72. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/14.png
  73. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/15.png
  74. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/16.png
  75. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/17.png
  76. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/18.png
  77. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/19.png
  78. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/2.png
  79. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/20.png
  80. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/21.png
  81. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/22.png
  82. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/23.png
  83. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/24.png
  84. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/25.png
  85. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/26.png
  86. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/27.png
  87. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/28.png
  88. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/29.png
  89. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/3.png
  90. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/30.png
  91. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/31.png
  92. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/32.png
  93. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/33.png
  94. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/34.png
  95. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/35.png
  96. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/36.png
  97. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/37.png
  98. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/38.png
  99. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/39.png
  100. BIN
      all_in_one_pos_kit/static/description/assets/screenshots/4.png

45
all_in_one_pos_kit/README.rst

@ -0,0 +1,45 @@
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
All in One POS Kit
==================
* This module combines a variety of POS features.
Installation
============
- www.odoo.com/documentation/16.0/setup/install.html
- Install our custom addon
License
-------
GNU AFFERO GENERAL PUBLIC LICENSE Version 3 (AGPL v3)
(https://www.gnu.org/licenses/agpl-3.0-standalone.html)
Company
-------
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__
Credits
-------
* Developer: (V16) Afra MP @cybrosys, Contact: odoo@cybrosys.com
Contacts
--------
* Mail Contact : odoo@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 https://www.cybrosys.com
Further information
===================
HTML Description: `<static/description/index.html>`__

24
all_in_one_pos_kit/__init__.py

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

101
all_in_one_pos_kit/__manifest__.py

@ -0,0 +1,101 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Afra MP (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
{
'name': 'All in One POS Kit',
'version': '16.0.1.0.0',
'category': 'Point of Sale',
'summary': 'This module combines Different POS features',
'description': 'This module combines Different POS features',
'author': 'Cybrosys Techno Solutions',
'company': 'Cybrosys Techno Solutions',
'maintainer': 'Cybrosys Techno Solutions',
'website': "https://www.cybrosys.com",
'depends': ['hr', 'point_of_sale', 'mrp'],
'external_dependencies': {'python': ['twilio', 'pandas']},
'data': [
'security/all_in_one_pos_kit_security.xml',
'security/ir.model.access.csv',
'views/res_config_settings_views.xml',
'views/pos_config_views.xml',
'views/pos_order_views.xml',
'views/dashboard_views.xml',
'views/product_template_views.xml',
'views/res_users_views.xml',
'views/product_product_views.xml',
'views/pos_report_views.xml',
'views/pos_greetings_views.xml',
'views/meals_planning_views.xml',
'report/all_in_one_pos_kit_templates.xml',
],
'assets': {
'point_of_sale.assets': [
'all_in_one_pos_kit/static/src/exchange_product/scss/pos.scss',
'all_in_one_pos_kit/static/src/order_line_image/css/order_line_image.css',
'all_in_one_pos_kit/static/src/product_magnify_image/css/pos_magnify_image.css',
'all_in_one_pos_kit/static/src/product_creation/css/*',
'all_in_one_pos_kit/static/src/mass_edit/js/*',
'all_in_one_pos_kit/static/src/service_charge/js/*',
'all_in_one_pos_kit/static/src/exchange_product/js/*',
'all_in_one_pos_kit/static/src/age_restricted/js/*',
'all_in_one_pos_kit/static/src/multi_barcode/js/pos_scan.js',
'all_in_one_pos_kit/static/src/delete_order_line/js/*',
'all_in_one_pos_kit/static/src/custom_tip/js/PaymentScreen.js',
'all_in_one_pos_kit/static/src/product_magnify_image/js/*',
'all_in_one_pos_kit/static/src/pos_mrp_order/js/models.js',
'all_in_one_pos_kit/static/src/pos_num_show_hide/js/pos_numpad.js',
'all_in_one_pos_kit/static/src/order_item_count/js/*',
'all_in_one_pos_kit/static/src/product_creation/js/*',
'all_in_one_pos_kit/static/src/pos_auto_lot/js/auto_lot.js',
'all_in_one_pos_kit/static/src/advanced_receipt/js/payment.js',
'all_in_one_pos_kit/static/src/category_wise_receipt/js/pos_receipt.js',
'all_in_one_pos_kit/static/src/time_based_product/js/*',
'all_in_one_pos_kit/static/src/exchange_product/xml/*',
'all_in_one_pos_kit/static/src/mass_edit/xml/*',
'all_in_one_pos_kit/static/src/service_charge/xml/ServiceChargeButton.xml',
'all_in_one_pos_kit/static/src/age_restricted/xml/restrict_popup.xml',
'all_in_one_pos_kit/static/src/order_line_image/xml/pos_order_line.xml',
'all_in_one_pos_kit/static/src/delete_order_line/xml/*',
'all_in_one_pos_kit/static/src/custom_tip/xml/PaymentScreen.xml',
'all_in_one_pos_kit/static/src/product_magnify_image/xml/*',
'all_in_one_pos_kit/static/src/pos_num_show_hide/xml/pos.xml',
'all_in_one_pos_kit/static/src/order_item_count/xml/*',
'all_in_one_pos_kit/static/src/product_creation/xml/*',
'all_in_one_pos_kit/static/src/advanced_receipt/xml/OrderReceipt.xml',
'all_in_one_pos_kit/static/src/category_wise_receipt/xml/pos_receipt.xml',
'all_in_one_pos_kit/static/src/pos_logo/xml/*',
],
'web.assets_backend': [
'all_in_one_pos_kit/static/src/dashboard/css/pos_dashboard.css',
'all_in_one_pos_kit/static/src/pos_report/css/*',
'all_in_one_pos_kit/static/src/dashboard/js/pos_dashboard.js',
'all_in_one_pos_kit/static/src/pos_report/js/*',
'all_in_one_pos_kit/static/src/dashboard/xml/pos_dashboard.xml',
'all_in_one_pos_kit/static/src/pos_report/xml/*',
'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.js',
],
},
'images': ['static/description/banner.jpg'],
'license': 'AGPL-3',
'installable': True,
'application': False,
'auto_install': False,
}

23
all_in_one_pos_kit/controllers/__init__.py

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

42
all_in_one_pos_kit/controllers/all_in_one_pos_kit.py

@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Afra MP (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
import werkzeug
from odoo import http
from odoo.http import request
from odoo.addons.web.controllers.main import home
class PosScreen(home.Home):
"""The class PosScreen is used to log in pos session directly"""
@http.route('/web/login', type='http', auth="none")
def web_login(self, redirect=None, **kw):
"""Override to add direct login to POS"""
res = super().web_login(redirect=redirect, **kw)
if request.env.user.pos_conf_id:
if not request.env.user.pos_conf_id.current_session_id:
request.env['pos.session'].sudo().create({
'user_id': request.env.uid,
'config_id': request.env.user.pos_conf_id.id
})
return werkzeug.utils.redirect('/pos/ui')
return res

57
all_in_one_pos_kit/controllers/xlsx_report.py

@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Afra MP (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
import json
from odoo import http
from odoo.http import content_disposition, request
from odoo.tools import html_escape
class TBXLSXReportController(http.Controller):
"""Controller class for generating and downloading XLSX reports."""
@http.route('/pos_dynamic_xlsx_reports', type='http', auth='user',
methods=['POST'], csrf=False)
def get_report_xlsx(self, model, options, output_format, report_data,
report_name, dfr_data):
""" Generate and download an XLSX report.
:param model: The model name for which the report is generated.
:param options: Options/configuration for the report.
:param output_format: The output format of the report (e.g.,'xlsx')
:param report_data: Data required for generating the report.
:param report_name: The name of the report.
:param dfr_data: Additional data required for the report.
:returns: The HTTP response containing the generated XLSX report"""
report_obj = request.env[model].with_user(request.session.uid)
try:
if output_format == 'xlsx':
response = request.make_response(None, headers=[
('Content-Type', 'application/vnd.ms-excel'), (
'Content-Disposition',
content_disposition(report_name + '.xlsx'))])
report_obj.get_pos_xlsx_report(options, response, report_data,
dfr_data)
response.set_cookie('fileToken', 'dummy-because-api-expects-one')
return response
except Exception as e:
error = {'code': 200, 'message': 'Odoo Server Error',
'data': http.serialize_exception(e)}
return request.make_response(html_escape(json.dumps(error)))

7
all_in_one_pos_kit/doc/RELEASE_NOTES.md

@ -0,0 +1,7 @@
## Module <all_in_one_pos_kit>
#### 3.10.2023
#### Version 16.0.1.0.0
#### ADD
- Initial commit for All in One POS Kit

35
all_in_one_pos_kit/models/__init__.py

@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Afra MP (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from . import account_move
from . import meals_planning
from . import mrp_production
from . import multi_barcode_product
from . import pos_config
from . import pos_greetings
from . import pos_order
from . import pos_report
from . import pos_session
from . import product_product
from . import product_template
from . import res_config_settings
from . import res_users
from . import stock_lot

80
all_in_one_pos_kit/models/account_move.py

@ -0,0 +1,80 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Afra MP (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
import math
import re
from odoo import api, fields, models
class AccountMove(models.Model):
"""Inherit the account_move module to add new fields and functions"""
_inherit = "account.move"
account_barcode = fields.Char(string='Barcode',
help='Barcode associated with the account '
'move.')
@api.model
def create(self, vals):
"""Super the create function to It generates an EAN barcode based on
the ID of the created record and assigns it to the `account_barcode`
field."""
res = super(AccountMove, self).create(vals)
res.account_barcode = self.generate_ean(str(res.id))
return res
def ean_checksum(self, eancode):
"""Returns the checksum of an ean string of length 13, returns -1 if
the string has the wrong length"""
if len(eancode) != 13:
return -1
oddsum = 0
evensum = 0
finalean = eancode[::-1][1:]
for i in range(len(finalean)):
if i % 2 == 0:
oddsum += int(finalean[i])
else:
evensum += int(finalean[i])
return int(10 - math.ceil((oddsum * 3) + evensum % 10.0)) % 10
def check_ean(eancode):
"""Returns True if eancode is a valid ean13 string, or null"""
if not eancode:
return True
if len(eancode) != 13:
return False
try:
int(eancode)
except:
return False
return eancode.ean_checksum(eancode) == int(eancode[-1])
def generate_ean(self, ean):
"""Creates and returns a valid ean13 from an invalid one"""
if not ean:
return "0000000000000"
ean = re.sub("[A-Za-z]", "0", ean)
ean = re.sub("[^0-9]", "", ean)
ean = ean[:13]
if len(ean) < 13:
ean = ean + '0' * (13 - len(ean))
return ean[:-1] + str(self.ean_checksum(ean))

73
all_in_one_pos_kit/models/meals_planning.py

@ -0,0 +1,73 @@
# -*- coding: utf-8 -*-
################################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Afra MP (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
from odoo import api, fields, models
from odoo.exceptions import ValidationError
class MealsPlanning(models.Model):
"""By using this model user can specify the time range and pos session"""
_name = 'meals.planning'
_description = "Product Planning"
_inherit = ['mail.thread', 'mail.activity.mixin']
name = fields.Char(string='Name', required=True,
help='Name for Product Planning')
pos_ids = fields.Many2many('pos.config', string='Shops',
help='Choose PoS Sessions', required=True)
time_from = fields.Float(string='From', required=True,
help='Add from time(24hr)')
time_to = fields.Float(string='To', required=True, help='Add to time(24hr)')
product_ids = fields.Many2many('product.product', string='Product',
domain=[('available_in_pos', '=', True)],
help='Select the products available for'
' the menu.')
state = fields.Selection([('activated', 'Activated'),
('deactivated', 'Deactivated')],
string='State',
default='deactivated',
help='Select the state of the item (activated or '
'deactivated).')
company_id = fields.Many2one('res.company', string='Company',
default=lambda self: self.env.company,
help='Select the company associated with the '
'item.')
@api.constrains('time_from', 'time_to')
def _check_time_range(self):
"""Validation for from time and to time"""
if self.time_from >= self.time_to:
raise ValidationError('From time must be less than to time!')
if self.time_from > 24.0 or self.time_to > 24.0:
raise ValidationError(
'Time value greater than 24 is not valid!')
def action_activate_meals_plan(self):
"""Change state to activate"""
self.write({
'state': 'activated'
})
def action_deactivate_meals_plan(self):
"""Change state to deactivate"""
self.write({
'state': 'deactivated'
})

92
all_in_one_pos_kit/models/mrp_production.py

@ -0,0 +1,92 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Afra MP (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from odoo import models
class MrpProduction(models.Model):
"""Inherit the class mrp_production to add new function"""
_inherit = 'mrp.production'
def create_mrp_from_pos(self, products):
"""Fetch value from js and create manufacturing order for the product
and return true"""
product_ids = []
if products:
for product in products:
if self.env['product.product'].browse(
int(product['id'])).to_make_mrp:
flag = 1
if product_ids:
for product_id in product_ids:
if product_id['id'] == product['id']:
product_id['qty'] += product['qty']
flag = 0
if flag:
product_ids.append(product)
for prod in product_ids:
if prod['qty'] > 0:
if self.env['mrp.bom'].search([('product_tmpl_id', '=',
prod['product_tmpl_id'])]):
if self.env['mrp.bom'].search(
[('product_id', '=', prod['id'])]):
bom = self.env['mrp.bom'].search(
[('product_id', '=', prod['id'])])[0]
elif self.env['mrp.bom'].search([(
'product_tmpl_id', '=',
prod[
'product_tmpl_id']),
('product_id', '=',
False)]):
bom = self.env['mrp.bom'].search([(
'product_tmpl_id',
'=', prod[
'product_tmpl_id']),
(
'product_id', '=',
False)])[0]
else:
bom = []
if bom:
mrp_order = self.sudo().create({
'origin': 'POS-' + prod['pos_reference'],
'state': 'confirmed',
'product_id': prod['id'],
'product_tmpl_id': prod['product_tmpl_id'],
'product_uom_id': prod['uom_id'],
'product_qty': prod['qty'],
'bom_id': bom.id})
list_value = []
for bom_line in mrp_order.bom_id.bom_line_ids:
list_value.append((0, 0, {
'raw_material_production_id': mrp_order.id,
'name': mrp_order.name,
'product_id': bom_line.product_id.id,
'product_uom': bom_line.product_uom_id.id,
'product_uom_qty': bom_line.product_qty * mrp_order.product_qty,
'picking_type_id': mrp_order.picking_type_id.id,
'location_id': mrp_order.location_src_id.id,
'location_dest_id': bom_line.product_id.with_company(
self.company_id.id).property_stock_production.id,
'company_id': mrp_order.company_id.id,
}))
mrp_order.update({'move_raw_ids': list_value})
return True

46
all_in_one_pos_kit/models/multi_barcode_product.py

@ -0,0 +1,46 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Afra MP (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from odoo import fields, models
class ProductMultiBarcode(models.Model):
"""Created new model to add store multi barcode for product"""
_name = 'multi.barcode.product'
_description = 'For creating multiple Barcodes for products'
multi_barcode = fields.Char(string="Barcode",
help="Provide alternate barcodes for this "
"product")
product_id = fields.Many2one('product.product',
string='Product',
help='Related product name in product.product'
' model')
product_template_id = fields.Many2one('product.template',
string='Product template',
help='Related product name in '
'product.template model')
_sql_constraints = [('field_unique', 'unique(multi_barcode)',
'Existing barcode is not allowed !'), ]
def get_barcode_val(self, product):
"""Returns barcode of record in self and product id"""
return self.multi_barcode, product

81
all_in_one_pos_kit/models/pos_config.py

@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Afra MP (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from odoo import api, fields, models
class PosConfig(models.Model):
"""Inherited POS Configuration to add field's and functions"""
_inherit = 'pos.config'
is_session = fields.Boolean(string="Session",
compute='_compute_is_session',
help="Check it is for sessions")
is_service_charges = fields.Boolean(string="Service Charges",
help="Enable to add service charge")
charge_type = fields.Selection([('amount', 'Amount'),
('percentage', 'Percentage')],
string='Type', default='amount',
help="Can choose charge percentage or "
"amount")
service_charge = fields.Float(string='Service Charge',
help="Charge need to apply")
service_product_id = fields.Many2one(
'product.product', string='Service Product',
domain="[('available_in_pos', '=', True),('sale_ok', '=', True),"
"('type', '=', 'service')]", help="Service Product")
image = fields.Binary(string='Image', help='Add logo for pos session')
user_ids = fields.Many2many('res.users',
compute='_compute_user_ids', string='User',
help="The users who are allowed to access this"
"feature.")
def _compute_is_session(self):
"""To check the service charge is set up for session wise or
globally"""
if self.env['ir.config_parameter'].sudo().get_param(
'service_charges_pos.visibility') == 'session':
self.is_session = True
else:
self.is_session = False
@api.onchange('is_service_charges')
def _onchange_is_service_charges(self):
"""When the service charge is enabled set service product
and amount by default per session"""
if self.is_service_charges:
if not self.service_product_id:
self.service_product_id = self.env['product.product'].search(
[('available_in_pos', '=', True), ('sale_ok', '=', True),
('type', '=', 'service')], limit=1)
self.service_charge = 10.0
else:
self.service_product_id = False
self.service_charge = 0.0
def _compute_user_ids(self):
"""Computes the allowed users in pos"""
for record in self:
if record.env.user.show_users:
record.user_ids = self.env['res.users'].search(
[('pos_config_ids', '=', record.id)])
else:
record.user_ids = None

51
all_in_one_pos_kit/models/pos_greetings.py

@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Afra MP (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from odoo import fields, models
class POSGreetings(models.Model):
"""Model representing POS Greetings."""
_name = 'pos.greetings'
_description = 'POS Greetings'
_rec_name = 'order_id'
partner_id = fields.Many2one('res.partner', string='Customer',
help='Select the customer for whom the SMS '
'will be sent.')
order_id = fields.Many2one('pos.order', string='Order',
help='Select the order associated with the SMS')
auth_token = fields.Char(string='Token',
help='Enter the authentication token for the SMS '
'service provider.')
twilio_number = fields.Char(string='Twilio Number',
help='Enter the Twilio phone number used to'
' send the SMS.')
to_number = fields.Char(string='Customer Number',
help='Enter the recipients phone number to send '
'the SMS to.')
sms_body = fields.Char(string='Body',
help='Enter the content or message of the SMS.')
session_id = fields.Many2one('pos.session', string='Session',
help='Select the session associated with '
'the SMS.')
send_sms = fields.Boolean(string='Send SMS',help='Check this box to send '
'the SMS when saving the record.')

264
all_in_one_pos_kit/models/pos_order.py

@ -0,0 +1,264 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Afra MP (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
import pytz
from twilio.rest import Client
from odoo import api, fields, models
class PosOrder(models.Model):
"""Inherited the pos_order class to add filed and function to calculate pos
order details in the dashboard menu"""
_inherit = 'pos.order'
exchange = fields.Boolean(string='Exchange',
help='Enable if the order contain is exchange '
'product')
sale_barcode = fields.Char(string='Barcode',
help='Barcode associated with the pos order.')
def get_pos_exchange_order(self):
"""Mark order a exchanged"""
self.exchange = True
return
@api.model
def get_department(self, option):
"""Function to filter the POs sales report chart"""
company_id = self.env.company.id
if option == 'pos_hourly_sales':
query = '''select EXTRACT(hour FROM date_order at time zone 'utc' at time zone '{}')
as date_month,sum(amount_total) from pos_order where
EXTRACT(month FROM date_order::date) = EXTRACT(month FROM CURRENT_DATE)
AND pos_order.company_id = ''' + str(
company_id) + ''' group by date_month '''
query = query.format(
self.env.user.tz if self.env.user.tz else pytz.UTC)
label = 'HOURS'
elif option == 'pos_monthly_sales':
query = '''select date_order::date as date_month,sum(amount_total) from pos_order where
EXTRACT(month FROM date_order::date) = EXTRACT(month FROM CURRENT_DATE) AND pos_order.company_id = ''' + str(
company_id) + ''' group by date_month '''
label = 'DAYS'
else:
query = '''select TO_CHAR(date_order,'MON')date_month,sum(amount_total) from pos_order where
EXTRACT(year FROM date_order::date) = EXTRACT(year FROM CURRENT_DATE) AND pos_order.company_id = ''' + str(
company_id) + ''' group by date_month'''
label = 'MONTHS'
self._cr.execute(query)
docs = self._cr.dictfetchall()
order = []
today = []
for record in docs:
order.append(record.get('sum'))
today.append(record.get('date_month'))
return [order, today, label]
@api.model
def get_details(self):
"""Function to get payment details,session details and sales person
details"""
company_id = self.env.company
self._cr.execute('''select pos_payment_method.name ->>'en_US',sum(amount)
from pos_payment inner join pos_payment_method on
pos_payment_method.id=pos_payment.payment_method_id
where pos_payment.company_id = ''' + str(company_id.id) + " " + '''
group by pos_payment_method.name ORDER
BY sum(amount) DESC; ''')
payment_details = self._cr.fetchall()
self._cr.execute('''select hr_employee.name,sum(pos_order.amount_paid)
as total,count(pos_order.amount_paid) as orders from
pos_order inner join hr_employee on pos_order.user_id =
hr_employee.user_id where pos_order.company_id =''' + str(
company_id.id) + " " + '''GROUP BY hr_employee.name order by total DESC;''')
salesperson = self._cr.fetchall()
payments = []
for rec in payment_details:
rec = list(rec)
if company_id.currency_id.position == 'after':
rec[1] = "%s %s" % (rec[1], company_id.currency_id.symbol)
else:
rec[1] = "%s %s" % (company_id.currency_id.symbol, rec[1])
payments.append(tuple(rec))
total_sales = []
for rec in salesperson:
rec = list(rec)
if company_id.currency_id.position == 'after':
rec[1] = "%s %s" % (rec[1], company_id.currency_id.symbol)
else:
rec[1] = "%s %s" % (company_id.currency_id.symbol, rec[1])
total_sales.append(tuple(rec))
sessions_list = []
session = {'opened': 'Opened', 'opening_control': "Opening Control"}
for session_id in self.env['pos.config'].search([]):
if session.get(session_id.pos_session_state) is None:
sessions_list.append({'session': session_id.name,
'status': 'Closed'})
else:
sessions_list.append({'session': session_id.name,
'status': session.get(
session_id.pos_session_state)})
return {'payment_details': payments, 'salesperson': total_sales,
'selling_product': sessions_list}
@api.model
def get_refund_details(self):
"""Function to get total count of orders,session and refund orders"""
total = sum(self.env['pos.order'].search([]).mapped('amount_total'))
today_refund_total = 0
today_sale = 0
for pos_order_id in self.env['pos.order'].search([]):
if pos_order_id.date_order.date() == fields.date.today():
today_sale = today_sale + 1
if pos_order_id.amount_total < 0.0:
today_refund_total = today_refund_total + 1
magnitude = 0
while abs(total) >= 1000:
magnitude += 1
total /= 1000.0
# add more suffixes if you need them
val = '%.2f%s' % (total, ['', 'K', 'M', 'G', 'T', 'P'][magnitude])
return {
'total_sale': val,
'total_order_count': self.env['pos.order'].search_count([]),
'total_refund_count': self.env['pos.order'].search_count(
[('amount_total', '<', 0.0)]),
'total_session': self.env['pos.session'].search_count([]),
'today_refund_total': today_refund_total,
'today_sale': today_sale,
}
@api.model
def get_the_top_customer(self):
"""Function to get top 10 customer in pos"""
self._cr.execute('''select res_partner.name as customer,pos_order.partner_id,sum(pos_order.amount_paid) as amount_total from pos_order
inner join res_partner on res_partner.id = pos_order.partner_id where pos_order.company_id = ''' + str(
self.env.company.id) + ''' GROUP BY pos_order.partner_id,
res_partner.name ORDER BY amount_total DESC LIMIT 10;''')
top_customer = self._cr.dictfetchall()
order = []
day = []
for record in top_customer:
order.append(record.get('amount_total'))
day.append(record.get('customer'))
return [order, day]
@api.model
def get_the_top_products(self):
"""Function to get top 10 product in """
self._cr.execute('''select DISTINCT(product_template.name)->>'en_US' as product_name,sum(qty) as total_quantity from
pos_order_line inner join product_product on product_product.id=pos_order_line.product_id inner join
product_template on product_product.product_tmpl_id = product_template.id where pos_order_line.company_id = ''' + str(
self.env.company.id) + ''' group by product_template.id ORDER
BY total_quantity DESC Limit 10 ''')
top_product = self._cr.dictfetchall()
total_quantity = []
product_name = []
for record in top_product:
total_quantity.append(record.get('total_quantity'))
product_name.append(record.get('product_name'))
return [total_quantity, product_name]
@api.model
def get_the_top_categories(self):
"""Function to get top categories in pos"""
query = '''select DISTINCT(product_category.complete_name) as product_category,sum(qty) as total_quantity
from pos_order_line inner join product_product on product_product.id=pos_order_line.product_id inner join
product_template on product_product.product_tmpl_id = product_template.id inner join product_category on
product_category.id =product_template.categ_id where pos_order_line.company_id = ''' + str(
self.env.company.id) + ''' group by product_category ORDER BY total_quantity DESC '''
self._cr.execute(query)
top_categories = self._cr.dictfetchall()
total_quantity = []
product_categ = []
for record in top_categories:
total_quantity.append(record.get('total_quantity'))
product_categ.append(record.get('product_category'))
return [total_quantity, product_categ]
@api.model
def get_invoice(self, id):
"""Retrieve invoice information based on a POS reference ID.
This method searches for a POS record with the specified reference ID. It
then retrieves the associated invoice based on the name matching the
reference. The invoice details, including ID, name, base URL, and account
barcode, are returned as a dictionary.
:param id: The POS reference ID to search for.
:return: A dictionary containing the invoice details.
:rtype: dict"""
invoice_id = self.env['account.move'].search(
[('ref', '=', self.search([('pos_reference', '=', id)]).name)])
return {'invoice_id': invoice_id.id, 'invoice_name': invoice_id.name,
'base_url': self.env['ir.config_parameter'].get_param(
'web.base.url'), 'barcode': invoice_id.account_barcode}
@api.model
def create_from_ui(self, orders, draft=False):
"""Create POS orders from the user interface.
This method is called to create POS orders based on the provided
data from the user interface.
:param orders: A list of dictionaries representing the POS orders.
:param draft: Set to True if the orders should be created in the
draft state.
:returns: A list of dictionaries containing the created order
details.
"""
res = super(PosOrder, self).create_from_ui(orders)
id = [line['id'] for line in res if line['id']]
if backend_order := self.search([('id', 'in', id)]):
for pos_order in backend_order:
params = self.env['ir.config_parameter'].sudo()
if params.get_param(
'pos.customer_msg') and pos_order.partner_id.phone:
try:
# Download the helper library from https://www.twilio.com/docs/python/install
Client(params.get_param('pos.account_sid'),
params.get_param(
'pos.auth_token')).messages.create(
body=params.get_param('pos.sms_body'),
from_=params.get_param('pos.twilio_number'),
to=str(pos_order.partner_id.phone))
self.env['pos.greetings'].create({
'partner_id': pos_order.partner_id.id,
'order_id': pos_order.id,
'auth_token': params.get_param('pos.auth_token'),
'twilio_number': params.get_param(
'pos.twilio_number'),
'to_number': str(pos_order.partner_id.phone),
'session_id': pos_order.session_id.id,
'sms_body': params.get_param('pos.sms_body'),
'send_sms': True,
})
except Exception:
pass
return res
class PosOrderLine(models.Model):
"""Inherit the class pos_order_line"""
_inherit = "pos.order.line"
def get_product_details(self, ids):
"""Function to get the product details"""
return [{'product_id': rec.product_id.id, 'name': rec.product_id.name,
'qty': rec.qty}
for rec in self.env['pos.order.line'].browse(ids)]

438
all_in_one_pos_kit/models/pos_report.py

@ -0,0 +1,438 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Afra MP (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
import io
import json
from odoo import api, fields, models
try:
from odoo.tools.misc import xlsxwriter
except ImportError:
import xlsxwriter
class PosReportGenerator(models.Model):
"""Class to generate PDF and XLS report in POS"""
_name = "pos.report"
_description = 'POS Report'
pos_report = fields.Char(string="PoS Report", help="Enter the name of the "
"PoS report.")
date_from = fields.Datetime(string="Date From", help="Specify the starting"
"date for the report")
date_to = fields.Datetime(string="Date to", help="Specify the ending date"
"for the report.")
report_type = fields.Selection(
[('report_by_order', 'Report By Order'),
('report_by_order_detail','Report By Order Detail'),
('report_by_product', 'Report By Product'),
('report_by_categories','Report By Categories'),
('report_by_salesman', 'Report By Salesman'),
('report_by_payment', 'Report By Payment')], default='report_by_order',
string='Report Type',help="Select the type of report to generate.")
@api.model
def pos_report(self, option):
"""The pos_report method is used to generate the PoS report based on the
selected option. It retrieves the necessary data from the database and
returns the report in a specific format."""
report_values = self.env['pos.report'].search([('id', '=', option[0])])
data = {'report_type': report_values.report_type,'model': self}
if report_values.date_from:
data.update({'date_from': report_values.date_from})
if report_values.date_to:
data.update({'date_to': report_values.date_to})
self._get_report_values(data)
return {
'name': "PoS Orders",
'type': 'ir.actions.client',
'tag': 'pos_r',
'orders': data,
'filters': self.get_filter(option),
'report_lines': self._get_report_values(data).get('POS'),
'report_main_line': self._get_report_values(data).get('pos_main'),
}
def get_filter(self, option):
"""Get the filter settings for the report"""
data = self.get_filter_data(option)
filters = {}
if data.get('report_type') == 'report_by_order':
filters['report_type'] = 'Report By Order'
elif data.get('report_type') == 'report_by_order_detail':
filters['report_type'] = 'Report By Order Detail'
elif data.get('report_type') == 'report_by_product':
filters['report_type'] = 'Report By Product'
elif data.get('report_type') == 'report_by_categories':
filters['report_type'] = 'Report By Categories'
elif data.get('report_type') == 'report_by_salesman':
filters['report_type'] = 'Report By Salesman'
elif data.get('report_type') == 'report_by_payment':
filters['report_type'] = 'Report By Payment'
else:
filters['report_type'] = 'report_by_order'
return filters
def get_filter_data(self, option):
"""Get the filter data for the report"""
return {'report_type': self.env['pos.report'].search([
('id', '=', option[0])]).report_type}
def _get_report_sub_lines(self, data):
"""Get the sub_lines of the report"""
report_sub_lines = []
if data.get('report_type') == 'report_by_order':
query = '''
select l.name,l.date_order,l.partner_id,l.amount_total,l.note,l.user_id,res_partner.name,l.name as shop,pos_session.name as session,
res_users.partner_id as user_partner,sum(pos_order_line.qty),l.id as id,
(SELECT res_partner.name as salesman FROM res_partner WHERE res_partner.id = res_users.partner_id)
from pos_order as l
left join pos_session on l.session_id = pos_session.id
left join res_partner on l.partner_id = res_partner.id
left join res_users on l.user_id = res_users.id
left join pos_order_line on l.id = pos_order_line.order_id
'''
term = 'Where '
if data.get('date_from'):
query += "Where l.date_order >= '%s' " % data.get('date_from')
term = 'AND '
if data.get('date_to'):
query += term + "l.date_order <= '%s' " % data.get('date_to')
query += "group by l.user_id,res_users.partner_id,res_partner.name,l.partner_id,l.date_order,pos_session.name,l.session_id,l.name,l.amount_total,l.note,l.id"
self._cr.execute(query)
report_sub_lines.append(self._cr.dictfetchall())
elif data.get('report_type') == 'report_by_order_detail':
query = '''
select l.name,l.date_order,l.partner_id,l.amount_total,l.note,l.user_id,res_partner.name,l.name as shop,pos_session.name as session,
res_users.partner_id as user_partner,sum(pos_order_line.qty), pos_order_line.full_product_name, pos_order_line.price_unit,pos_order_line.price_subtotal,pos_order_line.price_subtotal_incl,pos_order_line.product_id,product_product.default_code,
(SELECT res_partner.name as salesman FROM res_partner WHERE res_partner.id = res_users.partner_id)
from pos_order as l
left join pos_session on l.session_id = pos_session.id
left join res_partner on l.partner_id = res_partner.id
left join res_users on l.user_id = res_users.id
left join pos_order_line on l.id = pos_order_line.order_id
left join product_product on pos_order_line.product_id = product_product.id
'''
term = 'Where '
if data.get('date_from'):
query += "Where l.date_order >= '%s' " % data.get('date_from')
term = 'AND '
if data.get('date_to'):
query += term + "l.date_order <= '%s' " % data.get('date_to')
query += "group by l.user_id,res_users.partner_id,res_partner.name,l.partner_id,l.date_order,pos_session.name,l.session_id,l.name,l.amount_total,l.note,pos_order_line.full_product_name,pos_order_line.price_unit,pos_order_line.price_subtotal,pos_order_line.price_subtotal_incl,pos_order_line.product_id,product_product.default_code"
self._cr.execute(query)
report_sub_lines.append(self._cr.dictfetchall())
elif data.get('report_type') == 'report_by_product':
query = '''
select l.amount_total,l.amount_paid,sum(pos_order_line.qty) as qty, pos_order_line.full_product_name, pos_order_line.price_unit,product_product.default_code,product_category.name
from pos_order as l
left join pos_order_line on l.id = pos_order_line.order_id
left join product_product on pos_order_line.product_id = product_product.id
left join product_template on pos_order_line.product_id = product_template.id
left join product_category on product_category.id = product_template.categ_id
'''
term = 'Where '
if data.get('date_from'):
query += "Where l.date_order >= '%s' " % data.get('date_from')
term = 'AND '
if data.get('date_to'):
query += term + "l.date_order <= '%s' " % data.get('date_to')
query += "group by l.amount_total,l.amount_paid,pos_order_line.full_product_name,pos_order_line.price_unit,pos_order_line.product_id,product_product.default_code,product_template.categ_id,product_category.name"
self._cr.execute(query)
report_sub_lines.append(self._cr.dictfetchall())
elif data.get('report_type') == 'report_by_categories':
query = '''
select product_category.name,sum(l.qty) as qty,sum(l.price_subtotal) as amount_total,sum(price_subtotal_incl) as total_incl
from pos_order_line as l
left join product_template on l.product_id = product_template.id
left join product_category on product_category.id = product_template.categ_id
left join pos_order on l.order_id = pos_order.id
'''
term = 'Where '
if data.get('date_from'):
query += "Where pos_order.date_order >= '%s' " % data.get(
'date_from')
term = 'AND '
if data.get('date_to'):
query += term + "pos_order.date_order <= '%s' " % data.get(
'date_to')
query += "group by product_category.name"
self._cr.execute(query)
report_sub_lines.append(self._cr.dictfetchall())
elif data.get('report_type') == 'report_by_salesman':
query = '''
select res_partner.name,sum(pos_order_line.qty) as qty,sum(pos_order_line.price_subtotal) as amount,count(l.id) as order
from pos_order as l
left join res_users on l.user_id = res_users.id
left join res_partner on res_users.partner_id = res_partner.id
left join pos_order_line on l.id = pos_order_line.order_id
'''
term = 'Where '
if data.get('date_from'):
query += "Where l.date_order >= '%s' " % data.get('date_from')
term = 'AND '
if data.get('date_to'):
query += term + "l.date_order <= '%s' " % data.get('date_to')
query += "group by res_partner.name"
self._cr.execute(query)
report_sub_lines.append(self._cr.dictfetchall())
elif data.get('report_type') == 'report_by_payment':
query = '''
select pos_payment_method.name,sum(l.amount_total),pos_session.name as session,pos_config.name as config
from pos_order as l
left join pos_payment on l.id = pos_payment.pos_order_id
left join pos_payment_method on pos_payment.payment_method_id = pos_payment_method.id
left join pos_session on l.session_id = pos_session.id
left join pos_config on pos_session.config_id = pos_config.id
'''
term = 'Where '
if data.get('date_from'):
query += "Where l.date_order >= '%s' " % data.get('date_from')
term = 'AND '
if data.get('date_to'):
query += term + "l.date_order <= '%s' " % data.get('date_to')
query += "group by pos_payment_method.name,pos_session.name,pos_config.name"
self._cr.execute(query)
report_sub_lines.append(self._cr.dictfetchall())
return report_sub_lines
def _get_report_total_value(self, data):
"""The _get_report_total_value method retrieves the total values of the
report based on the selected report type and filters."""
report_main_lines = []
if data.get('report_type') == 'report_by_order':
self._cr.execute('''
select count(l.id) as order,sum(l.amount_total) as amount
from pos_order as l
''')
report_main_lines.append(self._cr.dictfetchall())
elif data.get('report_type') == 'report_by_order_detail':
self._cr.execute('''
select count(line.id) as order,sum(line.price_subtotal) as total,sum(line.price_subtotal_incl)
from pos_order_line as line
''')
report_main_lines.append(self._cr.dictfetchall())
elif data.get('report_type') == 'report_by_product':
self._cr.execute('''
select count(l.product_id) as order,sum(l.price_subtotal) as amount
from pos_order_line as l
''')
report_main_lines.append(self._cr.dictfetchall())
else:
report_main_lines = False
return report_main_lines
def _get_report_values(self, data):
"""The _get_report_values method generates the report values by calling
_get_report_sub_lines and _get_report_total_value."""
report_res_total = self._get_report_total_value(data)
if data.get('report_type'):
report_res = self._get_report_sub_lines(data)[0]
else:
report_res = self._get_report_sub_lines(data)
if data.get('report_type') == 'report_by_order':
report_res_total = self._get_report_total_value(data)[0]
return {
'doc_ids': self.ids,
'docs': data['model'],
'POS': report_res,
'pos_main': report_res_total,
}
def get_pos_xlsx_report(self, data, response, report_data, dfr_data):
"""Generate an XLSX report for the Point of Sale.
:param data: JSON-encoded data representing the report filters
:param response: HTTP response object
:param report_data: JSON-encoded report datas
:param dfr_data: data for DFR (Data Field Relations)"""
report_data_main = json.loads(report_data)
output = io.BytesIO()
filters = json.loads(data)
workbook = xlsxwriter.Workbook(output, {'in_memory': True})
sheet = workbook.add_worksheet()
heading = workbook.add_format({'align': 'center', 'bold': True,
'font_size': '10px', 'border': 2,
'border_color': 'black'})
txt_l = workbook.add_format({'font_size': '10px', 'border': 1,
'bold': True})
if filters.get('report_type') == 'report_by_order':
sheet.merge_range('D5:F5', 'Report Type: ' +
filters.get('report_type'), txt_l)
sheet.write('A7', 'PoS', heading)
sheet.write('B7', 'Order', heading)
sheet.write('C7', 'Date Order', heading)
sheet.write('D7', 'Customer', heading)
sheet.write('E7', 'Salesman', heading)
sheet.write('F7', 'Total Qty', heading)
sheet.write('G7', 'Amount Total', heading)
sheet.write('H7', 'Note', heading)
lst = [rec for rec in report_data_main[0]]
row = 6
col = 0
sheet.set_column(3, 0, 15)
sheet.set_column(4, 1, 15)
sheet.set_column(5, 2, 15)
sheet.set_column(6, 3, 15)
sheet.set_column(7, 4, 15)
sheet.set_column(8, 5, 15)
sheet.set_column(9, 6, 15)
for rec_data in report_data_main:
row += 1
sheet.write(row, col, rec_data['shop'], txt_l)
sheet.write(row, col + 1, rec_data['session'], txt_l)
sheet.write(row, col + 2, rec_data['date_order'], txt_l)
sheet.write(row, col + 3, rec_data['name'], txt_l)
sheet.write(row, col + 4, rec_data['salesman'], txt_l)
sheet.write(row, col + 5, rec_data['sum'], txt_l)
sheet.write(row, col + 6, rec_data['amount_total'], txt_l)
sheet.write(row, col + 7, rec_data['note'], txt_l)
if filters.get('report_type') == 'report_by_order_detail':
sheet.merge_range('E5:G5', 'Report Type: ' +
filters.get('report_type'), txt_l)
sheet.write('A7', 'PoS', heading)
sheet.write('B7', 'Order', heading)
sheet.write('C7', 'Date Order', heading)
sheet.write('D7', 'Customer', heading)
sheet.write('E7', 'Salesman', heading)
sheet.write('F7', 'Product Code', heading)
sheet.write('G7', 'Product Name', heading)
sheet.write('H7', 'Price unit', heading)
sheet.write('I7', 'Qty', heading)
sheet.write('J7', 'Price Subtotal', heading)
sheet.write('K7', 'Price Subtotal Incl', heading)
lst = [rec for rec in report_data_main[0]]
row = 6
col = 0
sheet.set_column(3, 0, 15)
sheet.set_column(4, 1, 15)
sheet.set_column(5, 2, 15)
sheet.set_column(6, 3, 15)
sheet.set_column(7, 4, 15)
sheet.set_column(8, 5, 15)
sheet.set_column(9, 6, 15)
sheet.set_column(10, 7, 15)
sheet.set_column(11, 8, 15)
sheet.set_column(12, 9, 15)
for rec_data in report_data_main:
row += 1
sheet.write(row, col, rec_data['shop'], txt_l)
sheet.write(row, col + 1, rec_data['session'], txt_l)
sheet.write(row, col + 2, rec_data['date_order'], txt_l)
sheet.write(row, col + 3, rec_data['name'], txt_l)
sheet.write(row, col + 4, rec_data['salesman'], txt_l)
sheet.write(row, col + 5, rec_data['default_code'], txt_l)
sheet.write(row, col + 6, rec_data['full_product_name'], txt_l)
sheet.write(row, col + 7, rec_data['price_unit'], txt_l)
sheet.write(row, col + 8, rec_data['sum'], txt_l)
sheet.write(row, col + 9, rec_data['price_subtotal'], txt_l)
sheet.write(row, col + 10, rec_data['price_subtotal_incl'],
txt_l)
if filters.get('report_type') == 'report_by_product':
sheet.merge_range('B5:D5', 'Report Type: ' +
filters.get('report_type'), txt_l)
sheet.write('A7', 'Category', heading)
sheet.write('B7', 'Product Code', heading)
sheet.write('C7', 'Product Name', heading)
sheet.write('D7', 'Qty', heading)
sheet.write('E7', 'Amount Total', heading)
sheet.write('F7', 'Amount Total Incl', heading)
lst = [rec for rec in report_data_main[0]]
row = 6
col = 0
sheet.set_column(3, 0, 15)
sheet.set_column(4, 1, 15)
sheet.set_column(5, 2, 15)
sheet.set_column(6, 3, 15)
sheet.set_column(7, 4, 15)
sheet.set_column(8, 5, 15)
for rec_data in report_data_main:
row += 1
sheet.write(row, col, rec_data['name'], txt_l)
sheet.write(row, col + 1, rec_data['default_code'], txt_l)
sheet.write(row, col + 2, rec_data['full_product_name'], txt_l)
sheet.write(row, col + 3, rec_data['qty'], txt_l)
sheet.write(row, col + 4, rec_data['amount_total'], txt_l)
sheet.write(row, col + 5, rec_data['amount_paid'], txt_l)
if filters.get('report_type') == 'report_by_categories':
sheet.merge_range('B5:C5', 'Report Type: ' +
filters.get('report_type'), txt_l)
sheet.write('A7', 'Category', heading)
sheet.write('B7', 'Qty', heading)
sheet.write('C7', 'Amount Total', heading)
sheet.write('D7', 'Amount Total Incl', heading)
lst = [rec for rec in report_data_main[0]]
row = 6
col = 0
sheet.set_column(3, 0, 15)
sheet.set_column(4, 1, 15)
sheet.set_column(5, 2, 15)
sheet.set_column(6, 3, 15)
for rec_data in report_data_main:
row += 1
sheet.write(row, col, rec_data['name'], txt_l)
sheet.write(row, col + 1, rec_data['qty'], txt_l)
sheet.write(row, col + 2, rec_data['amount_total'], txt_l)
sheet.write(row, col + 3, rec_data['total_incl'], txt_l)
if filters.get('report_type') == 'report_by_salesman':
sheet.merge_range('B5:C5', 'Report Type: ' +
filters.get('report_type'), txt_l)
sheet.write('A7', 'Salesman', heading)
sheet.write('B7', 'Total Order', heading)
sheet.write('C7', 'Total Qty', heading)
sheet.write('D7', 'Total Amount', heading)
lst = [rec for rec in report_data_main[0]]
row = 6
col = 0
sheet.set_column(3, 0, 15)
sheet.set_column(4, 1, 15)
sheet.set_column(5, 2, 15)
sheet.set_column(6, 3, 15)
for rec_data in report_data_main:
row += 1
sheet.write(row, col, rec_data['name'], txt_l)
sheet.write(row, col + 1, rec_data['order'], txt_l)
sheet.write(row, col + 2, rec_data['qty'], txt_l)
sheet.write(row, col + 3, rec_data['amount'], txt_l)
if filters.get('report_type') == 'report_by_payment':
sheet.merge_range('B5:C5', 'Report Type: ' +
filters.get('report_type'), txt_l)
sheet.write('A7', 'Point of Sale', heading)
sheet.write('B7', 'PoS Session', heading)
sheet.write('C7', 'Payment', heading)
sheet.write('D7', 'Total Amount', heading)
lst = [rec for rec in report_data_main[0]]
row = 6
col = 0
sheet.set_column(3, 0, 15)
sheet.set_column(4, 1, 15)
sheet.set_column(5, 2, 15)
sheet.set_column(6, 3, 15)
for rec_data in report_data_main:
name = list(rec_data['name'].values())[0]
row += 1
sheet.write(row, col, rec_data['config'], txt_l)
sheet.write(row, col + 1, rec_data['session'], txt_l)
sheet.write(row, col + 2, name, txt_l)
sheet.write(row, col + 3, rec_data['sum'], txt_l)
workbook.close()
output.seek(0)
response.stream.write(output.read())
output.close()

108
all_in_one_pos_kit/models/pos_session.py

@ -0,0 +1,108 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Afra MP (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from odoo import models
class PosSession(models.Model):
"""Inherit POS Session to load model and fields"""
_inherit = 'pos.session'
def _pos_ui_models_to_load(self):
"""Supering the function for loading res.config.settings to pos
session"""
result = super()._pos_ui_models_to_load()
result += ['res.config.settings', 'pos.order', 'pos.order.line',
'multi.barcode.product', 'meals.planning']
return result
def _loader_params_res_config_settings(self):
"""Returning the field required"""
return {
'search_params': {'fields': ['enable_service_charge', 'visibility',
'global_selection', 'global_charge',
'global_product_id',
'custom_tip_percentage', 'barcode',
'invoice_number', 'customer_details',
'customer_name', 'customer_address',
'customer_mobile', 'customer_phone',
'customer_email', 'customer_vat',
'barcode_type'], }, }
def _get_pos_ui_res_config_settings(self, params):
"""Returns the model"""
return self.env['res.config.settings'].search_read(
**params['search_params'])
def _loader_params_pos_order(self):
"""pos_order model field load in pos session"""
return {'search_params': {
'domain': [],
'fields': ['name', 'date_order', 'pos_reference',
'partner_id', 'lines', 'exchange']}}
def _get_pos_ui_pos_order(self, params):
"""Return the model pos_order"""
return self.env['pos.order'].search_read(**params['search_params'])
def _loader_params_pos_order_line(self):
"""pos_order_line model field load in pos session"""
return {'search_params': {'domain': [],
'fields': ['product_id', 'qty',
'price_subtotal',
'total_cost']}}
def _get_pos_ui_pos_order_line(self, params):
"""Return the model pos_order_line"""
return self.env['pos.order.line'].search_read(
**params['search_params'])
def _loader_params_product_product(self):
"""loaded product template field into pos session"""
result = super()._loader_params_product_product()
result['search_params']['fields'].extend(
['is_age_restrict', 'product_multi_barcodes_ids', 'name', 'id'])
return result
def _get_pos_ui_multi_barcode_product(self, params):
""""Return the model multi_barcode_product"""
return self.env['multi.barcode.product'].with_context(
**params['context']).search_read(**params['search_params'])
def _loader_params_multi_barcode_product(self):
"""loaded multi_barcode_product field into pos session"""
return {'search_params': {'fields': ['multi_barcode'], },
'context': {'display_default_code': False}, }
def _loader_params_meals_planning(self):
""" returning corresponding data to pos"""
data = [rec.id for rec in self.env['meals.planning'].search(
[('state', '=', 'activated'),
('pos_ids', 'in', self.config_id.id)])]
return {'search_params': {'domain': [('id', '=', data)],
'fields': ['name', 'product_ids',
'time_from', 'time_to', 'state',
'pos_ids']}}
def _get_pos_ui_meals_planning(self, params):
""""Return the model meals_planning"""
return self.env['meals.planning'].search_read(**params['search_params'])

58
all_in_one_pos_kit/models/product_product.py

@ -0,0 +1,58 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Afra MP (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from odoo import api, fields, models, _
class ProductProduct(models.Model):
"""Inherit the product_product module to add new fields"""
_inherit = 'product.product'
product_multi_barcodes_ids = fields.One2many('multi.barcode.product',
'product_id',
string='Barcodes',
help='Add multi barcode for '
'product')
@api.model
def create(self, vals):
"""Super the create function to update the field
product_multi_barcodes_ids"""
res = super(ProductProduct, self).create(vals)
res.product_multi_barcodes_ids.update({
'product_template_id': res.product_tmpl_id.id
})
return res
def write(self, vals):
"""Super the write function to update the field
product_multi_barcodes_ids"""
res = super(ProductProduct, self).write(vals)
self.product_multi_barcodes_ids.update({
'product_template_id': self.product_tmpl_id.id
})
return res
@api.onchange('to_make_mrp')
def _onchange_to_make_mrp(self):
"""Function to show raise error if the product doesn't have BOM"""
if self.to_make_mrp and not self.bom_count:
raise Warning(_('Please set Bill of Material for this product.'))

66
all_in_one_pos_kit/models/product_template.py

@ -0,0 +1,66 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Afra MP (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from odoo import api, fields, models
from odoo.exceptions import ValidationError
class ProductTemplate(models.Model):
"""Inherited product.template to add field"""
_inherit = 'product.template'
is_age_restrict = fields.Boolean(string="Is Age Restricted",
help="Enable if the product is age "
"restricted")
product_template_ids = fields.One2many('multi.barcode.product',
'product_template_id',
string='Barcodes',
help='Add multi barcode for the '
'module')
to_make_mrp = fields.Boolean(string='To Create MRP Order',
help="Check if the product should be make mrp "
"order")
@api.model
def create(self, vals):
"""Super the create function to update the field product_template_ids"""
res = super(ProductTemplate, self).create(vals)
res.product_template_ids.update({
'product_id': res.product_variant_id.id
})
return res
def write(self, vals):
"""Super the write function to update the field product_template_ids"""
res = super(ProductTemplate, self).write(vals)
if self.product_template_ids:
self.product_template_ids.update({
'product_id': self.product_variant_id.id
})
return res
@api.onchange('to_make_mrp')
def _onchange_to_make_mrp(self):
"""Function to show raise error if the product doesn't have BOM"""
if self.to_make_mrp:
if not self.bom_count:
raise ValidationError(
'Please set Bill of Material for this product.')

146
all_in_one_pos_kit/models/res_config_settings.py

@ -0,0 +1,146 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Afra MP (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from odoo import api, fields, models
class ResConfigSettings(models.TransientModel):
"""Inherited Configuration Settings"""
_inherit = "res.config.settings"
enable_service_charge = fields.Boolean(
string="Service Charges",
config_parameter="all_in_one_pos_kit.enable_service_charge",
help="Enable to add service charge")
visibility = fields.Selection(
[('global', 'Global'), ('session', 'Session')],
default='global', string="Visibility",
config_parameter="all_in_one_pos_kit.visibility",
help='Setup the Service charge globally or per session')
global_selection = fields.Selection([
('amount', 'Amount'),
('percentage', 'Percentage')],
string='Type', default='amount',
config_parameter="all_in_one_pos_kit.global_selection",
help='Set the service charge as a amount or percentage')
global_charge = fields.Float(
string='Service Charge',
config_parameter="all_in_one_pos_kit.global_charge",
help='Set a default service charge globally')
global_product_id = fields.Many2one(
'product.product', string='Service Product',
domain="[('available_in_pos', '=', True),('sale_ok', '=', True),"
"('type', '=', 'service')]",
config_parameter="all_in_one_pos_kit.global_product_id",
help='Set a service product globally')
custom_tip_percentage = fields.Float(
string="Custom Percentage",
config_parameter='all_in_one_pos_kit.custom_tip_percentage',
help="enter the percentage custom tips")
barcode = fields.Boolean(string='Order Barcode',
config_parameter='all_in_one_pos_kit.barcode',
help='Enable or disable the display of order '
'barcode')
invoice_number = fields.Boolean(
string='Invoice Number',
config_parameter='all_in_one_pos_kit.invoice_number',
help='Enable or disable the display of invoice number')
customer_details = fields.Boolean(
string='Customer Details',
config_parameter='all_in_one_pos_kit.customer_details',
help='Enable or disable the display of customer details')
customer_name = fields.Boolean(
string='Customer Name',
config_parameter='all_in_one_pos_kit.customer_name',
help='Enable or disable the display of customer name')
customer_address = fields.Boolean(
string='Customer Address',
config_parameter='all_in_one_pos_kit.customer_address',
help='Enable or disable the display of customer address')
customer_mobile = fields.Boolean(
string='Customer Mobile',
config_parameter='all_in_one_pos_kit.customer_mobile',
help='Enable or disable the display of customer mobile number')
customer_phone = fields.Boolean(
string='Customer Phone',
config_parameter='all_in_one_pos_kit.customer_phone',
help='Enable or disable the display of customer phone number')
customer_email = fields.Boolean(
string='Customer Email',
config_parameter='all_in_one_pos_kit.customer_email',
help='Enable or disable the display of customer email')
customer_vat = fields.Boolean(
string='Customer VAT',
config_parameter='all_in_one_pos_kit.customer_vat',
help='Enable or disable the display of customer VAT number')
barcode_type = fields.Selection(
selection=[('barcode', 'Barcode'),('qr_code', 'QRCode')],
string='Barcode Type',
config_parameter='all_in_one_pos_kit.barcode_type',
help='Select the type of barcode to be displayed (Barcode or QRCode)')
customer_msg = fields.Boolean(string='POS Greetings',
config_parameter='pos.customer_msg',
help='Create an account if you ever create an'
'account')
auth_token = fields.Char(string='Auth Token',
config_parameter='pos.auth_token',
help='Copy the token from your twilio console '
'window adn paste here')
account_sid = fields.Char(string='Account SID',
config_parameter='pos.account_sid',
help='Enter the Account SID provided by Twilio '
'for authentication.')
twilio_number = fields.Char(string='Twilio Number',
config_parameter='pos.twilio_number',
help='Enter the Twilio phone number used to '
'send the SMS.')
sms_body = fields.Text(string='Body',
help='Enter the content or message of the SMS to be'
'sent.')
@api.onchange('enable_service_charge')
def _onchange_enable_service_charge(self):
"""When the service charge is enabled set service product and amount
by default in globally"""
if self.enable_service_charge and not self.global_product_id:
self.global_product_id = self.env['product.product'].search(
[('available_in_pos', '=', True), ('sale_ok', '=', True),
('type', '=', 'service')], limit=1)
self.global_charge = 10.0
else:
self.global_product_id = False
self.global_charge = 0.0
def set_values(self):
"""Override method to set configuration values.
:return: Result of the super method"""
res = super(ResConfigSettings, self).set_values()
self.env['ir.config_parameter'].set_param(
'pos.sms_body', self.sms_body)
return res
def get_values(self):
"""Override method to get configuration values.
:return: Dictionary of configuration values"""
res = super(ResConfigSettings, self).get_values()
res.update(sms_body=self.env['ir.config_parameter'].sudo().get_param(
'pos.sms_body'))
return res

47
all_in_one_pos_kit/models/res_users.py

@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Afra MP (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from odoo import api, fields, models
class ResUsers(models.Model):
"""Inherit the class res_users to add field"""
_inherit = "res.users"
pos_conf_id = fields.Many2one('pos.config', string="POS Configuration",
help='select POS for the user')
pos_config_ids = fields.Many2many('pos.config', string='Allowed Pos',
help='Allowed Pos for this user')
show_users = fields.Boolean(string="Show users of pos", default=True,
help='Show users in dashboard ( for pos '
'administrators only)')
@api.model
def create(self, vals):
"""This method creates a new record for the ResUsers model with the
provided values. It clears the caches before creating the record."""
self.clear_caches()
return super(ResUsers, self).create(vals)
def write(self, vals):
"""For clearing out existing values and update with new values"""
self.clear_caches()
return super(ResUsers, self).write(vals)

58
all_in_one_pos_kit/models/stock_lot.py

@ -0,0 +1,58 @@
# -*- coding: utf-8 -*-
################################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Afra MP (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
from odoo import api, models
from odoo.tools import float_compare
class StockLot(models.Model):
"""This class inherits from the "stock.lot" model, which represents lots of
products in the inventory.It adds additional methods and fields to enhance
the functionality related to lots."""
_inherit = "stock.lot"
@api.model
def get_available_lots_for_pos(self, product_id, ):
"""Get available lots for a product suitable for the Point of Sale
(PoS).This method retrieves the available lots for a specific product
that are suitable for the Point of Sale (PoS) based on the configured
removal strategy. The lots are sorted based on the expiration date or
creation date,depending on the removal strategy."""
company_id = self.env.company.id
removal_strategy_id = (self.env['product.template'].browse(
self.env['product.product'].browse(product_id).product_tmpl_id.id)
.categ_id.removal_strategy_id.method)
if removal_strategy_id == 'fefo':
lots = self.sudo().search(
["&", ["product_id", "=", product_id], "|",
["company_id", "=", company_id],
["company_id", "=", False]],
order='expiration_date asc')
else:
lots = self.sudo().search(
["&", ["product_id", "=", product_id], "|",
["company_id", "=", company_id],
["company_id", "=", False], ],
order='create_date asc')
lots = lots.filtered(lambda l: float_compare(
l.product_qty, 0,
precision_digits=l.product_uom_id.rounding) > 0)[:1]
return lots.mapped("name")

22
all_in_one_pos_kit/report/__init__.py

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

42
all_in_one_pos_kit/report/all_in_one_pos_kit_report.py

@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
###############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
# Author: Afra MP (odoo@cybrosys.com)
#
# You can modify it under the terms of the GNU AFFERO
# GENERAL PUBLIC LICENSE (AGPL 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
#
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
# (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
###############################################################################
from odoo import api, models
class PosOrder(models.AbstractModel):
"""Model to generate the POS order report."""
_name = 'report.all_in_one_pos_kit.pos_order_report'
@api.model
def _get_report_values(self, docids, data=None):
"""Get the report values for generating the POS order report.
:param docids: The IDs of the records to include in the report.
:param data: Additional data for generating the report (optional).
:return: A dictionary containing the report values."""
if self.env.context.get('pos_order_report'):
if data.get('report_data'):
data.update({
'report_main_line_data': data.get('report_data')[
'report_lines'],
'Filters': data.get('report_data')['filters'],
'company': self.env.company})
return data

432
all_in_one_pos_kit/report/all_in_one_pos_kit_templates.xml

@ -0,0 +1,432 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="pos_order_report">
<!-- Template to filter the report based on the selected report type -->
<t t-call="web.html_container">
<t t-call="web.internal_layout">
<t t-if="Filters.get('report_type')=='Report By Order'">
<t t-call="all_in_one_pos_kit.report_order"/>
</t>
<t t-if="Filters.get('report_type')=='Report By Order Detail'">
<t t-call="all_in_one_pos_kit.report_order_detail"/>
</t>
<t t-if="Filters.get('report_type')=='Report By Product'">
<t t-call="all_in_one_pos_kit.report_product"/>
</t>
<t t-if="Filters.get('report_type')=='Report By Categories'">
<t t-call="all_in_one_pos_kit.report_category"/>
</t>
<t t-if="Filters.get('report_type')=='Report By Salesman'">
<t t-call="all_in_one_pos_kit.report_salesman"/>
</t>
<t t-if="Filters.get('report_type')=='Report By Payment'">
<t t-call="all_in_one_pos_kit.report_payment"/>
</t>
</t>
</t>
</template>
<template id="report_order">
<!-- Template for generating a report by order. It displays information
such as PoS,order, date order, customer, salesman, total quantity,
total amount, and note. -->
<div class="page">
<div class="oe_structure"/>
<span t-if="Filters.get('date_from')">
<strong>From:</strong>
<t t-esc="Filters['date_from']"/>
</span>
<span t-if="Filters.get('date_to')">
<strong>To:</strong>
<t t-esc="Filters['date_to']"/>
</span>
<div>
<div style="width:100%;">
<div style="text-align:centre;" class="row">
<div class="col-2">
<strong>Report Type:</strong>
<t t-esc="Filters.get('report_type')"/>
</div>
</div>
</div>
<br></br>
<table class="table table-sm table-reports">
<thead>
<tr class="text-right">
<th colspan="6">PoS</th>
<th colspan="6">Order</th>
<th colspan="6">Date Order</th>
<th colspan="6">Customer</th>
<th colspan="6">Salesman</th>
<th colspan="6">Total Qty</th>
<th colspan="6">Amount Total</th>
<th colspan="6">Note</th>
</tr>
</thead>
<tbody>
<t t-foreach="report_main_line_data" t-as="main">
<tr style="font-weight: bold;">
<td colspan="6">
<span t-esc="main['shop']"/>
</td>
<td colspan="6">
<span t-esc="main['session']"/>
</td>
<td colspan="6">
<span t-esc="main['date_order']"/>
</td>
<td colspan="6">
<span t-esc="main['name']"/>
</td>
<td colspan="6">
<span t-esc="main['salesman']"/>
</td>
<td colspan="6">
<span t-esc="main['sum']"/>
</td>
<td colspan="6">
<span t-esc="main['amount_total']"/>
</td>
<td colspan="6">
<span t-esc="main['note']"/>
</td>
</tr>
</t>
</tbody>
</table>
</div>
<br></br>
</div>
</template>
<template id="report_order_detail">
<!-- Template for generating a detailed report by order. It includes
additional information such as product code, product name, price unit,
quantity, subtotal price, and subtotal price including taxes. -->
<div class="page">
<div class="oe_structure"/>
<span t-if="Filters.get('date_from')">
<strong>From:</strong>
<t t-esc="Filters['date_from']"/>
</span>
<span t-if="Filters.get('date_to')">
<strong>To:</strong>
<t t-esc="Filters['date_to']"/>
</span>
<div>
<div style="width:100%;">
<div style="text-align:centre;" class="row">
<div class="col-2">
<strong>Report Type:</strong>
<t t-esc="Filters.get('report_type')"/>
</div>
</div>
</div>
<br></br>
<table class="table table-sm table-reports">
<thead>
<tr class="text-right">
<th colspan="6">PoS</th>
<th colspan="6">Order</th>
<th colspan="6">Date Order</th>
<th colspan="6">Customer</th>
<th colspan="6">Salesman</th>
<th colspan="6">Product Code</th>
<th colspan="6">Product Name</th>
<th colspan="6">Price unit</th>
<th colspan="6">Qty</th>
<th colspan="6">Price Subtotal</th>
<th colspan="6">Price Subtotal Incl</th>
</tr>
</thead>
<tbody>
<t t-foreach="report_main_line_data" t-as="main">
<tr style="font-weight: bold;">
<td colspan="6">
<span t-esc="main['shop']"/>
</td>
<td colspan="6">
<span t-esc="main['session']"/>
</td>
<td colspan="6">
<span t-esc="main['date_order']"/>
</td>
<td colspan="6">
<span t-esc="main['name']"/>
</td>
<td colspan="6">
<span t-esc="main['salesman']"/>
</td>
<td colspan="6">
<span t-esc="main['default_code']"/>
</td>
<td colspan="6">
<span t-esc="main['full_product_name']"/>
</td>
<td colspan="6">
<span t-esc="main['price_unit']"/>
</td>
<td colspan="6">
<span t-esc="main['sum']"/>
</td>
<td colspan="6">
<span t-esc="main['price_subtotal']"/>
</td>
<td colspan="6">
<span t-esc="main['price_subtotal_incl']"/>
</td>
</tr>
</t>
</tbody>
</table>
</div>
<br></br>
</div>
</template>
<template id="report_product">
<!-- Template for generating a report by product. It shows information
such as category, product code, product name, quantity, total amount,
and total amount including taxes. -->
<div class="page">
<div class="oe_structure"/>
<span t-if="Filters.get('date_from')">
<strong>From:</strong>
<t t-esc="Filters['date_from']"/>
</span>
<span t-if="Filters.get('date_to')">
<strong>To:</strong>
<t t-esc="Filters['date_to']"/>
</span>
<div>
<div style="width:100%;">
<div style="text-align:centre;" class="row">
<div class="col-2">
<strong>Report Type:</strong>
<t t-esc="Filters.get('report_type')"/>
</div>
</div>
</div>
<br></br>
<table class="table table-sm table-reports">
<thead>
<tr class="text-right">
<th colspan="6">Category</th>
<th colspan="6">Product Code</th>
<th colspan="6">Product Name</th>
<th colspan="6">Qty</th>
<th colspan="6">Amount Total</th>
<th colspan="6">Amount Total Incl</th>
</tr>
</thead>
<tbody>
<t t-foreach="report_main_line_data" t-as="main">
<tr style="font-weight: bold;">
<td colspan="6">
<span t-esc="main['name']"/>
</td>
<td colspan="6">
<span t-esc="main['default_code']"/>
</td>
<td colspan="6">
<span t-esc="main['full_product_name']"/>
</td>
<td colspan="6">
<span t-esc="main['qty']"/>
</td>
<td colspan="6">
<span t-esc="main['amount_total']"/>
</td>
<td colspan="6">
<span t-esc="main['amount_total']"/>
</td>
</tr>
</t>
</tbody>
</table>
</div>
<br></br>
</div>
</template>
<template id="report_category">
<!-- Template for generating a report by category. It displays
information about categories, quantity, total amount, and total amount
including taxes. -->
<div class="page">
<div class="oe_structure"/>
<span t-if="Filters.get('date_from')">
<strong>From:</strong>
<t t-esc="Filters['date_from']"/>
</span>
<span t-if="Filters.get('date_to')">
<strong>To:</strong>
<t t-esc="Filters['date_to']"/>
</span>
<div>
<div style="width:100%;">
<div style="text-align:centre;" class="row">
<div class="col-2">
<strong>Report Type:</strong>
<t t-esc="Filters.get('report_type')"/>
</div>
</div>
</div>
<br></br>
<table class="table table-sm table-reports">
<thead>
<tr>
<th colspan="6">Category</th>
<th colspan="6">Qty</th>
<th colspan="6">Amount Total</th>
<th colspan="6">Amount Total Incl</th>
</tr>
</thead>
<tbody>
<t t-foreach="report_main_line_data"
t-as="pos_category">
<tr style="font-weight: bold;">
<td colspan="6">
<span t-esc="pos_category['name']"/>
</td>
<td colspan="6">
<span t-esc="pos_category['qty']"/>
</td>
<td colspan="6">
<span t-esc="pos_category['amount_total']"/>
</td>
<td colspan="6">
<span t-esc="pos_category['total_incl']"/>
</td>
</tr>
</t>
</tbody>
</table>
</div>
<br></br>
</div>
</template>
<template id="report_salesman">
<!-- Template for generating a report by salesman. It includes
information about the salesman, total orders, total quantity, and
total amount. -->
<div class="page">
<div class="oe_structure"/>
<span t-if="Filters.get('date_from')">
<strong>From:</strong>
<t t-esc="Filters['date_from']"/>
</span>
<span t-if="Filters.get('date_to')">
<strong>To:</strong>
<t t-esc="Filters['date_to']"/>
</span>
<div>
<div style="width:100%;">
<div style="text-align:centre;" class="row">
<div class="col-2">
<strong>Report Type:</strong>
<t t-esc="Filters.get('report_type')"/>
</div>
</div>
</div>
<br></br>
<table class="table table-sm table-reports">
<thead>
<tr>
<th>Salesman</th>
<th colspan="6">Total Order</th>
<th colspan="6">Total Qty</th>
<th colspan="6">Total Amount</th>
</tr>
</thead>
<tbody>
<t t-foreach="report_main_line_data" t-as="main">
<tr style="font-weight: bold;">
<td>
<span t-esc="main['name']"/>
</td>
<td colspan="6">
<span t-esc="main['order']"/>
</td>
<td colspan="6">
<span t-esc="main['qty']"/>
</td>
<td colspan="6">
<span t-esc="main['amount']"/>
</td>
</tr>
</t>
</tbody>
</table>
</div>
<br></br>
</div>
</template>
<template id="report_payment">
<!-- Template for generating a report by payment. It shows details about
the point of sale, PoS session, payment methods, and total amount. -->
<div class="page">
<div class="oe_structure"/>
<span t-if="Filters.get('date_from')">
<strong>From:</strong>
<t t-esc="Filters['date_from']"/>
</span>
<span t-if="Filters.get('date_to')">
<strong>To:</strong>
<t t-esc="Filters['date_to']"/>
</span>
<div>
<div style="width:100%;">
<div style="text-align:centre;" class="row">
<div class="col-2">
<strong>Report Type:</strong>
<t t-esc="Filters.get('report_type')"/>
</div>
</div>
</div>
<br></br>
<table class="table table-sm table-reports">
<thead>
<tr>
<th>Point of Sale</th>
<th colspan="6">PoS Session</th>
<th colspan="6">Payment</th>
<th colspan="6">Total Amount</th>
</tr>
</thead>
<tbody>
<t t-foreach="report_main_line_data" t-as="main">
<tr style="font-weight: bold;">
<td>
<span t-esc="main['config']"/>
</td>
<td colspan="6">
<span t-esc="main['session']"/>
</td>
<td colspan="6">
<span>
<t t-foreach="main['name']" t-as="nme">
<t t-esc="main['name'][nme]"/>
</t>
</span>
</td>
<td colspan="6">
<span t-esc="main['sum']"/>
</td>
</tr>
</t>
</tbody>
</table>
</div>
<br></br>
</div>
</template>
<record id="action_report_pos_all_in_one" model="ir.actions.report">
<field name="name">POS All In One Report</field>
<field name="model">pos.report</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">all_in_one_pos_kit.pos_order_report</field>
<field name="report_file">all_in_one_pos_kit.pos_order_report</field>
</record>
</odoo>

43
all_in_one_pos_kit/security/all_in_one_pos_kit_security.xml

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record id="restrict_user" model="ir.rule">
<!-- Restrict access to Configurations for Users -->
<field name="name">Config User</field>
<field name="model_id" ref="point_of_sale.model_pos_config"/>
<field name="domain_force">[('id','in',user.pos_config_ids.ids)]</field>
<field name="groups" eval="[(4,ref('point_of_sale.group_pos_user'))]"/>
</record>
<record id="restrict_manager" model="ir.rule">
<!-- Restrict access to Configurations for Managers -->
<field name="name">Config Manager</field>
<field name="model_id" ref="point_of_sale.model_pos_config"/>
<field name="domain_force">[]</field>
<field name="groups"
eval="[(4,ref('point_of_sale.group_pos_manager'))]"/>
</record>
<record id="order_user" model="ir.rule">
<!-- Restrict access to Orders for Users -->
<field name="name">Orders User</field>
<field name="model_id" ref="point_of_sale.model_pos_order"/>
<field name="domain_force">
[('config_id','in',user.pos_config_ids.ids)]
</field>
<field name="groups" eval="[(4,ref('point_of_sale.group_pos_user'))]"/>
</record>
<record id="order_manager" model="ir.rule">
<!-- Orders Manager Rule -->
<field name="name">Orders Manager</field>
<field name="model_id" ref="point_of_sale.model_pos_order"/>
<field name="domain_force">[]</field>
<field name="groups"
eval="[(4,ref('point_of_sale.group_pos_manager'))]"/>
</record>
<record id="meals_panning_rule_company" model="ir.rule">
<!-- Multi Planning Multi Company Rule -->
<field name="name">multi panning multi company rule</field>
<field name="model_id" ref="model_meals_planning"/>
<field name="domain_force">
['|',('company_id','=',False),('company_id', 'in', company_ids)]
</field>
</record>
</odoo>

8
all_in_one_pos_kit/security/ir.model.access.csv

@ -0,0 +1,8 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_multi_barcode_product,access.multi.barcode.product,model_multi_barcode_product,base.group_user,1,1,1,1
access_mrp_production_pos_user,access.mrp.production.pos.user,model_mrp_production,point_of_sale.group_pos_user,1,1,1,0
access_mrp_bom_pos_user,access.mrp.bom.pos.user,mrp.model_mrp_bom,point_of_sale.group_pos_user,1,0,0,0
access_pos_report,access.pos.report,model_pos_report,base.group_user,1,1,1,1
access_pos_greetings,access.pos.greetings,model_pos_greetings,base.group_user,1,0,1,0
access_meals_planning_user,access.meals.planning.user,model_meals_planning,point_of_sale.group_pos_user,1,0,0,0
access_meals_planning_manager,access.meals.planning.manager,model_meals_planning,point_of_sale.group_pos_manager,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_multi_barcode_product access.multi.barcode.product model_multi_barcode_product base.group_user 1 1 1 1
3 access_mrp_production_pos_user access.mrp.production.pos.user model_mrp_production point_of_sale.group_pos_user 1 1 1 0
4 access_mrp_bom_pos_user access.mrp.bom.pos.user mrp.model_mrp_bom point_of_sale.group_pos_user 1 0 0 0
5 access_pos_report access.pos.report model_pos_report base.group_user 1 1 1 1
6 access_pos_greetings access.pos.greetings model_pos_greetings base.group_user 1 0 1 0
7 access_meals_planning_user access.meals.planning.user model_meals_planning point_of_sale.group_pos_user 1 0 0 0
8 access_meals_planning_manager access.meals.planning.manager model_meals_planning point_of_sale.group_pos_manager 1 1 1 1

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 839 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 627 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 988 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 967 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
all_in_one_pos_kit/static/description/assets/modules/1.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 678 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/10.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/11.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 990 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/12.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 465 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/13.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/14.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 636 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/15.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/16.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/17.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/18.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/19.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/20.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/21.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/22.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/23.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/24.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/25.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/26.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 440 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/27.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/28.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/29.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/30.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/31.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/32.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/33.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 669 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/34.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 657 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/35.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 524 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/36.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/37.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 661 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/38.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 KiB

BIN
all_in_one_pos_kit/static/description/assets/screenshots/39.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save