Browse Source

May 09: [ADD] Initital Commit 'laundry_management_pos'

pull/320/head
RisvanaCybro 1 year ago
parent
commit
c81ea47091
  1. 49
      laundry_management_pos/README.rst
  2. 22
      laundry_management_pos/__init__.py
  3. 66
      laundry_management_pos/__manifest__.py
  4. 21
      laundry_management_pos/controllers/__init__.py
  5. 47
      laundry_management_pos/controllers/laundry_management_pos.py
  6. 6
      laundry_management_pos/doc/RELEASE_NOTES.md
  7. 25
      laundry_management_pos/models/__init__.py
  8. 226
      laundry_management_pos/models/laundry_order.py
  9. 33
      laundry_management_pos/models/pos_config.py
  10. 160
      laundry_management_pos/models/pos_order.py
  11. BIN
      laundry_management_pos/static/description/assets/icons/check.png
  12. BIN
      laundry_management_pos/static/description/assets/icons/chevron.png
  13. BIN
      laundry_management_pos/static/description/assets/icons/cogs.png
  14. BIN
      laundry_management_pos/static/description/assets/icons/consultation.png
  15. BIN
      laundry_management_pos/static/description/assets/icons/ecom-black.png
  16. BIN
      laundry_management_pos/static/description/assets/icons/education-black.png
  17. BIN
      laundry_management_pos/static/description/assets/icons/hotel-black.png
  18. BIN
      laundry_management_pos/static/description/assets/icons/license.png
  19. BIN
      laundry_management_pos/static/description/assets/icons/lifebuoy.png
  20. BIN
      laundry_management_pos/static/description/assets/icons/manufacturing-black.png
  21. BIN
      laundry_management_pos/static/description/assets/icons/pos-black.png
  22. BIN
      laundry_management_pos/static/description/assets/icons/puzzle.png
  23. BIN
      laundry_management_pos/static/description/assets/icons/restaurant-black.png
  24. BIN
      laundry_management_pos/static/description/assets/icons/service-black.png
  25. BIN
      laundry_management_pos/static/description/assets/icons/trading-black.png
  26. BIN
      laundry_management_pos/static/description/assets/icons/training.png
  27. BIN
      laundry_management_pos/static/description/assets/icons/update.png
  28. BIN
      laundry_management_pos/static/description/assets/icons/user.png
  29. BIN
      laundry_management_pos/static/description/assets/icons/wrench.png
  30. BIN
      laundry_management_pos/static/description/assets/misc/categories.png
  31. BIN
      laundry_management_pos/static/description/assets/misc/check-box.png
  32. BIN
      laundry_management_pos/static/description/assets/misc/compass.png
  33. BIN
      laundry_management_pos/static/description/assets/misc/corporate.png
  34. BIN
      laundry_management_pos/static/description/assets/misc/customer-support.png
  35. BIN
      laundry_management_pos/static/description/assets/misc/cybrosys-logo.png
  36. BIN
      laundry_management_pos/static/description/assets/misc/features.png
  37. BIN
      laundry_management_pos/static/description/assets/misc/logo.png
  38. BIN
      laundry_management_pos/static/description/assets/misc/pictures.png
  39. BIN
      laundry_management_pos/static/description/assets/misc/pie-chart.png
  40. BIN
      laundry_management_pos/static/description/assets/misc/right-arrow.png
  41. BIN
      laundry_management_pos/static/description/assets/misc/star.png
  42. BIN
      laundry_management_pos/static/description/assets/misc/support.png
  43. BIN
      laundry_management_pos/static/description/assets/misc/whatsapp.png
  44. BIN
      laundry_management_pos/static/description/assets/modules/l1.png
  45. BIN
      laundry_management_pos/static/description/assets/modules/l2.png
  46. BIN
      laundry_management_pos/static/description/assets/modules/l3.png
  47. BIN
      laundry_management_pos/static/description/assets/modules/l4.png
  48. BIN
      laundry_management_pos/static/description/assets/modules/l5.png
  49. BIN
      laundry_management_pos/static/description/assets/modules/l6.png
  50. BIN
      laundry_management_pos/static/description/assets/screenshots/1.png
  51. BIN
      laundry_management_pos/static/description/assets/screenshots/10.png
  52. BIN
      laundry_management_pos/static/description/assets/screenshots/11.png
  53. BIN
      laundry_management_pos/static/description/assets/screenshots/12.png
  54. BIN
      laundry_management_pos/static/description/assets/screenshots/13.png
  55. BIN
      laundry_management_pos/static/description/assets/screenshots/14.png
  56. BIN
      laundry_management_pos/static/description/assets/screenshots/2.png
  57. BIN
      laundry_management_pos/static/description/assets/screenshots/3.png
  58. BIN
      laundry_management_pos/static/description/assets/screenshots/4.png
  59. BIN
      laundry_management_pos/static/description/assets/screenshots/5.png
  60. BIN
      laundry_management_pos/static/description/assets/screenshots/6.png
  61. BIN
      laundry_management_pos/static/description/assets/screenshots/7.png
  62. BIN
      laundry_management_pos/static/description/assets/screenshots/8.png
  63. BIN
      laundry_management_pos/static/description/assets/screenshots/9.png
  64. BIN
      laundry_management_pos/static/description/assets/screenshots/hero.gif
  65. BIN
      laundry_management_pos/static/description/banner.png
  66. BIN
      laundry_management_pos/static/description/icon.png
  67. 680
      laundry_management_pos/static/description/index.html
  68. 109
      laundry_management_pos/static/src/css/pos.css
  69. 81
      laundry_management_pos/static/src/js/button/product_create_button.js
  70. 46
      laundry_management_pos/static/src/js/button/washing_type_button.js
  71. 67
      laundry_management_pos/static/src/js/models.js
  72. 22
      laundry_management_pos/static/src/js/order_line.js
  73. 18
      laundry_management_pos/static/src/js/pos_receipt.js
  74. 17
      laundry_management_pos/static/src/js/product_img.js
  75. 50
      laundry_management_pos/static/src/js/screen/product_create_popup.js
  76. 43
      laundry_management_pos/static/src/js/screen/product_screen.js
  77. 34
      laundry_management_pos/static/src/js/screen/washing_type_popup.js
  78. 11
      laundry_management_pos/static/src/xml/button/product_create_button.xml
  79. 25
      laundry_management_pos/static/src/xml/button/washing_type_button.xml
  80. 57
      laundry_management_pos/static/src/xml/pos_receipt.xml
  81. 11
      laundry_management_pos/static/src/xml/product_img.xml
  82. 97
      laundry_management_pos/static/src/xml/screen/product_create_popup.xml
  83. 41
      laundry_management_pos/static/src/xml/screen/washing_type_popup.xml
  84. 31
      laundry_management_pos/views/laundry_order_views.xml
  85. 26
      laundry_management_pos/views/pos_config_views.xml
  86. 25
      laundry_management_pos/views/pos_order_views.xml

49
laundry_management_pos/README.rst

@ -0,0 +1,49 @@
.. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
POS Laundry Management
======================
* From the POS we need to generate Laundry orders in the back end with out close the current window.
* Automatically create Laundry order form POS sale.
* We can assign which products make Laundry order Automatically.
* We can assign which Service type make Laundry order.
Configuration
=============
* No additional configurations needed
Company
-------
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__
License
-------
Affero General Public License v3.0 (AGPL v3)
(https://www.gnu.org/licenses/agpl-3.0-standalone.html)
Credits
-------
Developer: (V16) Unnimaya C O, Contact: odoo@cybrosys.com
Contacts
--------
* Mail Contact : odoo@cybrosys.com
* Website : https://cybrosys.com
Bug Tracker
-----------
Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported.
Maintainer
==========
.. image:: https://cybrosys.com/images/logo.png
:target: https://cybrosys.com
This module is maintained by Cybrosys Technologies.
For support and more information, please visit `Our Website <https://cybrosys.com/>`__
Further information
===================
HTML Description: `<static/description/index.html>`__

22
laundry_management_pos/__init__.py

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Unnimaya C O (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
# GENERAL PUBLIC LICENSE (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import controllers
from . import models

66
laundry_management_pos/__manifest__.py

@ -0,0 +1,66 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Unnimaya C O (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
# GENERAL PUBLIC LICENSE (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': "POS Laundry Management",
'version': '16.0.1.0.0',
'category': 'Point of Sale',
'summary': """Launch Automatic Laundry Orders After selling Through POS.""",
'description': """It manages the Point of sale laundry process with assigning works to workers.We can create
Laundry orders with the help of POS.""",
'author': 'Cybrosys Techno Solutions',
'company': 'Cybrosys Techno Solutions',
'maintainer': 'Cybrosys Techno Solutions',
'website': 'https://www.cybrosys.com',
'depends': ['point_of_sale', 'laundry_management'],
'data': [
'views/pos_config_views.xml',
'views/laundry_order_views.xml',
'views/pos_order_views.xml'
],
'assets': {
'web.assets_backend': [
'laundry_management_pos/static/src/css/pos.css',
],
'point_of_sale.assets': [
'laundry_management_pos/static/src/xml/button/washing_type_button.xml',
'laundry_management_pos/static/src/js/button/washing_type_button.js',
'laundry_management_pos/static/src/js/screen/washing_type_popup.js',
'laundry_management_pos/static/src/xml/screen/washing_type_popup.xml',
'laundry_management_pos/static/src/js/models.js',
'laundry_management_pos/static/src/js/order_line.js',
'laundry_management_pos/static/src/js/pos_receipt.js',
'laundry_management_pos/static/src/xml/pos_receipt.xml',
'laundry_management_pos/static/src/js/product_img.js',
'laundry_management_pos/static/src/xml/product_img.xml',
'laundry_management_pos/static/src/js/screen/product_screen.js',
'laundry_management_pos/static/src/css/pos.css',
'laundry_management_pos/static/src/xml/button/product_create_button.xml',
'laundry_management_pos/static/src/js/button/product_create_button.js',
'laundry_management_pos/static/src/js/screen/product_create_popup.js',
'laundry_management_pos/static/src/xml/screen/product_create_popup.xml'
],
},
'images': ['static/description/banner.png'],
'license': 'AGPL-3',
'installable': True,
'auto_install': False,
'application': False,
}

21
laundry_management_pos/controllers/__init__.py

@ -0,0 +1,21 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Unnimaya C O (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
# GENERAL PUBLIC LICENSE (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import laundry_management_pos

47
laundry_management_pos/controllers/laundry_management_pos.py

@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Unnimaya C O (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
# GENERAL PUBLIC LICENSE (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import http
from odoo.http import request
class PosProductCreation(http.Controller):
"""Class PosProductCreation is used to create a product from the POS
Screen"""
@http.route('/create_product', type="json", auth="none")
def create_product(self, category, name, price, product_reference,
unit_measure, product_categories):
"""Used for creating product from the point of sale view
that easily create a new product from the point of sale"""
categories = {
'Consumable': 'consu',
'Service': 'service',
'Storable': 'product'
}
request.env['product.template'].sudo().create({
'name': name,
'detailed_type': categories.get(category, ''),
'default_code': product_reference,
'list_price': float(price),
'uom_id': int(unit_measure),
'uom_po_id': int(unit_measure),
'categ_id': int(product_categories),
'available_in_pos': True,
})

6
laundry_management_pos/doc/RELEASE_NOTES.md

@ -0,0 +1,6 @@
## Module <laundry_management_pos>
#### 04.05.2024
#### Version 16.0.1.0.0
#### ADD
- Initial commit for POS Laundry Management

25
laundry_management_pos/models/__init__.py

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Unnimaya C O (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
# GENERAL PUBLIC LICENSE (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from . import laundry_order
from . import pos_config
from . import pos_order

226
laundry_management_pos/models/laundry_order.py

@ -0,0 +1,226 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Unnimaya C O (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
# GENERAL PUBLIC LICENSE (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import json
from odoo import api, fields, models, _
class LaundryOrder(models.Model):
""" This class is inherited for model laundry_order.
It contains fields and the functions for the model
Methods:
_compute_amount_all(self):
Action perform to computing the total amounts of the LaundryOrder.
_compute_tax_totals_json(self):
Action perform to computing the total tax amount using the order-lines tax and amount.
_invoice_count(self):
Action perform to computing the invoice count based on the particular Laundry order.
_work_count(self):
Action perform to computing the work count based on the particular Laundry order.
action_view_laundry_works(self):
Action perform to works details of the LaundryOrder , the laundry work smart button views are displayed.
action_view_invoice(self):
Action perform to Invoice details of the LaundryOrder when opening the smart button we can view the invoice details.
"""
_inherit = 'laundry.order'
order_ref = fields.Char(string='Order Ref',
help='Reference field for order')
pos_reference = fields.Char(string='Receipt Number',
help='Reference field for POS')
is_invoiced = fields.Boolean(string='Is Invoiced', invisible=1,
help='Boolean field for checking and '
'adding the invoices')
pos_order = fields.Boolean(string='Is POS order',
help='Boolean field for pos order '
'identification')
pos_order_id = fields.Many2one('pos.order', string='POS order',
help='Relating the many2one field for pos.order')
tax_totals_json = fields.Char(compute='_compute_tax_totals_json',
help='For computing the tax ')
amount_untaxed = fields.Monetary(string='Untaxed Amount',
compute='_compute_amount_all',
help='For computing the untaxed amount')
amount_tax = fields.Monetary(string='Taxes', compute='_compute_amount_all',
help='Compute the tax amounts')
total_amount = fields.Monetary(string='Total', store=True,
compute='_compute_amount_all',
help='Compute the total amount')
@api.depends('order_lines')
def _compute_amount_all(self):
"""
Compute the total amounts of the LaundryOrder.
"""
for order in self:
amount_untaxed = amount_tax = 0.0
for line in order.order_lines:
amount_untaxed += line.amount
amount_tax += line.price_tax
order.update({
'amount_untaxed': amount_untaxed,
'amount_tax': amount_tax,
'total_amount': amount_untaxed + amount_tax,
})
@api.depends('order_lines.tax_ids', 'order_lines.amount',
'total_amount')
def _compute_tax_totals_json(self):
""" computing the total tax amount using the order-lines
tax and amount"""
def compute_taxes(order_lines):
price = order_lines.amount
orders = order_lines.laundry_obj
return order_lines.tax_ids._origin.compute_all(price,
orders.currency_id,
product=
order_lines.product_id,
partner=
orders.partner_shipping_id)
for order in self:
tax_lines_data = self.env['account.move']._prepare_tax_lines_data_for_totals_from_object(
order.order_lines, compute_taxes)
tax_totals = self.env['account.move']._get_tax_totals(
order.partner_id, tax_lines_data, order.order_lines.amount,
order.total_amount, order.currency_id)
order.tax_totals_json = json.dumps(tax_totals)
def _invoice_count(self):
"""Computing the invoice count based on the particular Laundry order
override the _invoice_count function"""
work = self.env['pos.order'].search(
[('name', '=', self.order_ref)])
if not work:
wrk_ordr_ids = self.env['account.move'].search([('invoice_origin', '=',
self.sale_obj.name)])
self.invoice_count = len(wrk_ordr_ids)
else:
work_orders = self.env['account.move'].search([('invoice_origin',
'=', work.name)])
self.invoice_count = len(work_orders)
self.is_invoiced = True
def _work_count(self):
"""Computing the work count based on the particular Laundry order
override the _work_count function"""
work = self.env['pos.order'].search(
[('name', '=', self.order_ref)])
if not work:
if self.id:
wrk_ordr_ids = self.env['washing.washing'].search([('laundry_obj.laundry_obj.id', '=', self.id)])
self.work_count = len(wrk_ordr_ids)
else:
self.work_count = False
else:
self.work_count = len(work.lines)
def action_view_laundry_works(self):
"""
works details of the LaundryOrder , the laundry work
smart button views are displayed here.
"""
result = super().action_view_laundry_works()
pos_orders = self.env['pos.order'].search(
[('name', '=', self.order_ref)])
pos_order_ids = pos_orders.mapped('id')
view_id = self.env.ref('laundry_management.washing_form_view').id
if pos_orders and len(pos_orders.lines) <= 1:
return {
'view_type': 'form',
'view_mode': 'form',
'res_model': 'washing.washing',
'view_id': view_id,
'type': 'ir.actions.act_window',
'name': _('Works'),
'res_id': pos_order_ids and pos_order_ids[0]
}
return result
def action_view_invoice(self):
"""
Invoice details of the LaundryOrder when opening the smart button
we can view the invoice details.
"""
result = super(LaundryOrder, self).action_view_invoice()
work = self.env['pos.order'].search(
[('name', '=', self.order_ref)])
invoice = self.env['account.move'].search(
[('invoice_origin', '=', work.name)])
invoice_ids = invoice.mapped('id')
view_id = self.env.ref('account.view_move_form').id
if invoice and len(invoice_ids) <= 1:
return {
'view_type': 'form',
'view_mode': 'form',
'res_model': 'account.move',
'view_id': view_id,
'type': 'ir.actions.act_window',
'name': _('Invoice'),
'res_id': invoice_ids and invoice_ids[0]
}
return result
class LaundryOrderLine(models.Model):
""" This class is inherited for model laundry_order_line.
It contains fields and the functions for the model
Methods:
_compute_price_tax(self):
Action perform to compute the subtotal amounts of the LaundryOrder line.
"""
_inherit = 'laundry.order.line'
# washing_type field is updated with the module Laundry Management
washing_type = fields.Many2one('washing.type', string='Washing Type',
required=False,
help='The many2one field for relating'
' to the washing type')
tax_ids = fields.Many2many('account.tax', string='Taxes',
help='The many2one field for relating to '
'the account tax')
price_tax = fields.Float(compute='_compute_price_tax', string='Total Tax',
help='The compute field for calculating price '
'tax')
@api.depends('qty', 'washing_type', 'extra_work', 'tax_ids')
def _compute_price_tax(self):
"""
Compute the amounts of the LaundryOrder line ie used to calculate subtotal amount with the quantity of product and the washing types.
"""
for line in self:
price = line.washing_type.amount
taxes = line.tax_ids.compute_all(price,
line.laundry_obj.currency_id,
line.qty,
product=line.product_id,
partner=line.laundry_obj.partner_shipping_id)
line.update({
'price_tax': taxes['total_included'] - taxes['total_excluded'],
})

33
laundry_management_pos/models/pos_config.py

@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Unnimaya C O (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
# GENERAL PUBLIC LICENSE (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo import fields, models
class PosConfig(models.Model):
""" This class is inherited for model pos_config.
It contains field for the model
"""
_inherit = 'pos.config'
orderline_washing_type = fields.Boolean(string='Washing Type',
help='Allow to add Washing type'
' for customer on OrderLines')

160
laundry_management_pos/models/pos_order.py

@ -0,0 +1,160 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
#
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Unnimaya C O (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
# GENERAL PUBLIC LICENSE (AGPL v3) along with this program.
# If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from datetime import datetime
from odoo import api, fields, models, _
from odoo.tools import float_repr
class PosOrderLine(models.Model):
""" This class is inherited for model pos_order_line.
It contains field and the functions for the model
Methods:
_export_for_ui(self, orderline):
Supering the export_for_ui function for generating the washing type in the order line for the model.
_order_line_fields(self, line, session_id):
Action perform to adding order-line details in the pos orders.
"""
_inherit = 'pos.order.line'
washing_type_id = fields.Many2one('washing.type',
String='Washing Type',
help='The many2one filed that related'
' to the washing type')
def _export_for_ui(self, orderline):
"""super the exporting function in the pos order line"""
result = super()._export_for_ui(orderline)
result['washing_type_id'] = \
orderline.washing_type.read(fields=['name'])[0]
return result
def _order_line_fields(self, line, session_id):
"""
Adding order-line details in the pos orders
"""
result = super()._order_line_fields(line, session_id)
vals = result[2]
washing_type_id = line[2].get('washingType_id')
new_values = {'washing_type_id': int(washing_type_id)}
vals.update(new_values)
return result
class PosOrder(models.Model):
""" This class is inherited for model pos_order.
It contains fields and the functions for the model
Methods:
create_from_ui(self, orders, draft=False):
Supering the create_from_ui that create and update Orders
from the frontend PoS application line for the model.
_prepare_invoice_lines(self):
Action perform to create Invoice for the corresponding POS order
"""
_inherit = "pos.order"
orderline_washing_type = fields.Boolean(string='Washing Type in orderline',
related='session_id.config_id.orderline_washing_type',
help='Related to the type in the pos session washing type id')
laundry_order = fields.Boolean('Laundry',
help='Field for calling the invoice'
' functionality')
@api.model
def create_from_ui(self, orders, draft=False):
""" Create and update Orders from the frontend PoS application.
"""
order = super(PosOrder, self).create_from_ui(orders=orders,
draft=draft)
if order:
order_id = order[0]['id']
values = self.env['pos.order'].browse(order_id)
values.write({
'laundry_order': True,
})
if values.laundry_order:
values.action_pos_order_invoice()
lines = []
for rec in values.lines:
vals = (0, 0, {
'product_id': rec.product_id.id,
'description': rec.full_product_name,
'qty': rec.qty,
'state': 'done',
'tax_ids': [(6, 0, rec.tax_ids.ids)],
'washing_type': rec.washing_type_id.id,
'amount': rec.price_subtotal_incl,
})
lines.append(vals)
laundry_order = self.env['laundry.order'].sudo().create({
'order_ref': values.name,
'pos_order_id': values.id,
'pos_reference': values.pos_reference,
'partner_id': values.partner_id.id,
'partner_invoice_id': values.partner_id.id,
'partner_shipping_id': values.partner_id.id,
'laundry_person': values.user_id.id,
'state': 'done',
'order_lines': lines,
})
for each in laundry_order:
for obj in each.order_lines:
self.env['washing.washing'].create(
{'name': obj.product_id.name + '-Washing',
'user_id': obj.washing_type.assigned_person.id,
'description': obj.description,
'laundry_obj': obj.id,
'state': 'done',
'washing_date': datetime.now().strftime(
'%Y-%m-%d %H:%M:%S')})
return order
def _prepare_invoice_lines(self):
"""
Invoice for the corresponding POS order
"""
invoice_lines = []
for line in self.lines:
invoice_lines.append((0, None, self._prepare_invoice_line(line)))
if line.order_id.pricelist_id.discount_policy == 'without_discount' \
and line.price_unit != line.product_id.lst_price:
invoice_lines.append((0, None, {
'name': _('Price discount from %s -> %s',
float_repr(line.product_id.lst_price,
self.currency_id.decimal_places),
float_repr(line.price_unit,
self.currency_id.decimal_places)),
'display_type': 'line_note',
}))
if line.customer_note:
invoice_lines.append((0, None, {
'name': line.customer_note,
'display_type': 'line_note',
}))
if line.washing_type_id:
invoice_lines.append((0, None, {
'name': line.washing_type_id.name,
'display_type': 'line_note',
}))
return invoice_lines

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 310 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 733 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 653 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 839 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 427 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 627 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 988 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 589 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 967 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
laundry_management_pos/static/description/assets/modules/l1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

BIN
laundry_management_pos/static/description/assets/modules/l2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

BIN
laundry_management_pos/static/description/assets/modules/l3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

BIN
laundry_management_pos/static/description/assets/modules/l4.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

BIN
laundry_management_pos/static/description/assets/modules/l5.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
laundry_management_pos/static/description/assets/modules/l6.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 367 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 KiB

BIN
laundry_management_pos/static/description/assets/screenshots/5.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

BIN
laundry_management_pos/static/description/assets/screenshots/6.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

BIN
laundry_management_pos/static/description/assets/screenshots/7.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 KiB

BIN
laundry_management_pos/static/description/assets/screenshots/8.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

BIN
laundry_management_pos/static/description/assets/screenshots/9.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 368 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 443 KiB

BIN
laundry_management_pos/static/description/banner.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
laundry_management_pos/static/description/icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

680
laundry_management_pos/static/description/index.html

@ -0,0 +1,680 @@
<div style="background-color: #714B67; min-height: 600px; width: 100%; padding: 15px; position: relative;">
<!-- TITLE BAR -->
<div class="d-flex align-items-center justify-content-between"
style="border-bottom: 1px solid #875A7B; padding: 15px; display: flex; justify-content: space-between; align-items: center;">
<img src="assets/misc/cybrosys-logo.png" width="42" height="42"
style="width: 42px; height: 42px;"/>
<div>
<div style="color: #7C7BAD; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
class="mr-2">
<i class="fa fa-check mr-1"></i>Community
</div>
<div style="color: #875A7B; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
class="mr-2">
<i class="fa fa-check mr-1"></i>Enterprise
</div>
<div style="color: #017E84; font-size: 14px; font-family: 'Montserrat', sans-serif; font-weight: bold; background-color: white; display: inline-block; padding: 3px 10px; border-radius: 50px;"
class="mr-2">
<i class="fa fa-check mr-1"></i>Odoo.sh
</div>
</div>
</div>
<!-- END OF TITLE BAR -->
<div class="container">
<div class="row">
<div class="col-sm-12 col-md-12 col-lg-12">
<!-- APP HERO -->
<h1 style="color: #FFFFFF; font-weight: bolder; font-size: 50px; text-align: center; margin-top: 50px;">
POS Laundry Management</h1>
<p style="color:#FFFFFF; padding: 8px 15px; text-align: center; font-size: 24px;">
A Module For Configuring the Point of Sale in Laundry
Management.</p>
<!-- END OF APP HERO -->
<img src="assets/screenshots/hero.gif"
style="width: 75%; height: auto; position: absolute; margin-left: auto; margin-right: auto; top: 45%; left: 12%; right: auto;"/>
</div>
</div>
</div>
</div>
<!-- NAVIGATION SECTION -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px; margin-top: 300px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/compass.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Explore This
Module</h2>
</div>
<div class="row my-4" style="font-family: 'Montserrat', sans-serif;">
<div class="col-sm-12 col-md-6 my-3">
<a href="#overview">
<div class="d-flex justify-content-between align-items-center"
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
<div>
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Overview</span>
<span
style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">Learn
more about this
module</span>
</div>
<img src="assets/misc/right-arrow.png" width="36" height="36"/>
</div>
</a>
</div>
<div class="col-sm-12 col-md-6 my-3">
<a href="#features">
<div class="d-flex justify-content-between align-items-center"
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
<div>
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Features</span>
<span
style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">View
features of this
module</span>
</div>
<img src="assets/misc/right-arrow.png" width="36" height="36"/>
</div>
</a>
</div>
<div class="col-sm-12 col-md-6 my-3">
<a href="#screenshots">
<div class="d-flex justify-content-between align-items-center"
style="background-color: #f5f5f5; padding: 30px; width: 100%;">
<div>
<span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Screenshots</span>
<span
style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33; display: block;">View
screenshots for this
module</span>
</div>
<img src="assets/misc/right-arrow.png" width="36" height="36"/>
</div>
</a>
</div>
</div>
<!-- END OF NAVIGATION SECTION -->
<!-- OVERVIEW SECTION -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="overview">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/pie-chart.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Overview
</h2>
</div>
<div class="row"
style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;">
<div class="col-sm-12 py-4">
In the POS Laundry Management App, It manages the Point of sale laundry
process with assigning works to workers.We can create Laundry orders
with the help of POS. Before installing this module, Install the <a
href="https://apps.odoo.com/apps/modules/16.0/laundry_management/">Laundry
management module </a> in the Odoo App Store.
</div>
</div>
<!-- END OF OVERVIEW SECTION -->
<!-- FEATURES SECTION -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="features">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/features.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Features
</h2>
</div>
<div class="row"
style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;">
<div class="col-sm-12 col-md-6">
<div class="d-flex align-items-center"
style="margin-top: 40px; margin-bottom: 40px">
<img src="assets/misc/check-box.png" class="mr-2"/>
<span
style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Display Laundry Service in the POS Screen.
</span>
</div>
<div class="d-flex align-items-center"
style="margin-top: 40px; margin-bottom: 40px">
<img src="assets/misc/check-box.png" class="mr-2"/>
<span
style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Display Washing Type in the Order lines and Order Receipts.
</span>
</div>
<div class="d-flex align-items-center"
style="margin-top: 40px; margin-bottom: 40px">
<img src="assets/misc/check-box.png" class="mr-2"/>
<span
style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Make Invoices Based on the Laundry Orders.
</span>
</div>
<div class="d-flex align-items-center"
style="margin-top: 40px; margin-bottom: 40px">
<img src="assets/misc/check-box.png" class="mr-2"/>
<span
style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> Create Product from the POS Screen.
</span>
</div>
</div>
</div>
<!-- END OF FEATURES SECTION -->
<!-- SCREENSHOTS SECTION -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;"
id="screenshots">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/pictures.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Screenshots
</h2>
</div>
<div class="row">
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Enable Washing Type in the POS Settings.</h3>
<img src="assets/screenshots/1.png" class="img-thumbnail"/>
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Laundry Service button in POS Screen</h3>
<img src="assets/screenshots/2.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Add Washing Type.</h3>
<p
style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
Click either Laundry Service button or the custom button in orderline to add the Washing Type.
</p>
<img src="assets/screenshots/3.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Washing Type added to the orderline.</h3>
<img src="assets/screenshots/4.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Washing Type in Receipt</h3>
<img src="assets/screenshots/5.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Washing Type in Invoice</h3>
<img src="assets/screenshots/6.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Create Product button in POS Screen</h3>
<p
style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
Click Create Product button to add new products.
</p>
<img src="assets/screenshots/7.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Product Popup.</h3>
<p
style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
Add product details and click Create Product button.
</p>
<img src="assets/screenshots/8.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Added Product.</h3>
<img src="assets/screenshots/9.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Laundry Order in Laundry Management module.</h3>
<p
style="font-weight: 400; font-family: 'Montserrat', sans-serif; font-size: 14px;">
Navigate to Laundry Order under Laundry Management menu in Laundry Management module and open the order created from POS.
</p>
<img src="assets/screenshots/10.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Works in Laundry Order.</h3>
<img src="assets/screenshots/11.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
List view of Works.</h3>
<img src="assets/screenshots/12.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Invoice in Laundry Order</h3>
<img src="assets/screenshots/13.png" class="img-thumbnail">
</div>
<div style="display: block; margin: 30px auto;">
<h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">
Invoice form view.</h3>
<img src="assets/screenshots/14.png" class="img-thumbnail">
</div>
</div>
<!-- END OF SCREENSHOTS SECTION -->
<!-- RELATED PRODUCTS -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/categories.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Related
Products
</h2>
</div>
<div class="row">
<div class="col-sm-12">
<div id="demo1" class="row carousel slide" data-ride="carousel">
<!-- The slideshow -->
<div class="carousel-inner" style="padding: 30px;">
<div class="carousel-item"
style="min-height: 198.656px;">
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/16.0/custom_receipts_for_pos/"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-radius: 0px;"
src="assets/modules/l1.png">
</div>
</a>
</div>
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/16.0/pos_kitchen_screen_odoo/"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-radius: 0px;"
src="assets/modules/l2.png">
</div>
</a>
</div>
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/16.0/pos_report_generator/"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-radius: 0px;"
src="assets/modules/l3.png">
</div>
</a>
</div>
</div>
<div class="carousel-item active"
style="min-height: 198.656px;">
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/16.0/dashboard_pos/"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-radius: 0px;"
src="assets/modules/l4.png">
</div>
</a>
</div>
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/16.0/pos_receipt_extend/"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-radius: 0px;"
src="assets/modules/l5.png">
</div>
</a>
</div>
<div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16"
style="float:left">
<a href="https://apps.odoo.com/apps/modules/16.0/low_stocks_product_alert/"
target="_blank">
<div style="border-radius:10px">
<img class="img img-responsive center-block"
style="border-radius: 0px;"
src="assets/modules/l6.png">
</div>
</a>
</div>
</div>
</div>
<!-- Left and right controls -->
<a class="carousel-control-prev" href="#demo1"
data-slide="prev"
style="width:35px; color:#000"> <span
class="carousel-control-prev-icon"><i
class="fa fa-chevron-left"
style="font-size:24px"></i></span>
</a> <a class="carousel-control-next" href="#demo1"
data-slide="next" style="width:35px; color:#000">
<span class="carousel-control-next-icon"><i
class="fa fa-chevron-right"
style="font-size:24px"></i></span>
</a>
</div>
</div>
</div>
<!-- END OF RELATED PRODUCTS -->
<!-- OUR SERVICES -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/star.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Our Services
</h2>
</div>
<div class="container my-5">
<div class="row">
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #1dd1a1 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/cogs.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Customization</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #ff6b6b !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/wrench.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Implementation</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #6462CD !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/lifebuoy.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Support</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #ffa801 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/user.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Hire
Odoo
Developer</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #54a0ff !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/puzzle.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Integration</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #6d7680 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/update.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Migration</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #786fa6 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/consultation.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Consultancy</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #f8a5c2 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/training.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Implementation</h6>
</div>
<div class="col-lg-4 d-flex flex-column justify-content-center align-items-center my-4">
<div class="d-flex justify-content-center align-items-center mx-3 my-3"
style="background-color: #e6be26 !important; border-radius: 15px !important; height: 80px; width: 80px;">
<img src="assets/icons/license.png" class="img-responsive"
height="48px" width="48px">
</div>
<h6 class="text-center"
style="font-family: Montserrat, 'sans-serif' !important; font-weight: bold;">
Odoo
Licensing Consultancy</h6>
</div>
</div>
</div>
<!--END OF OUR SERVICES -->
<!-- OUR INDUSTRIES -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/corporate.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Our
Industries
</h2>
</div>
<div class="container my-5">
<div class="row">
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/trading-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Trading
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Easily procure
and
sell your products</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/pos-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
POS
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Easy
configuration
and convivial experience</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/education-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Education
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
A platform for
educational management</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/manufacturing-black.png"
class="img-responsive mb-3" height="48px"
width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Manufacturing
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Plan, track and
schedule your operations</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/ecom-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
E-commerce &amp; Website
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Mobile
friendly,
awe-inspiring product pages</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/service-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Service Management
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Keep track of
services and invoice</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/restaurant-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Restaurant
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
Run your bar or
restaurant methodically</p>
</div>
</div>
<div class="col-lg-3">
<div class="my-4 d-flex flex-column justify-content-center"
style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;">
<img src="assets/icons/hotel-black.png"
class="img-responsive mb-3" height="48px" width="48px">
<h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;">
Hotel Management
</h5>
<p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;">
An
all-inclusive
hotel management application</p>
</div>
</div>
</div>
</div>
<!-- END OF OUR INDUSTRIES -->
<!-- SUPPORT -->
<div class="d-flex align-items-center"
style="border-bottom: 2px solid #714B67; padding: 15px 0px;">
<div class="d-flex justify-content-center align-items-center mr-2"
style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;">
<img src="assets/misc/customer-support.png"/>
</div>
<h2 class="mt-2"
style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;">
Support
</h2>
</div>
<div class="container mt-5">
<div class="row">
<div class="col-sm-12 col-md-6">
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;">
<div class="mr-4"
style="background-color: #714B67; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;">
<img src="assets/misc/support.png" height="48" width="48"
style="width: 42px; height: 42px;"/>
</div>
<div>
<h4>Need Help?</h4>
<p style="line-height: 100%;">Got questions or need help?
Get in touch.</p>
<a href="mailto:odoo@cybrosys.com">
<p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;">
odoo@cybrosys.com</p>
</a>
</div>
</div>
</div>
<div class="col-sm-12 col-md-6">
<div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;">
<div class="mr-4"
style="background-color: #2AC44D; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;">
<img src="assets/misc/whatsapp.png" height="52" width="52"
style="width: 52px; height: 52px;"/>
</div>
<div>
<h4>WhatsApp</h4>
<p style="line-height: 100%;">Say hi to us on WhatsApp!</p>
<a href="https://api.whatsapp.com/send?phone=918606827707">
<p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;">
+91 86068
27707</p>
</a>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12 my-5 d-flex justify-content-center align-items-center">
<img src="assets/misc/logo.png" width="144" height="31"
style="width:144px; height: 31px; margin-top: 40px;"/>
</div>
</div>
</div>
<!-- END OF SUPPORT -->

109
laundry_management_pos/static/src/css/pos.css

@ -0,0 +1,109 @@
.pos .numpad button {
color: #2F4F4F;
background: #D3D6D6;
border-color: #2F4F4F;
}
.pos button.button.set-customer{
padding-left: 0px;
padding-right: 0px;
color: black;
}
.pos .actionpad .button.set-customer.decentered{
padding-left: 0px;
padding-right: 0px;
color: black;
}
.pos .button-control {
background: #A9A9A9;
color: black;
border: none;
border-radius: 0;
border-top: 1px solid;
border-left: 1px solid;
border-bottom: 1px solid;
border-right: 1px solid;
border-color: white;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
flex-grow: 1;
height: 60px;
}
.pos .order .orderline .pos_product_image{
float:left;
margin:auto;
}
.pos .order {
padding-top: 0px !important;
}
.pos .order .orderline .product-name {
padding-top: 5px;
}
.pos .order .orderline .info-list {
margin-left: 15px;
padding-bottom: 10px;
font-weight: bold;
font-family: Verdana;
}
.pos .order .orderline .product-name{
padding:0;
display:inline-block;
font-weight: bold;
font-family: Verdana;
width:80%;
overflow:hidden;
text-overflow: ellipsis;
}
.pos .actionpad .button.pay {
height: calc(var(--btn-height-size) * 3);
color: black;
}
.pos .order .orderline .price{
padding:0;
font-weight: bold;
font-family: Verdana;
float:right;
}
.salesperson-scroll{
height: 270px;
overflow: auto;
}
.salesperson {
border-collapse: collapse;
width: 100%;
}
.salesperson td{
text-align: left;
border: 1px solid #ddd;
padding: 8px;
}
.salesperson tr:nth-child(even){background-color: #f2f2f2;}
.salesperson tr:hover {background-color: #ddd;}
.orderline-salesperson{
padding:5;
float:right;
}
.orderline-laundry{
padding:5;
float:left;
}
.pos .products-widget .products-widget-control{
display: none;
}
.pos button, .pos a.button {
display: inline-block;
cursor: pointer;
padding: 4px 10px;
font-size: 11px;
border: 1px solid #cacaca;
background: #A9A9A9;
border-radius: 3px;
}
.button-control:hover {
background: #efefef;
}

81
laundry_management_pos/static/src/js/button/product_create_button.js

@ -0,0 +1,81 @@
odoo.define('laundry_management_pos.product_create_button', function(require) {
'use strict';
const PosComponent = require('point_of_sale.PosComponent');
const ProductScreen = require('point_of_sale.ProductScreen');
const { useListener } = require("@web/core/utils/hooks");
const Registries = require('point_of_sale.Registries');
const ajax = require('web.ajax');
const { Gui } = require('point_of_sale.Gui');
// Extending the PosComponent that used to create a button in the POS View
class ProductCreateButton extends PosComponent {
async setup() {
super.setup();
await this.loadProductCategory();
}
async loadProductCategory() {
// Method for loading product categories
const product_categories = await this.rpc({
model: 'product.category',
method: 'search_read',
fields: ['name', 'complete_name'],
});
this.env.pos.product_categories = product_categories;
}
async _onClickCreateProduct(e) {
//Method for opening the popup
var self = this;
const core = require('web.core');
const _t = core._t;
const { confirmed, payload } = await Gui.showPopup("ProductCreatePopup", {
title: _t("POS Product Creation"),
confirmText: _t("Exit"),
});
if (confirmed) {
var product_category = payload[0];
var product_name = payload[1];
var product_reference = payload[2];
var product_price = payload[3];
var unit_measure = payload[4];
var product_categories = payload[5];
var pos_categories = payload[6];
if (!product_name){
return this.showPopup('ErrorPopup', {
title: _('Product Name is Required'),
});
}
if (!unit_measure){
return this.showPopup('ErrorPopup', {
title: _('A Unit Of Measure is Required'),
});
}
if (!product_categories){
return this.showPopup('ErrorPopup', {
title: _('Product Category is Required'),
});
}
ajax.jsonRpc('/create_product', 'call', {
'category': product_category,
'name': product_name,
'price': product_price,
'product_reference': product_reference,
'unit_measure': unit_measure,
'product_categories': product_categories,
'pos_categories': pos_categories
}).then(function(response) {});
}
}
}
// Create a new Button that used to Display the Product Information
ProductCreateButton.template = 'ProductCreateButton';
ProductScreen.addControlButton({
component: ProductCreateButton,
condition: function() {
return true;
},
position: ['before', 'SetPricelistButton'],
});
Registries.Component.add(ProductCreateButton);
return ProductCreateButton;
});

46
laundry_management_pos/static/src/js/button/washing_type_button.js

@ -0,0 +1,46 @@
odoo.define('laundry_management_pos.Custom', function (require) {
'use strict';
const { Gui } = require('point_of_sale.Gui');
const PosComponent = require('point_of_sale.PosComponent');
const Registries = require('point_of_sale.Registries');
const { useListener } = require("@web/core/utils/hooks");
const models = require('point_of_sale.models');
// Extending the PosComponent that used to create a button in the POS View
class CustomDemoButtons extends PosComponent {
async setup() {
super.setup();
await this.loadDataFromWashingTypeModel();
}
async _onClickLaundry(e) {
//Method corresponds to Laundry service button click
const core = require('web.core');
const _t = core._t;
Gui.showPopup("LaundryServiceTypePopup", {
title: _t("Laundry Service"),
confirmText: _t("Exit"),
service: this.env.pos.washing_type,
pos: this.env.pos,
});
}
async loadDataFromWashingTypeModel() {
// Method for loading washing types
const washingTypeData = await this.rpc({
model: 'washing.type',
method: 'search_read',
fields: ['name', 'assigned_person', 'amount'],
});
this.env.pos.washing_type = washingTypeData;
}
}
CustomDemoButtons.template = 'CustomDemoButtons';
const ProductScreen = Registries.Component.get('ProductScreen');
ProductScreen.addControlButton({
component: CustomDemoButtons,
condition: function () {
return this.env.pos.config.orderline_washing_type;
},
});
Registries.Component.add(CustomDemoButtons);
return CustomDemoButtons;
});

67
laundry_management_pos/static/src/js/models.js

@ -0,0 +1,67 @@
/** @odoo-module */
import { Orderline } from 'point_of_sale.models';
import Registries from 'point_of_sale.Registries';
const PosSaleOrderline = (Orderline) => class PosSaleOrderline extends Orderline {
constructor() {
super(...arguments);
this.washingType = this.washingType || arguments[1].washingType;
this.washingType_id = this.washingType_id || 0.0;
this.washingType_price = this.washingType_id || 0.0;
}
// Function to set the service type of the Washing
set_washingType(service) {
this.washingType = service.name;
this.washingType_id = service.id;
this.washingType_price = service.amount;
this.price = service.amount;
}
// Function to get the service type of the Washing
get_washingType() {
return this.washingType;
}
// Used to merge the services with Order-line
can_be_merged_with(orderline) {
if (orderline.get_washingType() !== this.get_washingType()) {
return false;
} else {
return super.can_be_merged_with(orderline);
}
}
// Clone the service with order-lines
clone() {
var orderline = super.clone();
orderline.washingType = this.washingType;
orderline.washingType_id = this.washingType_id;
orderline.washingType_price = this.washingType_price;
if(this.washingType_price){
orderline.price = this.washingType_price;
}
return orderline;
}
//Add washing type and price to orderline
export_as_JSON() {
var json = super.export_as_JSON();
json.washingType = this.washingType;
json.washingType_id = this.washingType_id;
json.washingType_price = this.washingType_price;
if (this.washingType_price){
json.price=this.washingType_price;
}
return json;
}
//Set washing type and price to orderline
init_from_JSON(json) {
super.init_from_JSON(json);
this.washingType = json.washingType;
this.washingType_id = json.washingType_id;
this.washingType_price = json.washingType_price;
}
};
Registries.Model.extend(Orderline, PosSaleOrderline);
export default PosSaleOrderline;

22
laundry_management_pos/static/src/js/order_line.js

@ -0,0 +1,22 @@
/** @odoo-module */
import { Orderline } from 'point_of_sale.models';
import Registries from 'point_of_sale.Registries';
const PosResOrderline = Orderline => class extends Orderline {
click() {
this.showPopup("LaundryServiceTypePopup", {
title: this.env._t("Laundry Service"),
service: this.env.pos.washing_type,
pos: this.env.pos,
orderline: this.props.line,
});
}
remove_laundry() {
//Method for removing laundry
this.props.line.washingType = '';
this.props.line.washingType_id = 0.0;
}
};
// Extend Orderline with PosResOrderline
Registries.Component.extend('Orderline', PosResOrderline);

18
laundry_management_pos/static/src/js/pos_receipt.js

@ -0,0 +1,18 @@
odoo.define('laundry_management_pos.receipt', function(require){
"use strict";
const { Orderline } = require('point_of_sale.models');
const Registries = require('point_of_sale.Registries');
var _super_orderline = Orderline.prototype;
// Extends the order-line used to add the Washing Details in the order receipts
const PosSaleOrderline = (Orderline) => class PosSaleOrderline extends Orderline {
// Used to add the Washing Details in the order receipt
export_for_printing(){
var line = _super_orderline.export_for_printing.apply(this, arguments);
line.service_type = this.get_washingType();
return line;
}
}
Registries.Model.extend(Orderline, PosSaleOrderline);
return PosSaleOrderline;
});

17
laundry_management_pos/static/src/js/product_img.js

@ -0,0 +1,17 @@
odoo.define('laundry_management_pos.pos_order_line', function(require) {
"use strict";
const { Orderline } = require('point_of_sale.models');
const Registries = require('point_of_sale.Registries');
// Extend the order lines for getting the product images
const PosSaleOrderline = (Orderline) => class PosSaleOrderline extends Orderline {
// Product images uploading to the particular field
get_product_image(){
const product = this.product;
return `/web/image?model=product.product&field=image_128&id=${product.id}&write_date=${product.write_date}&unique=1`;
}
};
Registries.Model.extend(Orderline, PosSaleOrderline);
return PosSaleOrderline;
});

50
laundry_management_pos/static/src/js/screen/product_create_popup.js

@ -0,0 +1,50 @@
/** @odoo-module */
import AbstractAwaitablePopup from 'point_of_sale.AbstractAwaitablePopup';
import Registries from 'point_of_sale.Registries';
import PosComponent from 'point_of_sale.PosComponent';
import { useListener } from '@web/core/utils/hooks';
const { useState, useRef } = owl;
// Extending the AbstractAwaitablePopup that used to add a new popup
class ProductCreatePopup extends AbstractAwaitablePopup {
setup() {
super.setup();
this.state = useState({
typeValue: this.props.startingValue,
productValue: this.props.startingValue,
priceValue: this.props.priceValue,
productRef: this.props.startingValue
});
}
getPayload() {
var selected_vals = [];
var category = this.state.typeValue;
var product = this.state.productValue;
var product_reference = this.state.productRef;
var price = this.state.priceValue;
var unit = this.state.unitValue;
var product_category = this.state.categoryValue;
selected_vals.push(category);
selected_vals.push(product);
selected_vals.push(product_reference);
selected_vals.push(price);
selected_vals.push(unit);
selected_vals.push(product_category);
return selected_vals
}
}
// Create Service popup
ProductCreatePopup.template = 'ProductCreatePopup';
ProductCreatePopup.defaultProps = {
confirmText: 'Ok',
cancelText: 'Cancel',
array: [],
title: 'Create ?',
body: '',
startingValue: '',
priceValue: 1,
list: [],
};
Registries.Component.add(ProductCreatePopup);
export default ProductCreatePopup;

43
laundry_management_pos/static/src/js/screen/product_screen.js

@ -0,0 +1,43 @@
/** @odoo-module **/
import ProductScreen from 'point_of_sale.ProductScreen';
import Registries from 'point_of_sale.Registries';
export const PoSSaleBeProductScreen = (ProductScreen) =>
class extends ProductScreen {
async onClickPartner() {
// Override to check whether the laundry type already is added
const currentPartner = this.currentOrder.get_partner();
if (currentPartner && this.currentOrder.getHasRefundLines()) {
this.showPopup('ErrorPopup', {
title: this.env._t("Can't change customer"),
body: _.str.sprintf(
this.env._t(
"This order already has refund lines for %s. We can't change the customer associated to it. Create a new order for the new customer."
),
currentPartner.name
),
});
return;
}
const { confirmed, payload: newPartner } = await this.showTempScreen(
'PartnerListScreen',
{ partner: currentPartner }
);
if (confirmed) {
this.currentOrder.set_partner(newPartner);
var washing=0
for (let line of this.currentOrder.orderlines) {
if (line.get_washingType())
{
washing=1
}
}
if (washing==0)
{
this.currentOrder.updatePricelist(newPartner);
}
}
}
};
Registries.Component.extend(ProductScreen, PoSSaleBeProductScreen);

34
laundry_management_pos/static/src/js/screen/washing_type_popup.js

@ -0,0 +1,34 @@
/** @odoo-module */
import AbstractAwaitablePopup from 'point_of_sale.AbstractAwaitablePopup';
import Registries from 'point_of_sale.Registries';
import PosComponent from 'point_of_sale.PosComponent';
import { useListener } from '@web/core/utils/hooks';
// Extending the AbstractAwaitablePopup that used to add a new popup
class LaundryServiceTypePopup extends AbstractAwaitablePopup {
setup() {
super.setup();
}
// Create a new Popup instance
laundryPopup(event) {
var order = this.props.pos.get_order();
if (order.selected_orderline && !this.props.orderline) {
order.selected_orderline.set_washingType(this.env.pos.washing_type.find(obj => obj['id'] === parseInt(event.currentTarget.dataset['id'])));
} else if (order.selected_orderline && this.props.orderline) {
this.props.orderline.set_washingType(this.env.pos.washing_type.find(obj => obj['id'] === parseInt(event.currentTarget.dataset['id'])));
}
this.env.posbus.trigger('close-popup', {
popupId: this.props.id,
response: { confirmed: false, payload: null },
});
}
}
// Create Service popup
LaundryServiceTypePopup.template = 'LaundryServiceTypePopup';
LaundryServiceTypePopup.defaultProps = {
confirmText: 'Ok',
cancelText: 'Cancel',
};
Registries.Component.add(LaundryServiceTypePopup);
export default LaundryServiceTypePopup;

11
laundry_management_pos/static/src/xml/button/product_create_button.xml

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<!-- Template for the Product create Button-->
<t t-name="ProductCreateButton" owl="1">
<div class="control-button" t-on-click="_onClickCreateProduct">
<i class="fa fa-plus" role="img" aria-label="Create Product" title="Create Product"/>
<span/>
<span>Create Product</span>
</div>
</t>
</templates>

25
laundry_management_pos/static/src/xml/button/washing_type_button.xml

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<!-- Inherits the order-lines for adding the laundry details into the lines-->
<t t-name="Orderline" t-inherit="point_of_sale.Orderline" t-inherit-mode="extension" owl="1">
<xpath expr="//ul[hasclass('info-list')]/t[1]/li" position="inside">
<span class="orderline-laundry" t-if="env.pos.config.orderline_washing_type">
<i t-on-click="click" class="oe_link_icon fa fa-user oe_icon line-salesperson-icon oe_green"
t-if="props.line.get_washingType()" role="img"/>
<i t-on-click="click" class="oe_link_icon fa fa-user-plus oe_icon line-salesperson-icon oe_red"
t-if="!props.line.get_washingType()" role="img"/>
<t t-esc="props.line.get_washingType()"/>
<i t-on-click="remove_laundry" class="oe_link_icon fa fa-remove oe_icon oe_red"
t-if="props.line.get_washingType()" role="img"/>
</span>
</xpath>
</t>
<!-- Laundry Service Button-->
<t t-name="CustomDemoButtons" owl="1">
<div class="control-button" t-on-click="_onClickLaundry">
<i class="fa fa-shopping-basket" role="img" aria-label="Laundry Service" title="Laundry Service"/>
<span/>
<span>Laundry Service</span>
</div>
</t>
</templates>

57
laundry_management_pos/static/src/xml/pos_receipt.xml

@ -0,0 +1,57 @@
<templates id="template" xml:space="preserve">
<!-- Inherits the order lines Receipt for adding the service details-->
<t t-name="OrderLinesReceipt" t-inherit="point_of_sale.OrderLinesReceipt"
t-inherit-mode="extension" owl="1">
<xpath expr="//div[hasclass('responsive-price')]" position="before">
<t t-if="line.service_type">
<div>
<h3><i><b><t t-esc="line.service_type"/></b></i></h3>
</div>
</t>
</xpath>
<xpath expr="//t[@t-foreach='receipt.orderlines']" position="inside">
<t t-if="line.person">
<br/>
<span>Assigned person:</span>
<br/>
<t t-esc="line.person"/>
<br/>
</t>
</xpath>
</t>
<!-- Inheirited the Order Receipt for dding laundry details-->
<t t-name="OrderReceipt" t-inherit="point_of_sale.OrderReceipt"
t-inherit-mode="extension" owl="1">
<xpath expr="//t[@t-if='receipt.company.logo']" position="replace"/>
<xpath expr="//t[@t-if='receipt.company.contact_address']" position="replace"/>
<xpath expr="//t[@t-if='receipt.company.phone']" position="replace"/>
<xpath expr="//t[@t-if='receipt.company.vat']" position="replace"/>
<xpath expr="//t[@t-if='receipt.company.email']" position="replace">
<span>
<h2 class="pos-receipt-center-align">Laundry Service</h2>
</span>
</xpath>
<xpath expr="//t[@t-if='receipt.company.website']" position="replace">
<t t-esc="receipt.company.name"/>
</xpath>
<xpath expr="//t[@t-if='receipt.cashier']" position="replace">
<div class="cashier">
<div>--------------------------------</div>
<div>Laundry Person <t t-esc="receipt.cashier"/></div>
</div>
</xpath>
<xpath expr="//div[hasclass('orderlines')]" position="before">
<div>
<div>
<t t-esc="receipt.partner.name"/>
<br/>
<t t-esc="receipt.partner.street"/>
<br/>
<t t-esc="receipt.partner.address"/>
<br/>
</div>
</div>
<br/>
</xpath>
</t>
</templates>

11
laundry_management_pos/static/src/xml/product_img.xml

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<template id="template" xml:space="preserve">
<!-- Inherited to add the product image to orderline-->
<t t-name="Productimage" t-inherit="point_of_sale.Orderline" t-inherit-mode="extension" owl="1">
<xpath expr="//span[hasclass('product-name')]" position="before">
<span class="product-img">
<img t-att-src="props.line.get_product_image()" style="padding: 5px; height: 50px; width:40px;"/>
</span>
</xpath>
</t>
</template>

97
laundry_management_pos/static/src/xml/screen/product_create_popup.xml

@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<!-- Template for Product creation popup-->
<t t-name="ProductCreatePopup" owl="1">
<div role="dialog" class="modal-dialog">
<Draggable>
<div class="popup popup-text">
<header class="title">
<div class="row">
<t t-esc="props.title"/>
</div>
</header>
<main class="body product_configurator_attributes col-lg-4 col-md-6 col-sm-12">
<div class="row">
<div>
<span>Product Name</span>
</div>
<div style="margin-top: 10px;">
<input class="name" type="text" t-model="state.productValue" required="1"/>
</div>
</div>
<br/>
<div class="row">
<div>
<span>Internal Reference</span>
</div>
<div style="margin-top: 10px;">
<input class="name" type="text" t-model="state.productRef" required=""/>
</div>
</div>
<br/>
<div class="row">
<div>
<span>Product Price</span>
</div>
<div style="margin-top: 10px;">
<input class="price" type="text" t-model="state.priceValue" required=""/>
</div>
</div>
<br/>
<div class="row">
<div>
<span>Product Type</span>
</div>
<div style="margin-top: 10px;">
<select class="type" style="width: 233px;height:46px" t-model="state.typeValue" required="">
<option>Consumable</option>
<option>Storable</option>
<option>Service</option>
</select>
</div>
</div>
<br/>
<div class="row">
<div>
<span>Unit Of Measure</span>
</div>
<div style="margin-top: 10px;">
<select class="type" style="width: 233px;height:46px" t-model="state.unitValue" required="">
<option/>
<t t-foreach="env.pos.units" t-as="item" t-key="item.name">
<option t-att-value="item.id" t-esc="item.name"/>
</t>
</select>
</div>
</div>
<br/>
<div class="row">
<div>
<span>Product Category</span>
</div>
<div style="margin-top: 10px;">
<select class="type" style="width: 233px;height:46px" t-model="state.categoryValue" required="">
<option/>
<t t-foreach="env.pos.product_categories" t-as="item" t-key="item.id">
<option t-att-value="item.id" t-esc="item.name"/>
</t>
</select>
</div>
</div>
<br/>
</main>
<footer class="footer">
<div style="color: white;background: #6EC89B;border-color: transparent;" class="button confirm"
t-on-click="confirm">
Create Product
</div>
<div style="color:white;background:#D25B5B;border-color: transparent;" class="button cancel"
t-on-click="cancel">
Cancel
</div>
</footer>
</div>
</Draggable>
</div>
</t>
</templates>

41
laundry_management_pos/static/src/xml/screen/washing_type_popup.xml

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<!-- Create the template for the Washing type popup-->
<t t-name="LaundryServiceTypePopup" owl="1">
<div role="dialog" class="modal-dialog">
<div class="popup popup-text">
<header class="title"><t t-esc="props.title || '' " /></header>
<t t-if="props.service">
<div class='salesperson-scroll'>
<table class='salesperson'>
<tbody>
<tr t-on-click="laundryPopup"
class="salesperson-selected"
t-foreach="props.service"
t-as="service"
t-key="service['name']"
t-att-data-value="service['name']"
t-att-data-id="service['id']">
<td>
<div>
<span t-esc="service['name']"/>
</div>
<div>
<span t-esc="service['amount']"/>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</t>
<footer class="footer">
<div class="button cancel" t-on-click="cancel">
Cancel
</div>
</footer>
</div>
</div>
</t>
</templates>

31
laundry_management_pos/views/laundry_order_views.xml

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Inherits the laundry order form view also the id inherits from
the dependent module Laundry_management-->
<record id="laundry_order_form_view" model="ir.ui.view">
<field name="name">laundry.order.view.form.inherit.laundry.management.pos</field>
<field name="inherit_id" ref="laundry_management.laundry_order_form_view"/>
<field name="model">laundry.order</field>
<field name="arch" type="xml">
<xpath expr="//field[@name='order_date']" position="before">
<field name="pos_reference"
attrs="{'invisible':[('is_invoiced', '=', False)]}"/>
</xpath>
<xpath expr="//field[@name='pos_reference']" position="before">
<field name="is_invoiced" invisible="1"/>
</xpath>
<xpath expr="//field[@name='order_lines']/tree/field[@name='extra_work']"
position="after">
<field name="tax_ids" widget="many2many_tags"/>
</xpath>
<xpath expr="//button[@name='create_invoice']"
position="attributes">
<attribute name="attrs">{'invisible': ['|', ('is_invoiced', '=', True), ('state', 'in', ('draft', 'order', 'process'))]}</attribute>
</xpath>
<xpath expr="//field[@name='partner_id']" position="before">
<field name="pos_order_id"
attrs="{'invisible':[('is_invoiced', '=', False)]}"/>
</xpath>
</field>
</record>
</odoo>

26
laundry_management_pos/views/pos_config_views.xml

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<!-- Inherited to add the Washing Type to pos config-->
<record id="pos_config_view_form" model="ir.ui.view">
<field name="name">pos.config.view.form.inherit.laundry.management.pos</field>
<field name="model">pos.config</field>
<field name="inherit_id" ref="point_of_sale.pos_config_view_form"/>
<field name="arch" type="xml">
<div id="other_devices" position="after">
<div class="col-12 col-lg-6 o_setting_box"
id="orderline_washing_type">
<div class="o_setting_left_pane">
<field name="orderline_washing_type"/>
</div>
<div class="o_setting_right_pane">
<label for="orderline_washing_type" string="Washing Type"/>
<div class="text-muted mb16">
Add Types on order lines to be printed on
receipt and invoice.
</div>
</div>
</div>
</div>
</field>
</record>
</odoo>

25
laundry_management_pos/views/pos_order_views.xml

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Inherits the pos order form view -->
<record id="view_pos_pos_form" model="ir.ui.view">
<field name="name">pos.order.view.form.inherit.laundry.management.pos</field>
<field name="inherit_id" ref="point_of_sale.view_pos_pos_form"/>
<field name="model">pos.order</field>
<field name="arch" type="xml">
<xpath expr="//field[@name='fiscal_position_id']"
position="before">
<field name="laundry_order" invisible="1"/>
</xpath>
<xpath expr="//field[@name='fiscal_position_id']"
position="after">
<field name="orderline_washing_type" invisible="1"/>
</xpath>
<xpath expr="//field[@name='lines']/tree/field[@name='price_subtotal_incl']"
position="after">
<field name="washing_type_id"
attrs="{'column_invisible':
[('parent.orderline_washing_type','=', False)]}"/>
</xpath>
</field>
</record>
</odoo>
Loading…
Cancel
Save