| @ -0,0 +1,50 @@ | |||
| .. image:: https://img.shields.io/badge/license-AGPL--3-blue.svg | |||
|     :target: https://www.gnu.org/licenses/agpl-3.0-standalone.html | |||
|     :alt: License: AGPL-3 | |||
| 
 | |||
| One Page Checkout | |||
| ================= | |||
| * Condensed ecommerce checkout into a single page. | |||
| 
 | |||
| Installation | |||
| ============ | |||
| - https://www.odoo.com/documentation/15.0/administration/install.html | |||
| - Install our custom addon | |||
| 
 | |||
| License | |||
| ------- | |||
| 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: | |||
|             (V15) Jumana Haseen, | |||
|             (V16) Yassir Irfan, | |||
| 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>`__ | |||
| @ -0,0 +1,22 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################# | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | |||
| #    Author: Jumana Haseen (<https://www.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 <https://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################# | |||
| from . import controllers | |||
| @ -0,0 +1,60 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################# | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | |||
| #    Author: Jumana Haseen (<https://www.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 <https://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################# | |||
| { | |||
|     'name': 'One Page Checkout', | |||
|     'version': '15.0.1.0.0', | |||
|     'category': 'eCommerce', | |||
|     'summary': """ | |||
|         Simplifies ecommerce checkout by condensing it into a single, | |||
|         user-friendly page. | |||
|         """, | |||
|     'description': """ | |||
|         Condenses the entire ecommerce checkout process into a single, | |||
|         user-friendly page, simplifying the steps and enhancing the user | |||
|         experience. | |||
|         """, | |||
|     'author': 'Cybrosys Techno Solutions', | |||
|     'company': 'Cybrosys Techno Solutions', | |||
|     'maintainer': 'Cybrosys Techno Solutions', | |||
|     'website': 'https://www.cybrosys.com', | |||
|     'images': ['static/description/banner.jpg'], | |||
|     'depends': ['website', 'website_sale'], | |||
|     'data': [ | |||
|         'views/address_column_templates.xml', | |||
|         'views/address_form_templates.xml', | |||
|         'views/extra_info_templates.xml', | |||
|         'views/payment_templates.xml', | |||
|         'views/website_sale_templates.xml', | |||
|     ], | |||
|     'assets': { | |||
|         'web.assets_frontend': [ | |||
|             'one_page_checkout/static/src/css/style.css', | |||
|             'one_page_checkout/static/src/js/website_sale.js', | |||
|             'one_page_checkout/static/src/js/checkout_form.js', | |||
|             'one_page_checkout/static/src/js/website_sale_delivery.js', | |||
|         ], | |||
|     }, | |||
|     'license': 'AGPL-3', | |||
|     'installable': True, | |||
|     'auto_install': False, | |||
|     'application': False, | |||
| } | |||
| @ -0,0 +1,23 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################# | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | |||
| #    Author: Jumana Haseen (<https://www.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 <https://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################# | |||
| from . import website_form | |||
| from . import website_sale | |||
| @ -0,0 +1,55 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################# | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | |||
| #    Author: Jumana Haseen (<https://www.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 <https://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################# | |||
| from odoo import http | |||
| from odoo.http import request | |||
| from odoo.addons.website.controllers.form import WebsiteForm | |||
| 
 | |||
| 
 | |||
| class WebsiteSaleForm(WebsiteForm): | |||
|     """ | |||
|     Class representing a form for ecommerce checkout. | |||
|     Inherits: | |||
|     WebsiteForm: The base class for website forms, providing common | |||
|     functionalities. | |||
|     Usage: | |||
|     1. Create an instance of `WebsiteSaleForm` and customize it as needed. | |||
|     2. Use the instance to handle the checking out in your shop. | |||
|     """ | |||
|     @http.route('/website/form/shop.sale.order', type='http', auth="public", | |||
|                 methods=['POST'], website=True) | |||
|     def website_form_sale_order(self, **kwargs): | |||
|         """ | |||
|         This function is called when the user submits the checkout form for a | |||
|         sales order on the website. It first calls the parent method `website_ | |||
|         form_sale_order` to handle the submission of the form and create the | |||
|         sales order. Then, it retrieves the created sales order from the | |||
|         website session and stores its ID in the user's session. Finally, | |||
|         it redirects the user to the payment status page. | |||
| 
 | |||
|         :param kwargs: Optional keyword arguments. | |||
|         :return: A redirect to the payment status page. | |||
|         """ | |||
|         super(WebsiteSaleForm, self).website_form_saleorder(**kwargs) | |||
|         order = request.website.sale_get_order() | |||
|         if request.session.get('sale_last_order_id') is None and order: | |||
|             request.session['sale_last_order_id'] = order.id | |||
|         return request.redirect('/payment/status') | |||
| @ -0,0 +1,136 @@ | |||
| # -*- coding: utf-8 -*- | |||
| ############################################################################# | |||
| # | |||
| #    Cybrosys Technologies Pvt. Ltd. | |||
| # | |||
| #    Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | |||
| #    Author: Jumana Haseen (<https://www.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 <https://www.gnu.org/licenses/>. | |||
| # | |||
| ############################################################################# | |||
| from odoo import http | |||
| from odoo.http import request | |||
| from odoo.addons.website_sale.controllers.main import WebsiteSale | |||
| 
 | |||
| 
 | |||
| class WebsiteSaleEcom(WebsiteSale): | |||
|     """ | |||
|     Customized version of the website sale controller for e-commerce. | |||
|     This class is a subclass of `WebsiteSale` and provides additional | |||
|     customizations and overrides specific to e-commerce functionality on the | |||
|     website. It extends the base functionality of `WebsiteSale` to cater to the | |||
|     specific needs of an e-commerce website. | |||
| 
 | |||
|     Inherits: | |||
|         WebsiteSale: The base class for the website sale controller. | |||
|     Usage: | |||
|     1. Create an instance of `WebsiteSaleEcom` and customize it as needed. | |||
|     2. Use the instance to handle e-commerce functionality on your website. | |||
|     """ | |||
| 
 | |||
|     def _get_address_values(self, **post): | |||
|         """ | |||
|         This method overrides the default `address()` method of the | |||
|         `WebsiteSale` class to get additional context values related to the | |||
|         customer's address. | |||
| 
 | |||
|         :param post: A dictionary containing the form data submitted by the | |||
|         user. | |||
|         :type post: dict | |||
| 
 | |||
|         :return: A dictionary containing the updated q-context values related | |||
|         to the customer's address. | |||
|         :rtype: dict | |||
|         """ | |||
|         result = super(WebsiteSaleEcom, self).address(**post).qcontext | |||
|         return result | |||
| 
 | |||
|     @http.route(['/shop/address'], type='http', methods=['GET', 'POST'], | |||
|                 auth="public", website=True, sitemap=False) | |||
|     def address(self, **kw): | |||
|         """ | |||
|         Renders the checkout address page for the current website sale order. | |||
|         If the request is a POST, updates the current order's delivery and | |||
|         invoice addresses with the provided data. | |||
| 
 | |||
|         If the current user is authenticated and the order's partner matches | |||
|         the authenticated user's partner, redirects to the payment page. | |||
| 
 | |||
|         :return: An HTTP response with the rendered checkout address page or a | |||
|         redirection to the login or payment page. | |||
|         :rtype: werkzeug.wrappers.Response | |||
|         """ | |||
| 
 | |||
|         res = super(WebsiteSaleEcom, self).address(**kw) | |||
|         order = request.website.sale_get_order() | |||
|         render_values = self._get_shop_payment_values(order, **kw) | |||
|         render_values.update({ | |||
|             'is_public_user': request.website.is_public_user(), | |||
|             'is_address': False}) | |||
|         request.render("website_sale.address", render_values) | |||
|         order = res.qcontext.get('website_sale_order') | |||
|         if order: | |||
|             user = request.website.user_id.sudo() | |||
|             if order.partner_id.id == user.partner_id.id: | |||
|                 return request.redirect('/shop/payment') | |||
|             else: | |||
|                 return res | |||
|         return res | |||
| 
 | |||
|     @http.route(['/shop/extra_info'], type='http', auth="public", website=True, | |||
|                 sitemap=False) | |||
|     def extra_info(self): | |||
|         """ | |||
|         Overwrites the existing extra_info function. | |||
|         Redirects the current request to the checkout payment page. | |||
| 
 | |||
|         :return: An HTTP response redirecting to the checkout payment page. | |||
|         :rtype: werkzeug.wrappers.Response | |||
|         """ | |||
|         return request.redirect('/shop/payment') | |||
| 
 | |||
|     @http.route('/shop/payment', type='http', auth='public', website=True, | |||
|                 sitemap=False) | |||
|     def shop_payment(self, **post): | |||
|         """ | |||
|         Overwrites the existing shop_payment function. | |||
|         Removed the redirection if there is no address for user. | |||
|         This page proposes several payment means based on available | |||
|         payment.provider. State at this point : | |||
| 
 | |||
|          - a draft sales order with lines; otherwise, clean context / session | |||
|             and back to the shop | |||
|          - no transaction in context / session, or only a draft one, if the | |||
|             customer did go to a 'payment.provider' webshop_payment site but | |||
|             closed the tab without paying / canceling | |||
|         """ | |||
|         order = request.website.sale_get_order() | |||
|         render_values = self._get_shop_payment_values(order, **post) | |||
|         render_values['only_services'] = order and order.only_services or False | |||
|         address_values = self._get_address_values(**post) | |||
|         # Included /address values to the /payment and its template | |||
|         render_values.update({ | |||
|             'country_states': address_values.get('country_states', []), | |||
|             'only_services': address_values.get('only_services', False), | |||
|             'countries': address_values.get('countries', []), | |||
|             'country': address_values.get('country', []), | |||
|             'checkout': address_values.get('checkout', []), | |||
|             'error': address_values.get('error', {}), | |||
|             'mode': address_values.get('mode', 'shipping'), | |||
|             'add': True if address_values.get('response_template') is None else False, | |||
|         }) | |||
|         if render_values['errors']: | |||
|             render_values.pop('providers', '') | |||
|             render_values.pop('tokens', '') | |||
|         return request.render("website_sale.payment", render_values) | |||
| @ -0,0 +1,6 @@ | |||
| ## Module <one_page_checkout> | |||
| 
 | |||
| #### 08.04.2024 | |||
| #### Version 15.0.1.0.0 | |||
| #### ADD | |||
| - Initial Commit for One Page Checkout  | |||
| After Width: | Height: | Size: 3.6 KiB | 
| After Width: | Height: | Size: 310 B | 
| After Width: | Height: | Size: 1.3 KiB | 
| After Width: | Height: | Size: 1.4 KiB | 
| After Width: | Height: | Size: 576 B | 
| After Width: | Height: | Size: 733 B | 
| After Width: | Height: | Size: 911 B | 
| After Width: | Height: | Size: 1.1 KiB | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 673 B | 
| After Width: | Height: | Size: 878 B | 
| After Width: | Height: | Size: 653 B | 
| After Width: | Height: | Size: 905 B | 
| After Width: | Height: | Size: 839 B | 
| After Width: | Height: | Size: 427 B | 
| After Width: | Height: | Size: 627 B | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 988 B | 
| After Width: | Height: | Size: 1.2 KiB | 
| After Width: | Height: | Size: 1.5 KiB | 
| After Width: | Height: | Size: 1.1 KiB | 
| After Width: | Height: | Size: 1.9 KiB | 
| After Width: | Height: | Size: 1.1 KiB | 
| After Width: | Height: | Size: 2.1 KiB | 
| After Width: | Height: | Size: 4.4 KiB | 
| After Width: | Height: | Size: 589 B | 
| After Width: | Height: | Size: 3.4 KiB | 
| After Width: | Height: | Size: 1.7 KiB | 
| After Width: | Height: | Size: 2.3 KiB | 
| After Width: | Height: | Size: 967 B | 
| After Width: | Height: | Size: 1.6 KiB | 
| After Width: | Height: | Size: 3.8 KiB | 
| After Width: | Height: | Size: 5.0 KiB | 
| After Width: | Height: | Size: 49 KiB | 
| After Width: | Height: | Size: 45 KiB | 
| After Width: | Height: | Size: 43 KiB | 
| After Width: | Height: | Size: 84 KiB | 
| After Width: | Height: | Size: 48 KiB | 
| After Width: | Height: | Size: 48 KiB | 
| After Width: | Height: | Size: 162 KiB | 
| After Width: | Height: | Size: 109 KiB | 
| After Width: | Height: | Size: 91 KiB | 
| After Width: | Height: | Size: 98 KiB | 
| After Width: | Height: | Size: 77 KiB | 
| After Width: | Height: | Size: 128 KiB | 
| After Width: | Height: | Size: 80 KiB | 
| After Width: | Height: | Size: 8.9 KiB | 
| @ -0,0 +1,651 @@ | |||
| <div style="background-color: #714B67; height: 810px; width: 100%; | |||
|  padding: 15px; position: relative;"> | |||
|     <!-- TITLE BAR --> | |||
|     <div class="d-flex align-items-center justify-content-between" | |||
|          style="border-bottom: 1px solid #875A7B; padding: 15px; display: flex; justify-content: space-between; align-items: center;"> | |||
|         <img src="assets/misc/cybrosys-logo.png" width="42" height="42" | |||
|              style="width: 42px; height: 42px;"/> | |||
|         <div> | |||
|             <div | |||
|                     style="color: #7C7BAD; font-size: 14px; | |||
|                     font-family: 'Montserrat', sans-serif; font-weight: bold; | |||
|                     background-color: white; display: inline-block; | |||
|                     padding: 3px 10px; border-radius: 50px;" | |||
|                     class="mr-2"> | |||
|                 <i class="fa fa-check mr-1"></i>Community | |||
|             </div> | |||
|             <div | |||
|                     style="color: #da3ce8; 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: #e83cb2; font-size: 14px; f | |||
|                     ont-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;"> | |||
|                     One Page Checkout</h1> | |||
|                 <p style="color:#FFFFFF; padding: 8px 15px; text-align: center; font-size: 24px;"> | |||
|                     This Module simplifies ecommerce checkout by condensing it | |||
|                     into a single, | |||
|                     user-friendly page. | |||
|                 </p> | |||
|                 <img src="./assets/screenshots/hero.gif" | |||
|                      class="img-responsive" width="100%" height="auto"/> | |||
| 
 | |||
|                 <!-- END OF APP HERO --> | |||
|             </div> | |||
|         </div> | |||
|     </div> | |||
| 
 | |||
| 
 | |||
| </div> | |||
| 
 | |||
| <!-- NAVIGATION SECTION --> | |||
| <div class="d-flex align-items-center" | |||
|      style="border-bottom: 2px solid #714B67; padding: 15px 0px; margin-top: 300px;"> | |||
|     <div class="d-flex justify-content-center align-items-center mr-2" | |||
|          style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | |||
|         <img src="assets/misc/compass.png"/> | |||
|     </div> | |||
|     <h2 class="mt-2" | |||
|         style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | |||
|         Explore This | |||
|         Module</h2> | |||
| </div> | |||
| <div class="row my-4" style="font-family: 'Montserrat', sans-serif;"> | |||
|     <div class="col-sm-12 col-md-6 my-3"> | |||
|         <a href="#overview"> | |||
|             <div class="d-flex justify-content-between align-items-center" | |||
|                  style="background-color: #f5f5f5; padding: 30px; width: 100%;"> | |||
|                 <div> | |||
|                     <span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Overview</span> | |||
|                     <span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33;  display: block;">Learn | |||
|             more about this | |||
|             module</span> | |||
|                 </div> | |||
|                 <img src="assets/misc/right-arrow.png" width="36" height="36"/> | |||
|             </div> | |||
|         </a> | |||
|     </div> | |||
|     <div class="col-sm-12 col-md-6 my-3"> | |||
|         <a href="#features"> | |||
|             <div class="d-flex justify-content-between align-items-center" | |||
|                  style="background-color: #f5f5f5; padding: 30px; width: 100%;"> | |||
|                 <div> | |||
|                     <span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Features</span> | |||
|                     <span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33;  display: block;">View | |||
|             features of this | |||
|             module</span> | |||
|                 </div> | |||
|                 <img src="assets/misc/right-arrow.png" width="36" height="36"/> | |||
|             </div> | |||
|         </a> | |||
|     </div> | |||
|     <div class="col-sm-12 col-md-6 my-3"> | |||
|         <a href="#screenshots"> | |||
|             <div class="d-flex justify-content-between align-items-center" | |||
|                  style="background-color: #f5f5f5; padding: 30px; width: 100%;"> | |||
|                 <div> | |||
|                     <span style="color: #714B67; font-size: 24px; font-weight: 500; display: block;">Screenshots</span> | |||
|                     <span style="color: #714B67; font-size: 16px; font-weight: 400; color:#282F33;  display: block;">View | |||
|             screenshots for this | |||
|             module</span> | |||
|                 </div> | |||
|                 <img src="assets/misc/right-arrow.png" width="36" height="36"/> | |||
|             </div> | |||
|         </a> | |||
|     </div> | |||
| </div> | |||
| <!-- END OF NAVIGATION SECTION --> | |||
| 
 | |||
| <!-- OVERVIEW SECTION --> | |||
| <div class="d-flex align-items-center" | |||
|      style="border-bottom: 2px solid #714B67; padding: 15px 0px;" id="overview"> | |||
|     <div class="d-flex justify-content-center align-items-center mr-2" | |||
|          style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | |||
|         <img src="assets/misc/pie-chart.png"/> | |||
|     </div> | |||
|     <h2 class="mt-2" | |||
|         style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | |||
|         Overview | |||
|     </h2> | |||
| </div> | |||
| <div class="row" | |||
|      style="font-family: 'Montserrat', sans-serif; font-weight: 400; font-size: 14px; line-height: 200%;"> | |||
|     <div class="col-sm-12 py-4"> | |||
|         This Module simplifies ecommerce checkout by condensing it into a | |||
|         single, | |||
|         user-friendly page. | |||
|     </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;">Select any delivery method.</span> | |||
|             <span style="display:block; font-family:'Montserrat', sans-serif; font-size:14px">Choose your preferred delivery method from a range | |||
|                 of options available for your orders.</span> | |||
|         </div> | |||
|         <div class="d-flex align-items-center" style="margin-top: 30px; | |||
|         margin-bottom: 30px"> | |||
|             <img src="assets/misc/check-box.png" class="mr-2"/> | |||
|             <span style="font-family: 'Montserrat', sans-serif; | |||
|             font-size: 18px; font-weight: bold;">Create a new address and select existing address.</span> | |||
|             <span style="font-family: 'Montserrat', sans-serif; | |||
|             font-size: 18px; font-weight: bold;">Easily add a new address to your profile or select | |||
|                 from existing addresses for a seamless and personalized checkout experience.</span> | |||
|         </div> | |||
|     </div> | |||
|     <div class="col-sm-12 col-md-6"> | |||
|         <div class="d-flex align-items-center" style="margin-top: 30px; | |||
|          margin-bottom: 30px"> | |||
|             <img src="assets/misc/check-box.png" class="mr-2"/> | |||
|             <span style="font-family: 'Montserrat', sans-serif; | |||
|              font-size: 18px; font-weight: bold;">Apply your promo-codes.</span> | |||
|             <span style="font-family: 'Montserrat', sans-serif; | |||
|              font-size: 18px; font-weight: bold;">Enter your promo code to apply special discounts.</span> | |||
| 
 | |||
|         </div> | |||
|         <div class="d-flex align-items-center" | |||
|              style="margin-top: 30px; margin-bottom: 30px"> | |||
|             <img src="assets/misc/check-box.png" class="mr-2"/> | |||
|             <span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Inline validation for public users.</span> | |||
|             <span style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;">Enable inline form validation for public users, | |||
|                 ensuring that inputted data is instantly validated and errors | |||
|                 are highlighted for a smoother and error-free user experience.</span> | |||
|         </div> | |||
|     </div> | |||
| </div> | |||
| <!-- END OF FEATURES SECTION --> | |||
| 
 | |||
| <!-- SCREENSHOTS SECTION --> | |||
| <div class="d-flex align-items-center" | |||
|      style="border-bottom: 2px solid #714B67; padding: 15px 0px;" | |||
|      id="screenshots"> | |||
|     <div class="d-flex justify-content-center align-items-center mr-2" | |||
|          style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | |||
|         <img src="assets/misc/pictures.png"/> | |||
|     </div> | |||
|     <h2 class="mt-2" | |||
|         style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | |||
|         Screenshots | |||
|     </h2> | |||
| </div> | |||
| <div class="row"> | |||
|     <div class="col-sm-12"> | |||
| 
 | |||
|         <div style="display: block; margin: 30px auto;"> | |||
|             <h3 style="font-family: 'Montserrat', sans-serif; font-size: 18px; font-weight: bold;"> | |||
|                 Checking out with Login User. | |||
|             </h3> | |||
|             <img src="assets/screenshots/sc1.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;"> | |||
|                 Form validation on checking out with Public User. | |||
|             </h3> | |||
|             <img src="assets/screenshots/sc2.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;"> | |||
|                Checking out with Public User by adding required details. | |||
|             </h3> | |||
|             <img src="assets/screenshots/sc3.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;"> | |||
|                Confirm it by clicking on confirm button and save the address | |||
|             </h3> | |||
|             <img src="assets/screenshots/sc4.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;"> | |||
|                Payment done adding payment details and redirected to confirmation page | |||
|             </h3> | |||
|             <img src="assets/screenshots/sc6.png" class="img-thumbnail"> | |||
|         </div> | |||
|     </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/15.0/woo_commerce/" | |||
|                            target="_blank"> | |||
|                             <div style="border-radius:10px"> | |||
|                                 <img class="img img-responsive center-block" | |||
|                                      style="border-radius: 0px;" | |||
|                                      src="./assets/modules/1.png"> | |||
|                             </div> | |||
|                         </a> | |||
|                     </div> | |||
|                     <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" | |||
|                          style="float:left"> | |||
|                         <a href="https://apps.odoo.com/apps/modules/15.0/delivery_date_ecommerce/" | |||
|                            target="_blank"> | |||
|                             <div style="border-radius:10px"> | |||
|                                 <img class="img img-responsive center-block" | |||
|                                      style="border-radius: 0px;" | |||
|                                      src="./assets/modules/2.png"></div> | |||
|                         </a> | |||
|                     </div> | |||
|                     <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" | |||
|                          style="float:left"> | |||
|                         <a href="https://apps.odoo.com/apps/modules/15.0/website_repeat_sale/" | |||
|                            target="_blank"> | |||
|                             <div style="border-radius:10px"> | |||
|                                 <img class="img img-responsive center-block" | |||
|                                      style="border-radius: 0px;" | |||
|                                      src="./assets/modules/3.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/15.0/geoip_website_redirect/" | |||
|                            target="_blank"> | |||
|                             <div style="border-radius:10px"> | |||
|                                 <img class="img img-responsive center-block" | |||
|                                      style="border-radius: 0px;" | |||
|                                      src="./assets/modules/4.png"></div> | |||
|                         </a> | |||
|                     </div> | |||
|                     <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" | |||
|                          style="float:left"> | |||
|                         <a href="https://apps.odoo.com/apps/modules/15.0/product_brand_ecommerce/" | |||
|                            target="_blank"> | |||
|                             <div style="border-radius:10px"> | |||
|                                 <img class="img img-responsive center-block" | |||
|                                      style="border-radius: 0px;" | |||
|                                      src="./assets/modules/5.png"></div> | |||
|                         </a> | |||
|                     </div> | |||
|                     <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" | |||
|                          style="float:left"> | |||
|                         <a href="https://apps.odoo.com/apps/modules/15.0/table_reservation_on_website/" | |||
|                            target="_blank"> | |||
|                             <div style="border-radius:10px"> | |||
|                                 <img class="img img-responsive center-block" | |||
|                                      style="border-radius: 0px;" | |||
|                                      src="./assets/modules/6.png"></div> | |||
|                         </a> | |||
|                     </div> | |||
|                 </div> | |||
|             </div> | |||
|             <!-- Left and right controls --> | |||
|             <a class="carousel-control-prev" href="#demo1" data-slide="prev" | |||
|                style="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 & Website | |||
|                 </h5> | |||
|                 <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | |||
|                     Mobile | |||
|                     friendly, | |||
|                     awe-inspiring product pages</p> | |||
|             </div> | |||
|         </div> | |||
|         <div class="col-lg-3"> | |||
|             <div class="my-4 d-flex flex-column justify-content-center" | |||
|                  style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> | |||
|                 <img src="assets/icons/service-black.png" | |||
|                      class="img-responsive mb-3" height="48px" width="48px"> | |||
|                 <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | |||
|                     Service Management | |||
|                 </h5> | |||
|                 <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | |||
|                     Keep track of | |||
|                     services and invoice</p> | |||
|             </div> | |||
|         </div> | |||
|         <div class="col-lg-3"> | |||
|             <div class="my-4 d-flex flex-column justify-content-center" | |||
|                  style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> | |||
|                 <img src="assets/icons/restaurant-black.png" | |||
|                      class="img-responsive mb-3" height="48px" width="48px"> | |||
|                 <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | |||
|                     Restaurant | |||
|                 </h5> | |||
|                 <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | |||
|                     Run your bar or | |||
|                     restaurant methodically</p> | |||
|             </div> | |||
|         </div> | |||
|         <div class="col-lg-3"> | |||
|             <div class="my-4 d-flex flex-column justify-content-center" | |||
|                  style="background-color: #f6f8f9 !important; border-radius: 0px; padding: 2rem !important; height: 250px !important;"> | |||
|                 <img src="assets/icons/hotel-black.png" | |||
|                      class="img-responsive mb-3" height="48px" width="48px"> | |||
|                 <h5 style="font-family: Montserrat, sans-serif !important; color: #000 !important; font-weight: bold;"> | |||
|                     Hotel Management | |||
|                 </h5> | |||
|                 <p style="font-family: Montserrat, sans-serif !important; font-size: 0.9rem !important;"> | |||
|                     An | |||
|                     all-inclusive | |||
|                     hotel management application</p> | |||
|             </div> | |||
|         </div> | |||
|     </div> | |||
| </div> | |||
| <!-- END OF OUR INDUSTRIES --> | |||
| 
 | |||
| <!-- SUPPORT --> | |||
| <div class="d-flex align-items-center" | |||
|      style="border-bottom: 2px solid #714B67; padding: 15px 0px;"> | |||
|     <div class="d-flex justify-content-center align-items-center mr-2" | |||
|          style="background-color: #F5F5F5; border-radius: 0px; width: 40px; height: 40px;"> | |||
|         <img src="assets/misc/customer-support.png"/> | |||
|     </div> | |||
|     <h2 class="mt-2" | |||
|         style="font-family: 'Montserrat', sans-serif; font-size: 24px; font-weight: bold;"> | |||
|         Support | |||
|     </h2> | |||
| </div> | |||
| <div class="container mt-5"> | |||
|     <div class="row"> | |||
|         <div class="col-sm-12 col-md-6"> | |||
|             <div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;"> | |||
|                 <div class="mr-4 d-flex justify-content-center align-items-center" | |||
|                      style="background-color: #714B67; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;"> | |||
|                     <img src="assets/misc/support.png" height="48" width="48" | |||
|                          style="width: 42px; height: 42px;"/> | |||
|                 </div> | |||
|                 <div> | |||
|                     <h4>Need Help?</h4> | |||
|                     <p style="line-height: 100%;">Got questions or need help? | |||
|                         Get in touch.</p> | |||
|                     <a href="mailto:odoo@cybrosys.com"> | |||
|                         <p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;"> | |||
|                             odoo@cybrosys.com</p> | |||
|                     </a> | |||
|                 </div> | |||
|             </div> | |||
|         </div> | |||
|         <div class="col-sm-12 col-md-6"> | |||
|             <div style="background-color: #F6F8F9; padding: 30px; display: flex; align-items: center;"> | |||
|                 <div class="mr-4 d-flex justify-content-center align-items-center" | |||
|                      style="background-color: #2AC44D; display: inline-block; height: 70px; width: 70px; display: flex; align-items: center; justify-content: center;"> | |||
|                     <img src="assets/misc/whatsapp.png" height="52" width="52" | |||
|                          style="width: 52px; height: 52px;"/> | |||
|                 </div> | |||
|                 <div> | |||
|                     <h4>WhatsApp</h4> | |||
|                     <p style="line-height: 100%;">Say hi to us on WhatsApp!</p> | |||
|                     <a href="https://api.whatsapp.com/send?phone=918606827707"> | |||
|                         <p style="font-weight: 400; font-size: 28px; line-height: 80%; color: #714B67;"> | |||
|                             +91 86068 | |||
|                             27707</p> | |||
|                     </a> | |||
|                 </div> | |||
|             </div> | |||
|         </div> | |||
|     </div> | |||
|     <div class="row"> | |||
|         <div class="col-sm-12 my-5 d-flex justify-content-center align-items-center"> | |||
|             <img src="assets/misc/logo.png" width="144" height="31" | |||
|                  style="width:144px; height: 31px; margin-top: 40px;"/> | |||
|         </div> | |||
|     </div> | |||
| </div> | |||
| <!-- END OF SUPPORT --> | |||
| @ -0,0 +1,40 @@ | |||
| /* Column Responsive CSS for including three templates in a single page */ | |||
| .single_pg_checkout_layout{ | |||
|     width:90%; | |||
|     max-width:1400px; | |||
|     margin:15px auto; | |||
| } | |||
| .single_pg_checkout_layout .column { | |||
|   float: left; | |||
|   width: 29.33%; | |||
|   margin:15px auto; | |||
| 
 | |||
| } | |||
| .block-ui{ | |||
|     pointer-events:none; | |||
|     opacity:0.5; | |||
| } | |||
| /* Clear floats after the columns */ | |||
| .single_pg_checkout_layout:after { | |||
|   content: ""; | |||
|   display: table; | |||
|   clear: both; | |||
| } | |||
| @media screen and (max-width: 500px) { | |||
|   .single_pg_checkout_layout .column { | |||
|     width: 80%; | |||
|     margin: 15px auto; | |||
|   } | |||
| } | |||
| @media screen and (max-width: 500px) { | |||
|   .single_pg_checkout_layout .column { | |||
|     width: 90%; | |||
|     margin: 15px auto; | |||
|   } | |||
| } | |||
| @media screen and (max-width: 500px) { | |||
|   .single_pg_checkout_layout .column { | |||
|     width: 97%; | |||
|     margin: 15px auto; | |||
|   } | |||
| } | |||
| @ -0,0 +1,32 @@ | |||
| odoo.define('one_page_checkout.checkout_form', require => { | |||
|     'use strict'; | |||
| 
 | |||
|     const publicWidget = require('web.public.widget'); | |||
|     const paymentFormMixin = require('payment.payment_form_mixin'); | |||
|     /** | |||
|      * OnePagePaymentForm widget. Enhances the payment form by adding a click | |||
|      * event listener that submits the extra_info_form along with the payment form. | |||
|      * | |||
|      * @extends paymentFormMixin | |||
|      */ | |||
|     publicWidget.registry.OnePagePaymentForm = publicWidget.Widget.extend(paymentFormMixin, { | |||
|         selector: 'form[name="o_payment_checkout"]', | |||
|         events: Object.assign({}, publicWidget.Widget.prototype.events, { | |||
|                 'click button[name="o_payment_submit_button"]': '_onClickPayment', | |||
|             }), | |||
|         init: function () { | |||
|             this._super(...arguments); | |||
|         }, | |||
|         /** | |||
|          * OnePagePaymentForm widget. Enhances the payment form by adding a click | |||
|          * event listener that submits the extra_info_form along with the payment form. | |||
|          * | |||
|          * @extends paymentFormMixin | |||
|          */ | |||
|         _onClickPayment: async function (ev) { | |||
|             $('#extra_info_form').submit() | |||
| 
 | |||
|         }, | |||
|     }); | |||
|     return publicWidget.registry.OnePagePaymentForm; | |||
| }); | |||
| @ -0,0 +1,228 @@ | |||
| odoo.define('one_page_checkout.website_sale', function (require) { | |||
| 'use strict'; | |||
| 
 | |||
| var core = require('web.core'); | |||
| var config = require('web.config'); | |||
| var publicWidget = require('web.public.widget'); | |||
| var VariantMixin = require('website_sale.VariantMixin'); | |||
| var wSaleUtils = require('website_sale.utils'); | |||
| const cartHandlerMixin = wSaleUtils.cartHandlerMixin; | |||
| require("web.zoomodoo"); | |||
| const dom = require('web.dom'); | |||
| 
 | |||
| publicWidget.registry.OnePageCheckoutWebsiteSale = publicWidget.Widget.extend( | |||
|     VariantMixin, cartHandlerMixin, { | |||
|         selector: '.single_pg_checkout_layout', | |||
|         events: _.extend({}, VariantMixin.events || {}, { | |||
|             'click .a-submit': '_onClickSubmit', | |||
|             'click .show_coupon': '_onClickShowCoupon', | |||
|             'change select[name="country_id"]': '_onChangeCountry', | |||
|             'click span[title="Details"]': '_onCartDetailClick', | |||
|         }), | |||
| 
 | |||
|         /** | |||
|          * Initializes the widget. | |||
|          * Sets the `isWebsite` property to `true`. | |||
|          */ | |||
|         init: function () { | |||
|             this._super.apply(this, arguments); | |||
|             this.isWebsite = true; | |||
|         }, | |||
| 
 | |||
|         /** | |||
|          * Starts the widget. | |||
|          * Calls the super method and returns the resulting promise. | |||
|          * @returns {Promise} A promise representing the start of the widget. | |||
|          */ | |||
|         start() { | |||
|             const def = this._super(...arguments); | |||
|             return def; | |||
|         }, | |||
| 
 | |||
|         /** | |||
|          * Destroys the widget. | |||
|          * Calls the super method and performs any necessary cleanup. | |||
|          */ | |||
|         destroy() { | |||
|             this._super.apply(this, arguments); | |||
|             this._cleanupZoom(); | |||
|         }, | |||
|         /** | |||
|          * Changes the country and updates the corresponding fields | |||
|             based on the selected country. | |||
|          */ | |||
|         _changeCountry: function () { | |||
|             if (!$("#country_id").val()) { | |||
|                 return; | |||
|             } | |||
|             // Get country information via RPC call
 | |||
|             this._rpc({ | |||
|                 route: "/shop/country_infos/" + $("#country_id").val(), | |||
|                 params: { | |||
|                     mode: $("#country_id").attr('mode'), | |||
|                 }, | |||
|             }).then(function (data) { | |||
|                 $("input[name='phone']").attr('placeholder', data.phone_code !== 0 ? '+'+ data.phone_code : '');            // populate states and display
 | |||
|                 var selectStates = $("select[name='state_id']"); | |||
|                 // Dont reload state at first loading (done in qweb)
 | |||
|                 if (selectStates.data('init')===0 || selectStates.find('option').length===1) { | |||
|                     if (data.states.length || data.state_required) { | |||
|                         selectStates.html(''); | |||
|                         _.each(data.states, function (x) { | |||
|                             var opt = $('<option>').text(x[1]) | |||
|                                 .attr('value', x[0]) | |||
|                                 .attr('data-code', x[2]); | |||
|                             selectStates.append(opt); | |||
|                         }); | |||
|                         selectStates.parent('div').show(); | |||
|                     } else { | |||
|                         selectStates.val('').parent('div').hide(); | |||
|                     } | |||
|                     selectStates.data('init', 0); | |||
|                 } else { | |||
|                     selectStates.data('init', 0); | |||
|                 } | |||
|                 // Manage fields order / visibility
 | |||
|                 if (data.fields) { | |||
|                     if ($.inArray('zip', data.fields) > $.inArray('city', data.fields)){ | |||
|                         $(".div_zip").before($(".div_city")); | |||
|                     } else { | |||
|                         $(".div_zip").after($(".div_city")); | |||
|                     } | |||
|                     var all_fields = ["street", "zip", "city", "country_name"]; // "state_code"];
 | |||
|                     _.each(all_fields, function (field) { | |||
|                         $(".checkout_autoformat .div_" + field.split('_')[0]).toggle($.inArray(field, data.fields)>=0); | |||
|                     }); | |||
|                 } | |||
|                 if ($("label[for='zip']").length) { | |||
|                     $("label[for='zip']").toggleClass('label-optional', !data.zip_required); | |||
|                     $("label[for='zip']").get(0).toggleAttribute('required', !!data.zip_required); | |||
|                 } | |||
|                 if ($("label[for='zip']").length) { | |||
|                     $("label[for='state_id']").toggleClass('label-optional', !data.state_required); | |||
|                     $("label[for='state_id']").get(0).toggleAttribute('required', !!data.state_required); | |||
|                 } | |||
|             }); | |||
|         }, | |||
|         /** | |||
|          * Handles the click event on submit buttons and performs the necessary actions. | |||
|          * @param {Event} ev - The click event. | |||
|          * @param {boolean} forceSubmit - Determines whether to force the submission | |||
|             even if certain conditions are not met. | |||
|          */ | |||
|         _onClickSubmit: function (ev, forceSubmit) { | |||
|             if ($(ev.currentTarget).is('#products_grid .a-submit') && !forceSubmit) { | |||
|                 return; | |||
|             } | |||
|             // Hide the 'address_public_user' div
 | |||
|             var $aSubmit = $(ev.currentTarget); | |||
|             if (!ev.isDefaultPrevented() && !$aSubmit.is(".disabled")) { | |||
|                 ev.preventDefault(); | |||
|                 $aSubmit.closest('form').submit(); | |||
|             } | |||
|             if ($aSubmit.hasClass('a-submit-disable')) { | |||
|                 $aSubmit.addClass("disabled"); | |||
|             } | |||
|             if ($aSubmit.hasClass('a-submit-loading')) { | |||
|                 var loading = '<span class="fa fa-cog fa-spin"/>'; | |||
|                 var fa_span = $aSubmit.find('span[class*="fa"]'); | |||
|                 if (fa_span.length) { | |||
|                     fa_span.replaceWith(loading); | |||
|                 } else { | |||
|                     $aSubmit.append(loading); | |||
|                 } | |||
|             } | |||
|         }, | |||
|         /** | |||
|          * Handles the click event to show the coupon form by hiding the | |||
|             "show coupon" button and displaying the coupon form. | |||
|          * @param {Event} ev - The click event. | |||
|          */ | |||
|         _onClickShowCoupon: function (ev) { | |||
|             $(".show_coupon").hide(); | |||
|             $('.coupon_form').removeClass('d-none'); | |||
|         }, | |||
|         /** | |||
|          * Handles the change event on the country field and triggers the country | |||
|             change functionality. | |||
|          * If the checkout_autoformat element is not present, the function does | |||
|             nothing.one_page_checkout_cart | |||
|          * This function internally calls the _changeCountry function. | |||
|          * @param {Event} ev - The change event. | |||
|          */ | |||
|         _onChangeCountry: function (ev) { | |||
|             if (!this.$('.checkout_autoformat').length) { | |||
|                 return; | |||
|             } | |||
|             this._changeCountry(); | |||
|         }, | |||
|         /** | |||
|          * Handles the click event on the cart detail element. | |||
|          * Toggles the chevron icon and shows/hides the summary div accordingly. | |||
|          * @param {Event} ev - The click event. | |||
|          */ | |||
|         _onCartDetailClick: function(ev) { | |||
|             var $elem = $(ev.currentTarget); | |||
|             if ($elem.hasClass('fa-chevron-down')) { | |||
|                 $elem.removeClass('fa-chevron-down'); | |||
|                 $elem.addClass('fa-chevron-up'); | |||
|             } else { | |||
|                 $elem.removeClass('fa-chevron-up'); | |||
|                 $elem.addClass('fa-chevron-down'); | |||
|             } | |||
|             var $summary_div = $('.toggle_summary_div'); | |||
|             $summary_div.toggleClass('d-none'); | |||
|         } | |||
| }); | |||
| /** | |||
|  * This widget is used for the one-page checkout cart functionality. | |||
|  * It adds events to change shipping and edit address. | |||
|  */ | |||
| publicWidget.registry.OnePageCheckoutWebsiteSaleCart = publicWidget.Widget.extend({ | |||
|     selector: '.single_pg_checkout_layout .oe_cart', | |||
|     events: { | |||
|         'click .js_change_shipping': '_onClickChangeShipping', | |||
|         'click .js_edit_address': '_onClickEditAddress', | |||
|     }, | |||
|     /** | |||
|      * Handles the click event on the "Change Shipping" element. | |||
|      * Updates the shipping options by toggling visibility and applying CSS classes. | |||
|      * Performs a POST request to update the selected shipping option via AJAX. | |||
|      * @param {Event} ev - The click event. | |||
|      */ | |||
|     _onClickChangeShipping: function (ev) { | |||
|         var $old = $('.all_shipping').find('.card.border.border-primary'); | |||
|         $old.find('.btn-ship').toggle(); | |||
|         $old.addClass('js_change_shipping'); | |||
|         $old.removeClass('border border-primary'); | |||
| 
 | |||
|         var $new = $(ev.currentTarget).parent('div.one_kanban').find('.card'); | |||
|         $new.find('.btn-ship').toggle(); | |||
|         $new.removeClass('js_change_shipping'); | |||
|         $new.addClass('border border-primary'); | |||
| 
 | |||
|         var $form = $(ev.currentTarget).parent('div.one_kanban').find('form.d-none'); | |||
|         $.post($form.attr('action'), $form.serialize()+'&xhr=1'); | |||
|     }, | |||
|     /** | |||
|      * Handles the click event on the "Edit Address" element. | |||
|      * Prevents the default action of the click event. | |||
|      * Updates the action attribute of the corresponding form and submits it. | |||
|      * @param {Event} ev - The click event. | |||
|      */ | |||
|     _onClickEditAddress: function (ev) { | |||
|         ev.preventDefault(); | |||
|         $(ev.currentTarget).closest('div.one_kanban').find('form.d-none').attr('action', '/shop/address').submit(); | |||
|     } | |||
| }); | |||
| /** | |||
|  * Returns an object with two properties representing publicWidget registries. | |||
|  * - OnePageCheckoutWebsiteSale: Represents the publicWidget registry for the OnePageCheckoutWebsiteSale. | |||
|  * - OnePageCheckoutWebsiteSaleCart: Represents the publicWidget registry for the OnePageCheckoutWebsiteSaleCart. | |||
|  * @returns {Object} An object with publicWidget registries. | |||
|  */ | |||
| return { | |||
|     OnePageCheckoutWebsiteSale: publicWidget.registry.OnePageCheckoutWebsiteSale, | |||
|     OnePageCheckoutWebsiteSaleCart: publicWidget.registry.OnePageCheckoutWebsiteSaleCart, | |||
| }; | |||
| }); | |||
| @ -0,0 +1,138 @@ | |||
| odoo.define('one_page_checkout.checkout', function (require) { | |||
| 'use strict'; | |||
| 
 | |||
| var core = require('web.core'); | |||
| var publicWidget = require('web.public.widget'); | |||
| 
 | |||
| var _t = core._t; | |||
| var concurrency = require('web.concurrency'); | |||
| var dp = new concurrency.DropPrevious(); | |||
| 
 | |||
| publicWidget.registry.OPCWebsiteSaleDelivery = publicWidget.Widget.extend({ | |||
|     selector: '.single_pg_checkout_layout', | |||
|     events: { | |||
|         'change select[name="shipping_id"]': '_onSetAddress', | |||
|         'click #delivery_carrier .o_delivery_carrier_select': '_onCarrierClick', | |||
|     }, | |||
|     /** | |||
|      * @override | |||
|      */ | |||
|     start: function () { | |||
|         var self = this; | |||
|         var $carriers = $('#delivery_carrier input[name="delivery_type"]'); | |||
|         // Asynchronously retrieve every carrier price
 | |||
|         _.each($carriers, function (carrierInput, k) { | |||
|             self._showLoading($(carrierInput)); | |||
|             self._rpc({ | |||
|                 route: '/shop/carrier_rate_shipment', | |||
|                 params: { | |||
|                     'carrier_id': carrierInput.value, | |||
|                 }, | |||
|             }).then(self._handleCarrierUpdateResultBadge.bind(self)); | |||
|         }); | |||
|         return this._super.apply(this, arguments); | |||
|     }, | |||
|     /** | |||
|      * @private | |||
|      * @param {jQuery} $carrierInput | |||
|      */ | |||
|     _showLoading: function ($carrierInput) { | |||
|         $carrierInput.siblings('.o_wsale_delivery_badge_price').empty(); | |||
|         $carrierInput.siblings('.o_wsale_delivery_badge_price').append('<span class="fa fa-circle-o-notch fa-spin"/>'); | |||
|     }, | |||
|     /** | |||
|      * Update the total cost according to the selected shipping method | |||
|      * | |||
|      * @private | |||
|      * @param {float} amount : The new total amount of to be paid | |||
|      */ | |||
|     _updateShippingCost: function(amount){ | |||
|         core.bus.trigger('update_shipping_cost', amount); | |||
|     }, | |||
|     /** | |||
|      * Handles the result of the carrier update and updates the relevant elements on the order summary. | |||
|      * Updates the carrier badge, delivery amount, untaxed amount, tax amount, total amount, and shipping cost (if applicable). | |||
|      * @param {Object} result - The result of the carrier update. | |||
|      */ | |||
|     _handleCarrierUpdateResult: function (result) { | |||
|         this._handleCarrierUpdateResultBadge(result); | |||
|         var $amountDelivery = $('#order_delivery .monetary_field'); | |||
|         var $amountUntaxed = $('#order_total_untaxed .monetary_field'); | |||
|         var $amountTax = $('#order_total_taxes .monetary_field'); | |||
|         var $amountTotal = $('#order_total .monetary_field, #amount_total_summary.monetary_field'); | |||
| 
 | |||
|         if (result.status === true) { | |||
|             $amountDelivery.html(result.new_amount_delivery); | |||
|             $amountUntaxed.html(result.new_amount_untaxed); | |||
|             $amountTax.html(result.new_amount_tax); | |||
|             $amountTotal.html(result.new_amount_total); | |||
|         } else { | |||
|             $amountDelivery.html(result.new_amount_delivery); | |||
|             $amountUntaxed.html(result.new_amount_untaxed); | |||
|             $amountTax.html(result.new_amount_tax); | |||
|             $amountTotal.html(result.new_amount_total); | |||
|         } | |||
|         if (result.new_amount_total_raw !== undefined) { | |||
|             this._updateShippingCost(result.new_amount_total_raw); | |||
|         } | |||
|     }, | |||
|     /** | |||
|      * Handles the result of the carrier update and updates the carrier badge accordingly. | |||
|      * Updates the badge text and styling based on the result status and amount. | |||
|      * @param {Object} result - The result of the carrier update. | |||
|      */ | |||
|     _handleCarrierUpdateResultBadge: function (result) { | |||
|         var $carrierBadge = $('#delivery_carrier input[name="delivery_type"][value=' + result.carrier_id + '] ~ .o_wsale_delivery_badge_price'); | |||
| 
 | |||
|         if (result.status === true) { | |||
|             // If free delivery (`free_over` field), show 'Free', not '$0'
 | |||
|             if (result.is_free_delivery) { | |||
|                 $carrierBadge.text(_t('Free')); | |||
|             } else { | |||
|                 $carrierBadge.html(result.new_amount_delivery); | |||
|             } | |||
|             $carrierBadge.removeClass('o_wsale_delivery_carrier_error'); | |||
|         } else { | |||
|             $carrierBadge.addClass('o_wsale_delivery_carrier_error'); | |||
|             $carrierBadge.text(result.error_message); | |||
|         } | |||
|     }, | |||
|     /** | |||
|      * Handles the click event on a carrier element. | |||
|      * Updates the selected carrier by sending an RPC request to update the carrier. | |||
|      * Shows a loading indicator while the request is being processed. | |||
|      * @param {Event} ev - The click event. | |||
|      */ | |||
|     _onCarrierClick: function (ev) { | |||
|         var $radio = $(ev.currentTarget).find('input[type="radio"]'); | |||
|         this._showLoading($radio); | |||
|         $radio.prop("checked", true); | |||
|         dp.add(this._rpc({ | |||
|             route: '/shop/update_carrier', | |||
|             params: { | |||
|                 carrier_id: $radio.val(), | |||
|             }, | |||
|         })).then(this._handleCarrierUpdateResult.bind(this)); | |||
|     }, | |||
|     /** | |||
|      * Handles the change event on the address selection element. | |||
|      * Determines whether to show the available shipping countries for billing or all countries. | |||
|      * Updates the visibility and disabled state of the country and state selection elements accordingly. | |||
|      * @param {Event} ev - The change event. | |||
|      */ | |||
|     _onSetAddress: function (ev) { | |||
|         var value = $(ev.currentTarget).val(); | |||
|         var $providerFree = $('select[name="country_id"]:not(.o_provider_restricted), select[name="state_id"]:not(.o_provider_restricted)'); | |||
|         var $providerRestricted = $('select[name="country_id"].o_provider_restricted, select[name="state_id"].o_provider_restricted'); | |||
|         if (value === 0) { | |||
|             // Ship to the same address: only show shipping countries available for billing
 | |||
|             $providerFree.hide().attr('disabled', true); | |||
|             $providerRestricted.show().attr('disabled', false).change(); | |||
|         } else { | |||
|             // Create a new address: show all countries available for billing
 | |||
|             $providerFree.show().attr('disabled', false).change(); | |||
|             $providerRestricted.hide().attr('disabled', true); | |||
|         } | |||
|     }, | |||
| }); | |||
| }); | |||
| @ -0,0 +1,91 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo> | |||
|     <template id="address_column" name="Address Column"> | |||
|         <div class="col-12 col-xl order-xl-1 oe_cart"> | |||
|             <div class="row" | |||
|                  t-if="not only_services and not request.website.is_public_user()"> | |||
|                 <div class="col-lg-12"> | |||
|                     <h3 class="o_page_header mt8"> | |||
|                         Billing Address | |||
|                     </h3> | |||
|                 </div> | |||
|                 <!-- Call the address_kanban template for the billing address --> | |||
|                 <div class="col-lg-12 one_kanban"> | |||
|                     <t t-call="website_sale.address_kanban"> | |||
|                         <t t-set='contact' | |||
|                            t-value="order.partner_id"/> | |||
|                         <t t-set='selected' t-value="1"/> | |||
|                         <t t-set='readonly' t-value="1"/> | |||
|                         <t t-set='allow_edit' t-value="1"/> | |||
|                     </t> | |||
|                 </div> | |||
|             </div> | |||
|             <!-- Display the shipping address header if the user is not a | |||
|             public user and has permission to access the delivery/invoice address group --> | |||
|             <t t-if="not only_services and not request.website.is_public_user()"> | |||
|                 <div class="row"> | |||
|                     <div class="col-lg-12"> | |||
|                         <h3 class="o_page_header mt16 mb4"> | |||
|                             Shipping Address | |||
|                         </h3> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="col-lg-12 one_kanban"> | |||
|                     <t t-call="website_sale.address_kanban"> | |||
|                         <t t-set='contact' | |||
|                            t-value="order.partner_shipping_id"/> | |||
|                         <t t-set='selected' t-value="1"/> | |||
|                         <t t-set='readonly' t-value="1"/> | |||
|                         <t t-set='allow_edit' t-value="1"/> | |||
|                     </t> | |||
|                 </div> | |||
|                 <div class="row all_shipping"> | |||
|                     <div class="col-lg-12"> | |||
|                         <div class="row mt8"> | |||
|                             <!-- Display a button to add a new shipping address --> | |||
|                             <div class="col-md-12 col-lg-12 one_kanban"> | |||
|                                 <form action="/shop/address" | |||
|                                       method="post" | |||
|                                       class=''> | |||
|                                     <input type="hidden" | |||
|                                            name="csrf_token" | |||
|                                            t-att-value="request.csrf_token()" | |||
|                                            t-nocache="The csrf token must always be up to date."/> | |||
|                                     <a role="button" | |||
|                                        href="#" | |||
|                                        class='a-submit btn btn-secondary mb-2 btn-block'> | |||
|                                         <i class="fa fa-plus-square"/> | |||
|                                         <span> | |||
|                                             Add an address | |||
|                                         </span> | |||
|                                     </a> | |||
|                                 </form> | |||
|                             </div> | |||
|                             <!-- Loop over each shipping address and call | |||
|                             the address_kanban template for each address --> | |||
|                             <t t-foreach="shippings" | |||
|                                t-as="ship"> | |||
|                                 <div class="col-md-12 col-lg-6 one_kanban mb-2"> | |||
|                                     <t t-call="website_sale.address_kanban"> | |||
|                                         <t t-set='contact' | |||
|                                            t-value="ship"/> | |||
|                                         <t t-set='selected' | |||
|                                            t-value="order.partner_shipping_id==ship"/> | |||
|                                         <t t-set='readonly' | |||
|                                            t-value="bool(len(shippings)==1)"/> | |||
|                                         <t t-set='edit_billing' | |||
|                                            t-value="bool(ship==order.partner_id)"/> | |||
|                                         <t t-set="allow_edit" | |||
|                                            t-value="not order.partner_id or (ship.id in order.partner_id.child_ids.ids)"/> | |||
|                                     </t> | |||
|                                 </div> | |||
|                             </t> | |||
|                         </div> | |||
|                     </div> | |||
|                 </div> | |||
|             </t> | |||
|             <!-- Call the one_page_checkout.address_form template --> | |||
|             <t t-call="one_page_checkout.address_form"/> | |||
|         </div> | |||
|     </template> | |||
| </odoo> | |||
| @ -0,0 +1,198 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo> | |||
|     <template id="address_form" name="Address Form"> | |||
|         <div class="row"> | |||
|             <!-- Form for public users to enter their payment information --> | |||
|              <form id="address_form_id" t-if="request.website.is_public_user()" | |||
|                   action="/shop/payment" method="post" | |||
|                   class="checkout_autoformat"> | |||
|                  <div id='address_on_payment'> | |||
|                 <t t-call="website_sale.address_on_payment" t-set="address"/> | |||
|             </div> | |||
|                 <div class="row" t-if="not add"> | |||
|                     <t t-set="error_message" t-value="error.get('error_message', False)"/> | |||
|                     <t t-if="error_message"> | |||
|                         <h5 class="text-danger" t-esc="error_message[0]"/> | |||
|                     </t> | |||
|                     <div t-attf-class="mb-3 col-lg-12 div_name"> | |||
|                         <label class="col-form-label" | |||
|                                for="name">Name | |||
|                         </label> | |||
|                         <input type="text" name="name" | |||
|                                t-attf-class="form-control #{'is-invalid' if error.get('name', '') != '' else 'valid'}" | |||
|                                t-att-value="'name' in checkout and checkout['name']"/> | |||
|                     </div> | |||
|                     <div class="w-100"/> | |||
|                     <div t-attf-class="mb-3 col-lg-6" | |||
|                          id="div_email"> | |||
|                         <label t-attf-class="col-form-label #{mode[1] == 'shipping' and 'label-optional' or ''}" | |||
|                                for="email">Email | |||
|                         </label> | |||
|                         <input type="email" | |||
|                                name="email" | |||
|                                t-attf-class="form-control #{'is-invalid' if error.get('email', '') != '' else 'valid'}" | |||
|                                t-att-value="'email' in checkout and checkout['email']"/> | |||
|                     </div> | |||
|                     <div t-attf-class="mb-3 col-lg-6" | |||
|                          id="div_phone"> | |||
|                         <label class="col-form-label" | |||
|                                for="phone">Phone | |||
|                         </label> | |||
|                         <input type="tel" name="phone" | |||
|                                t-attf-class="form-control #{'is-invalid' if error.get('name', '') != '' else 'valid'}" | |||
|                                t-att-value="'phone' in checkout and checkout['phone']"/> | |||
|                     </div> | |||
|                     <div class="w-100"/> | |||
|                     <div t-attf-class="mb-3 col-lg-12 div_street"> | |||
|                         <label class="col-form-label" | |||
|                                for="street">Street | |||
|                             <span class="d-none d-md-inline"> | |||
|                                 and Number | |||
|                             </span> | |||
|                         </label> | |||
|                         <input type="text" | |||
|                                name="street" | |||
|                                t-attf-class="form-control #{'is-invalid' if error.get('street', '') != '' else 'valid'}" | |||
|                                t-att-value="'street' in checkout and checkout['street']"/> | |||
|                     </div> | |||
|                     <div t-attf-class="mb-3 col-lg-12 div_street2"> | |||
|                         <label class="col-form-label label-optional" | |||
|                                for="street2">Street 2 | |||
|                         </label> | |||
|                         <input type="text" | |||
|                                name="street2" | |||
|                                t-attf-class="form-control" | |||
|                                t-att-value="'street2' in checkout and checkout['street2']"/> | |||
|                     </div> | |||
|                     <div class="w-100"/> | |||
|                     <t t-set='zip_city' | |||
|                        t-value='country and [x for x in country.get_address_fields() if x in ["zip", "city"]] or ["city", "zip"]'/> | |||
|                     <t t-if="'zip' in zip_city and zip_city.index('zip') < zip_city.index('city')"> | |||
|                         <div t-attf-class="mb-3 col-md-4 div_zip"> | |||
|                             <label class="col-form-label label-optional" | |||
|                                    for="zip">Zip Code | |||
|                             </label> | |||
|                             <input type="text" | |||
|                                    name="zip" | |||
|                                    t-attf-class="form-control" | |||
|                                    t-att-value="'zip' in checkout and checkout['zip']"/> | |||
|                         </div> | |||
|                     </t> | |||
|                     <div t-attf-class="mb-3 col-md-8 div_city"> | |||
|                         <label class="col-form-label" | |||
|                                for="city">City | |||
|                         </label> | |||
|                         <input type="text" name="city" | |||
|                                t-attf-class="form-control #{'is-invalid' if error.get('city', '') != '' else 'valid'}" | |||
|                                t-att-value="'city' in checkout and checkout['city']"/> | |||
|                     </div> | |||
|                     <t t-if="'zip' in zip_city and zip_city.index('zip') > zip_city.index('city')"> | |||
|                         <div t-attf-class="mb-3 col-md-4 div_zip"> | |||
|                             <label class="col-form-label label-optional" | |||
|                                    for="zip">Zip Code | |||
|                             </label> | |||
|                             <input type="text" | |||
|                                    name="zip" | |||
|                                    t-attf-class="form-control" | |||
|                                    t-att-value="'zip' in checkout and checkout['zip']"/> | |||
|                         </div> | |||
|                     </t> | |||
|                     <div class="w-100"/> | |||
|                     <div t-attf-class="mb-3  and 'o_has_error' or ''} col-lg-6 div_country"> | |||
|                         <label class="col-form-label" | |||
|                                for="country_id">Country | |||
|                         </label> | |||
|                         <select id="country_id" | |||
|                                 name="country_id" | |||
|                                 t-attf-class="form-select" | |||
|                                 t-att-mode="mode[1]"> | |||
|                             <option value=""> | |||
|                                 Country... | |||
|                             </option> | |||
|                             <t t-foreach="countries" | |||
|                                t-as="c"> | |||
|                                 <option t-att-value="c.id" | |||
|                                         t-att-selected="c.id == (country and country.id or -1)"> | |||
|                                     <t t-esc="c.name"/> | |||
|                                 </option> | |||
|                             </t> | |||
|                         </select> | |||
|                     </div> | |||
|                     <div t-attf-class="mb-3 col-lg-6 div_state" | |||
|                          t-att-style="(not country or not country.state_ids) and 'display: none'"> | |||
|                         <label class="col-form-label" for="state_id"> | |||
|                             State / Province | |||
|                         </label> | |||
|                         <select name="state_id" t-attf-class="form-select" | |||
|                                 data-init="1"> | |||
|                             <option value=""> | |||
|                                 State / Province... | |||
|                             </option> | |||
|                             <t t-foreach="country_states" t-as="s"> | |||
|                                 <option t-att-value="s.id" | |||
|                                         t-att-selected="s.id == ('state_id' in checkout and country and checkout['state_id'] != '' and int(checkout['state_id']))"> | |||
|                                     <t t-esc="s.name"/> | |||
|                                 </option> | |||
|                             </t> | |||
|                         </select> | |||
|                     </div> | |||
|                     <div class="w-100"/> | |||
|                     <!-- Checkbox to choose whether to ship to the same address as billing --> | |||
|                     <t t-if="mode == ('new', 'billing') and not only_services"> | |||
|                         <div class="col-lg-12"> | |||
|                             <div class="checkbox"> | |||
|                                 <label> | |||
|                                     <input type="checkbox" | |||
|                                            id='shipping_use_same' | |||
|                                            class="mr8" | |||
|                                            name='use_same' | |||
|                                            value="1" | |||
|                                            checked='checked'/> | |||
|                                     Ship to the same | |||
|                                     address | |||
|                                     <span class='ship_to_other text-muted' | |||
|                                           style="display: none"> | |||
|                                         &nbsp;( | |||
|                                         <i>Your | |||
|                                             shipping | |||
|                                             address | |||
|                                             will be | |||
|                                             requested | |||
|                                             later) | |||
|                                         </i> | |||
|                                     </span> | |||
|                                 </label> | |||
|                             </div> | |||
|                         </div> | |||
|                     </t> | |||
|                 </div> | |||
|                 <input type="hidden" name="csrf_token" | |||
|                        t-att-value="request.csrf_token()" | |||
|                        t-nocache="The csrf token must always be up to date."/> | |||
|                 <input type="hidden" name="submitted" | |||
|                        value="1"/> | |||
|                 <input type="hidden" name="partner_id" | |||
|                        t-att-value="partner_id or '0'"/> | |||
|                 <input type="hidden" name="callback" | |||
|                        t-att-value="callback"/> | |||
|                 <input type="hidden" | |||
|                        name="field_required" | |||
|                        t-att-value="'phone,name'"/> | |||
|                 <!-- Navigation --> | |||
|                 <div class="d-flex justify-content-between" t-if="not add"> | |||
|                     <a role="button" | |||
|                        t-att-href="mode == ('new', 'billing') and '/shop/cart' or '/shop/checkout'" | |||
|                        class="btn btn-secondary mb32"> | |||
|                         <i class="fa fa-chevron-left"/> | |||
|                         <span>Back</span> | |||
|                     </a> | |||
|                     <a role="button" href="#" | |||
|                        class="btn btn-primary mb32 a-submit a-submit-disable a-submit-loading"> | |||
|                         <span>Confirm</span> | |||
|                         <i class="fa fa-chevron-right"/> | |||
|                     </a> | |||
|                 </div> | |||
|             </form> | |||
|         </div> | |||
|     </template> | |||
| </odoo> | |||
| @ -0,0 +1,73 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo> | |||
|     <template id="extra_info" name="Extra Info"> | |||
|         <form action="/website/form/shop.sale.order" method="post" | |||
|               id="extra_info_form" | |||
|               enctype="multipart/form-data" | |||
|               t-attf-class="o_mark_required s_website_form_no_recaptcha #{'block-ui' if website_sale_order.partner_id.active == False else ''}" | |||
|               data-mark="*" data-force_action="shop.sale.order" | |||
|               data-model_name="sale.order" data-success-mode="redirect" | |||
|               data-success-page="/payment/status" hide-change-model="true"> | |||
|             <!-- Create a hidden input field with name "csrf_token" and | |||
|             value from request.csrf_token() --> | |||
|             <input type="hidden" name="csrf_token" | |||
|                    t-att-value="request.csrf_token()"/> | |||
|             <div class="s_website_form_rows row s_col_no_bgcolor"> | |||
|                 <!-- Create a form field for a text input with name "client_order_ref" --> | |||
|                 <div class="mb-0 py-2 col-12 s_website_form_field" | |||
|                      data-type="char" data-name="Field"> | |||
|                     <div class="row s_col_no_resize s_col_no_bgcolor"> | |||
|                         <label class="col-form-label col-sm-auto s_website_form_label" | |||
|                                style="width: 200px" for="sale1"> | |||
|                             <span class="s_website_form_label_content"> | |||
|                                 Your Reference | |||
|                             </span> | |||
|                         </label> | |||
|                         <!-- Create a text input field with id "sale1" and | |||
|                         class "form-control s_website_form_input" --> | |||
|                         <div class="col-sm"> | |||
|                             <input id="sale1" type="text" | |||
|                                    class="form-control s_website_form_input" | |||
|                                    name="client_order_ref"/> | |||
|                         </div> | |||
|                     </div> | |||
|                 </div> | |||
|                 <div class="mb-0 py-2 col-12 s_website_form_field s_website_form_custom" | |||
|                      data-type="text" data-name="Field"> | |||
|                     <div class="row s_col_no_resize s_col_no_bgcolor"> | |||
|                         <label class="col-form-label col-sm-auto s_website_form_label" | |||
|                                style="width: 200px" for="sale2"> | |||
|                             <span class="s_website_form_label_content">Give | |||
|                                 us your feedback | |||
|                             </span> | |||
|                         </label> | |||
|                         <!-- Create a textarea input field with id "sale2" | |||
|                         and class "form-control s_website_form_input" --> | |||
|                         <div class="col-sm"> | |||
|                             <textarea id="sale2" | |||
|                                       class="form-control s_website_form_input" | |||
|                                       name="Give us your feedback"/> | |||
|                         </div> | |||
|                     </div> | |||
|                 </div> | |||
|                 <!-- Create a form field for a binary input with name "a_document" --> | |||
|                 <div class="mb-0 py-2 col-12 s_website_form_field s_website_form_custom" | |||
|                      data-type="binary" data-name="Field"> | |||
|                     <div class="row s_col_no_resize s_col_no_bgcolor"> | |||
|                         <label class="col-form-label col-sm-auto s_website_form_label" | |||
|                                style="width: 200px" for="sale3"> | |||
|                             <span class="s_website_form_label_content"> | |||
|                                 Upload a document | |||
|                             </span> | |||
|                         </label> | |||
|                         <div class="col-sm"> | |||
|                             <input id="sale3" type="file" | |||
|                                    class="form-control s_website_form_input" | |||
|                                    name="a_document"/> | |||
|                         </div> | |||
|                     </div> | |||
|                 </div> | |||
|             </div> | |||
|         </form> | |||
|     </template> | |||
| </odoo> | |||
| @ -0,0 +1,81 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo> | |||
|     <template id="payment" name="Payment"> | |||
|         <!--- Section for selecting the delivery method, which is | |||
|         only shown if there is more than one delivery option available. --> | |||
|         <div t-if="deliveries" id="delivery_carrier"> | |||
|             <t t-set="delivery_nb" t-value="len(deliveries)"/> | |||
|             <h3 t-if="delivery_nb > 1" class="mb24">Choose a | |||
|                 delivery method | |||
|             </h3> | |||
|             <div t-if="delivery_nb > 1" | |||
|                  class="card border-0" id="delivery_method"> | |||
|                 <ul class="list-group"> | |||
|                     <t t-foreach="deliveries" t-as="delivery"> | |||
|                         <li class="list-group-item o_delivery_carrier_select"> | |||
|                             <t t-call="website_sale_delivery.payment_delivery_methods"/> | |||
|                         </li> | |||
|                     </t> | |||
|                 </ul> | |||
|             </div> | |||
|         </div> | |||
|         <!-- Section for selecting the payment method, which is shown | |||
|         if there is a total amount to be paid. --> | |||
|         <div class="col-12 col-xl order-xl-1 oe_cart"> | |||
|             <div class="oe_structure clearfix mt-3" | |||
|                  id="oe_structure_website_sale_payment_1"/> | |||
|             <t t-if="website_sale_order.amount_total" > | |||
|                 <div t-if="acquirers or tokens" | |||
|                      id="payment_method" class="mt-3"> | |||
|                     <h3 class="mb24">Pay with</h3> | |||
|                     <t t-call="payment.checkout"> | |||
|                         <t t-set="footer_template_id" | |||
|                            t-value="'website_sale.payment_footer'"/> | |||
|                         <t t-set="submit_button_label">Pay | |||
|                             Now | |||
|                         </t> | |||
|                     </t> | |||
|                 </div> | |||
|                 <!-- If there are payment providers available, the user is | |||
|                 presented with the option to choose a payment method. | |||
|                 Otherwise, a message is displayed saying that no suitable | |||
|                 payment option could be found. --> | |||
|                 <div t-else="" class="alert alert-warning"> | |||
|                     <strong>No suitable payment option could be | |||
|                         found. | |||
|                     </strong> | |||
|                     <br/> | |||
|                     If you believe that it is an error, please | |||
|                     contact the website administrator. | |||
|                 </div> | |||
|             </t> | |||
|         </div> | |||
|             <div t-if="not acquirers" class="mt-2"> | |||
|                 <a role="button" class="btn-link" | |||
|                    groups="base.group_system" | |||
|                    t-attf-href="/web#action=#{payment_action_id}"> | |||
|                     <i class="fa fa-arrow-right"/> | |||
|                     Add payment providers | |||
|                 </a> | |||
|             </div> | |||
|             <div class="js_payment mt-3" | |||
|                  t-if="not website_sale_order.amount_total" | |||
|                  id="payment_method" | |||
|                  name="o_website_sale_free_cart"> | |||
|                 <form target="_self" | |||
|                       action="/shop/payment/validate" | |||
|                       method="post"> | |||
|                     <input type="hidden" name="csrf_token" | |||
|                            t-att-value="request.csrf_token()" | |||
|                            t-nocache="The csrf token must always be up to date."/> | |||
|                     <!-- If there is no amount to be paid (i.e., the cart is free), | |||
|                     a confirmation button is displayed instead of the payment methods section. --> | |||
|                     <t t-call="website_sale.payment_footer"> | |||
|                         <t t-set="submit_button_label">Confirm | |||
|                             Order | |||
|                         </t> | |||
|                     </t> | |||
|                 </form> | |||
|             </div> | |||
|     </template> | |||
| </odoo> | |||
| @ -0,0 +1,48 @@ | |||
| <?xml version="1.0" encoding="utf-8"?> | |||
| <odoo> | |||
|     <!-- This template inherits from the website_sale.payment template and | |||
|     is used for the one-page checkout payment step. --> | |||
|     <template id="one_page_checkout_payment" inherit_id="website_sale.payment"> | |||
|         <xpath expr="//div[@id='wrap']/div" position="replace"> | |||
|             <div class="row single_pg_checkout_layout"> | |||
|                 <div class='col-12'> | |||
|                     <t t-call="website_sale.wizard_checkout"> | |||
|                         <!-- This sets the step to 20 if the partner is inactive, | |||
|                         or 40 if the partner is active. --> | |||
|                         <t t-if="website_sale_order.partner_id.active == False"> | |||
|                             <t t-set="step" t-value="20"/> | |||
|                         </t> | |||
|                         <t t-else=""> | |||
|                             <t t-set="step" t-value="40"/> | |||
|                         </t> | |||
|                     </t> | |||
|                 </div> | |||
|                 <!-- This displays any errors that occur during checkout. --> | |||
|                 <div class="col-12" t-if="errors"> | |||
|                     <t t-foreach="errors" t-as="error"> | |||
|                         <div class="alert alert-danger" t-if="error" role="alert"> | |||
|                             <h4> | |||
|                                 <t t-esc="error[0]"/> | |||
|                             </h4> | |||
|                             <t t-esc="error[1]"/> | |||
|                         </div> | |||
|                     </t> | |||
|                 </div> | |||
|                 <!-- This calls the cart_summary and extra_info templates for the left column. --> | |||
|                 <div class="column"> | |||
|                     <t t-call="website_sale.cart_summary"/> | |||
|                     <t t-call="one_page_checkout.extra_info"/> | |||
|                 </div> | |||
|                 <!-- This calls the address column template for the middle column. --> | |||
|                 <div class="column"> | |||
|                     <t t-call="one_page_checkout.address_column"/> | |||
|                 </div> | |||
|                 <!-- This calls the payment template for the right column. | |||
|                 If the partner is inactive, it adds the "block-ui" class to the column. --> | |||
|                 <div t-attf-class="column #{'block-ui' if website_sale_order.partner_id.active == False else ''}"> | |||
|                     <t t-call="one_page_checkout.payment"/> | |||
|                 </div> | |||
|             </div> | |||
|         </xpath> | |||
|     </template> | |||
| </odoo> | |||