@ -0,0 +1,46 @@ | 
				
			|||
.. image:: https://img.shields.io/badge/license-LGPL--3-green.svg | 
				
			|||
    :target: https://www.gnu.org/licenses/lgpl-3.0-standalone.html | 
				
			|||
    :alt: License: LGPL-3 | 
				
			|||
 | 
				
			|||
Stock 3D View | 
				
			|||
============= | 
				
			|||
Virtual 3D Visualization of warehouses and Locations | 
				
			|||
 | 
				
			|||
Configuration | 
				
			|||
============= | 
				
			|||
The user should be added to the security group: Administrator(Inventory/ Stock) inorder to get access to the 3d view.. | 
				
			|||
 | 
				
			|||
License | 
				
			|||
------- | 
				
			|||
General Public License, Version 3 (LGPL v3). | 
				
			|||
(https://www.gnu.org/licenses/lgpl-3.0-standalone.html) | 
				
			|||
 | 
				
			|||
Company | 
				
			|||
------- | 
				
			|||
* `Cybrosys Techno Solutions <https://cybrosys.com/>`__ | 
				
			|||
 | 
				
			|||
Credits | 
				
			|||
------- | 
				
			|||
* Developers: (V16) Prasanna Kumara B, 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,23 @@ | 
				
			|||
# -*- coding: utf-8 -*- | 
				
			|||
############################################################################# | 
				
			|||
# | 
				
			|||
#    Cybrosys Technologies Pvt. Ltd. | 
				
			|||
# | 
				
			|||
#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
				
			|||
#    Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) | 
				
			|||
# | 
				
			|||
#    You can modify it under the terms of the GNU LESSER | 
				
			|||
#    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | 
				
			|||
# | 
				
			|||
#    This program is distributed in the hope that it will be useful, | 
				
			|||
#    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
				
			|||
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
				
			|||
#    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | 
				
			|||
# | 
				
			|||
#    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | 
				
			|||
#    (LGPL v3) along with this program. | 
				
			|||
#    If not, see <http://www.gnu.org/licenses/>. | 
				
			|||
# | 
				
			|||
############################################################################# | 
				
			|||
from . import controllers | 
				
			|||
from . import models | 
				
			|||
@ -0,0 +1,63 @@ | 
				
			|||
# -*- coding: utf-8 -*- | 
				
			|||
############################################################################# | 
				
			|||
# | 
				
			|||
#    Cybrosys Technologies Pvt. Ltd. | 
				
			|||
# | 
				
			|||
#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
				
			|||
#    Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) | 
				
			|||
# | 
				
			|||
#    You can modify it under the terms of the GNU LESSER | 
				
			|||
#    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | 
				
			|||
# | 
				
			|||
#    This program is distributed in the hope that it will be useful, | 
				
			|||
#    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
				
			|||
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
				
			|||
#    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | 
				
			|||
# | 
				
			|||
#    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | 
				
			|||
#    (LGPL v3) along with this program. | 
				
			|||
#    If not, see <http://www.gnu.org/licenses/>. | 
				
			|||
# | 
				
			|||
############################################################################# | 
				
			|||
{ | 
				
			|||
    'name': "Stock 3D View", | 
				
			|||
    'version': '15.0.1.0.0', | 
				
			|||
    'category': 'Warehouse', | 
				
			|||
    'summary': """Virtual 3D Visualization of warehouses and Locations""", | 
				
			|||
    'description': """This module innovative addition to the inventory and  | 
				
			|||
     warehouse management module, enhancing the traditional methods of tracking  | 
				
			|||
     stock and warehouse operations. Leveraging advanced visualization  | 
				
			|||
     technology, this app provides users with an immersive and dynamic  | 
				
			|||
     three-dimensional representation of their warehouses, inventory items, and  | 
				
			|||
     stock movements.""", | 
				
			|||
    'author': 'Cybrosys Techno Solutions', | 
				
			|||
    'company': 'Cybrosys Techno Solutions', | 
				
			|||
    'maintainer': 'Cybrosys Techno Solutions', | 
				
			|||
    'website': "https://www.cybrosys.com", | 
				
			|||
    'depends': ['stock', 'web'], | 
				
			|||
    'data': [ | 
				
			|||
        'views/stock_location_views.xml', | 
				
			|||
    ], | 
				
			|||
    'assets': { | 
				
			|||
        'web.assets_backend': [ | 
				
			|||
            '/stock_3d_view/static/src/js/form_3d_view.js', | 
				
			|||
            '/stock_3d_view/static/src/js/listview_3d.js', | 
				
			|||
            '/stock_3d_view/static/src/css/3d_view.scss', | 
				
			|||
            'https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.js', | 
				
			|||
            'https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js', | 
				
			|||
            "https://cdn.jsdelivr.net/npm/three@0.122.0/examples/js/controls/OrbitControls.min.js", | 
				
			|||
        ], | 
				
			|||
        'web.assets_qweb': [ | 
				
			|||
            'stock_3d_view/static/src/xml/stock_location_3d_templates.xml', | 
				
			|||
            'stock_3d_view/static/src/xml/stock_location_modal_templates.xml', | 
				
			|||
            'stock_3d_view/static/src/xml/stock_location_breadcrumb_templates.xml', | 
				
			|||
        ], | 
				
			|||
    }, | 
				
			|||
    'images': [ | 
				
			|||
        'static/description/banner.png', | 
				
			|||
    ], | 
				
			|||
    'license': 'LGPL-3', | 
				
			|||
    'installable': True, | 
				
			|||
    'auto_install': False, | 
				
			|||
    'application': False, | 
				
			|||
} | 
				
			|||
@ -0,0 +1,22 @@ | 
				
			|||
# -*- coding: utf-8 -*- | 
				
			|||
############################################################################# | 
				
			|||
# | 
				
			|||
#    Cybrosys Technologies Pvt. Ltd. | 
				
			|||
# | 
				
			|||
#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
				
			|||
#    Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) | 
				
			|||
# | 
				
			|||
#    You can modify it under the terms of the GNU LESSER | 
				
			|||
#    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | 
				
			|||
# | 
				
			|||
#    This program is distributed in the hope that it will be useful, | 
				
			|||
#    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
				
			|||
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
				
			|||
#    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | 
				
			|||
# | 
				
			|||
#    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | 
				
			|||
#    (LGPL v3) along with this program. | 
				
			|||
#    If not, see <http://www.gnu.org/licenses/>. | 
				
			|||
# | 
				
			|||
############################################################################# | 
				
			|||
from . import stock_3d_view | 
				
			|||
@ -0,0 +1,170 @@ | 
				
			|||
"""This module handles the requests made by js files and returns the corresponding data.""" | 
				
			|||
# -*- coding: utf-8 -*- | 
				
			|||
############################################################################# | 
				
			|||
# | 
				
			|||
#    Cybrosys Technologies Pvt. Ltd. | 
				
			|||
# | 
				
			|||
#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
				
			|||
#    Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) | 
				
			|||
# | 
				
			|||
#    You can modify it under the terms of the GNU LESSER | 
				
			|||
#    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | 
				
			|||
# | 
				
			|||
#    This program is distributed in the hope that it will be useful, | 
				
			|||
#    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
				
			|||
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
				
			|||
#    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | 
				
			|||
# | 
				
			|||
#    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | 
				
			|||
#    (LGPL v3) along with this program. | 
				
			|||
#    If not, see <http://www.gnu.org/licenses/>. | 
				
			|||
# | 
				
			|||
############################################################################# | 
				
			|||
import math | 
				
			|||
from odoo import http | 
				
			|||
from odoo.http import request | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class Stock3DView(http.Controller): | 
				
			|||
    """Class for handling the requests and responses""" | 
				
			|||
 | 
				
			|||
    @http.route('/3Dstock/warehouse', type='json', auth='public') | 
				
			|||
    def get_warehouse_data(self, company_id): | 
				
			|||
        """ | 
				
			|||
        This method is used to handle the request for warehouse data. | 
				
			|||
        ------------------------------------------------ | 
				
			|||
        @param self: object pointer. | 
				
			|||
        @param company_id: current company id. | 
				
			|||
        @return: a list of warehouses created under the active company. | 
				
			|||
        """ | 
				
			|||
        warehouse = request.env['stock.warehouse'].sudo().search([]) | 
				
			|||
        warehouse_list = [] | 
				
			|||
        warehouse_list.clear() | 
				
			|||
        for rec in warehouse: | 
				
			|||
            if rec.company_id.id == company_id: | 
				
			|||
                warehouse_list.append((rec.id, rec.name)) | 
				
			|||
        return warehouse_list | 
				
			|||
 | 
				
			|||
    @http.route('/3Dstock/data', type='json', auth='public') | 
				
			|||
    def get_stock_data(self, company_id, wh_id): | 
				
			|||
        """ | 
				
			|||
        This method is used to handle the request for location data. | 
				
			|||
        ------------------------------------------------ | 
				
			|||
        @param self: object pointer | 
				
			|||
        @param company_id: current company id. | 
				
			|||
        @param wh_id: the selected warehouse id. | 
				
			|||
        @return:a list of locations with their dimensions and positions of | 
				
			|||
                selected warehouse. | 
				
			|||
        """ | 
				
			|||
        warehouse = request.env['stock.warehouse'].sudo().search( | 
				
			|||
            [('id', '=', int(wh_id)), ('company_id', '=', int(company_id))]) | 
				
			|||
        locations = request.env['stock.location'].sudo().search( | 
				
			|||
            [('company_id', '=', int(company_id)), | 
				
			|||
             ('active', '=', 'true'), | 
				
			|||
             ('usage', '=', 'internal')]) | 
				
			|||
        location_dict = {} | 
				
			|||
        for loc in locations: | 
				
			|||
            for wh in warehouse: | 
				
			|||
                if loc.warehouse_id.id == warehouse.id: | 
				
			|||
                    if loc.id not in ( | 
				
			|||
                            wh.lot_stock_id.id, wh.wh_input_stock_loc_id.id, | 
				
			|||
                            wh.wh_qc_stock_loc_id.id, | 
				
			|||
                            wh.wh_pack_stock_loc_id.id, wh.wh_output_stock_loc_id.id): | 
				
			|||
                        length = int(loc.length * 3.779 * 2) | 
				
			|||
                        width = int(loc.width * 3.779 * 2) | 
				
			|||
                        height = int(loc.height * 3.779 * 2) | 
				
			|||
                        location_dict.update( | 
				
			|||
                            {loc.unique_code: [loc.pos_x, loc.pos_y, loc.pos_z, | 
				
			|||
                                               length, width, height]}) | 
				
			|||
 | 
				
			|||
        return location_dict | 
				
			|||
 | 
				
			|||
    @http.route('/3Dstock/data/quantity', type='json', auth='public') | 
				
			|||
    def get_stock_count_data(self, loc_code): | 
				
			|||
        """ | 
				
			|||
        This method is used to handle the request for location's current stock | 
				
			|||
        quantity. | 
				
			|||
        ------------------------------------------------ | 
				
			|||
        @param self: object pointer. | 
				
			|||
        @param loc_code: the selected location code. | 
				
			|||
        @return: current quantity of selected location. | 
				
			|||
        """ | 
				
			|||
        quantity = request.env['stock.quant'].sudo().search( | 
				
			|||
            [('location_id.unique_code', '=', loc_code)]).mapped( | 
				
			|||
            'quantity') | 
				
			|||
        capacity = request.env['stock.location'].sudo().search( | 
				
			|||
            [('unique_code', '=', loc_code)]).max_capacity | 
				
			|||
        count = math.fsum(quantity) | 
				
			|||
        quant_data = (0, 0) | 
				
			|||
        if capacity: | 
				
			|||
            if capacity > 0: | 
				
			|||
                load = int((count * 100) / capacity) | 
				
			|||
                quant_data = (capacity, load) | 
				
			|||
            else: | 
				
			|||
                if count > 0: | 
				
			|||
                    quant_data = (0, -1) | 
				
			|||
        return quant_data | 
				
			|||
 | 
				
			|||
    @http.route('/3Dstock/data/product', type='json', auth='public') | 
				
			|||
    def get_stock_product_data(self, loc_code): | 
				
			|||
        """ | 
				
			|||
        This method is used to handle the request for data of products of | 
				
			|||
        selected location. | 
				
			|||
        ------------------------------------------------ | 
				
			|||
        @param self: object pointer. | 
				
			|||
        @param loc_code: the selected location code. | 
				
			|||
        @return: a dictionary including total capacity, current capacity and | 
				
			|||
        products stored in selected location. | 
				
			|||
        """ | 
				
			|||
        products = request.env['stock.quant'].sudo().search( | 
				
			|||
            [('location_id.unique_code', '=', loc_code)]) | 
				
			|||
        quantity_obj = request.env['stock.quant'].sudo().search( | 
				
			|||
            [('location_id.unique_code', '=', loc_code)]).mapped( | 
				
			|||
            'quantity') | 
				
			|||
        capacity = request.env['stock.location'].sudo().search( | 
				
			|||
            [('unique_code', '=', loc_code)]).max_capacity | 
				
			|||
        product_list = [] | 
				
			|||
        product_list.clear() | 
				
			|||
        if products: | 
				
			|||
            for rec in products: | 
				
			|||
                product_list.append((rec.product_id.display_name, rec.quantity)) | 
				
			|||
        load = math.fsum(quantity_obj) | 
				
			|||
        if capacity > 0: | 
				
			|||
            space = capacity - load | 
				
			|||
        else: | 
				
			|||
            space = 0 | 
				
			|||
        data = { | 
				
			|||
            'capacity': capacity, | 
				
			|||
            'space': space, | 
				
			|||
            'product_list': product_list | 
				
			|||
        } | 
				
			|||
        return data | 
				
			|||
 | 
				
			|||
    @http.route('/3Dstock/data/standalone', type='json', auth='public') | 
				
			|||
    def get_standalone_stock_data(self, company_id, loc_id): | 
				
			|||
        """ | 
				
			|||
        This method is used to handle the request for individual location data. | 
				
			|||
        ------------------------------------------------ | 
				
			|||
        @param self: object pointer. | 
				
			|||
        @param company_id: the current company id. | 
				
			|||
        @param loc_id: the selected location code. | 
				
			|||
        @return: a dictionary including of selected location's dimensions and | 
				
			|||
        positions. | 
				
			|||
        """ | 
				
			|||
        warehouse = request.env['stock.location'].sudo().search( | 
				
			|||
            [('company_id.id', '=', int(company_id)), | 
				
			|||
             ('id', '=', int(loc_id))]).mapped('warehouse_id') | 
				
			|||
        locations = request.env['stock.location'].sudo().search( | 
				
			|||
            [('company_id.id', '=', int(company_id)), | 
				
			|||
             ('active', '=', 'true'), | 
				
			|||
             ('usage', '=', 'internal')]) | 
				
			|||
        location_dict = {} | 
				
			|||
        for loc in locations: | 
				
			|||
            if loc.warehouse_id.id == warehouse.id: | 
				
			|||
                length = int(loc.length * 3.779 * 2) | 
				
			|||
                width = int(loc.width * 3.779 * 2) | 
				
			|||
                height = int(loc.height * 3.779 * 2) | 
				
			|||
                location_dict.update( | 
				
			|||
                    {loc.unique_code: [loc.pos_x, loc.pos_y, loc.pos_z, | 
				
			|||
                                       length, width, height, loc.id]}) | 
				
			|||
        return location_dict | 
				
			|||
@ -0,0 +1,6 @@ | 
				
			|||
## Module <stock_3d_view> | 
				
			|||
 | 
				
			|||
#### 27.09.2023 | 
				
			|||
#### Version 15.0.1.0.0 | 
				
			|||
#### ADD | 
				
			|||
- Initial commit for Stock 3D View | 
				
			|||
@ -0,0 +1,22 @@ | 
				
			|||
# -*- coding: utf-8 -*- | 
				
			|||
############################################################################# | 
				
			|||
# | 
				
			|||
#    Cybrosys Technologies Pvt. Ltd. | 
				
			|||
# | 
				
			|||
#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
				
			|||
#    Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) | 
				
			|||
# | 
				
			|||
#    You can modify it under the terms of the GNU LESSER | 
				
			|||
#    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | 
				
			|||
# | 
				
			|||
#    This program is distributed in the hope that it will be useful, | 
				
			|||
#    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
				
			|||
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
				
			|||
#    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | 
				
			|||
# | 
				
			|||
#    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | 
				
			|||
#    (LGPL v3) along with this program. | 
				
			|||
#    If not, see <http://www.gnu.org/licenses/>. | 
				
			|||
# | 
				
			|||
############################################################################# | 
				
			|||
from . import stock_location | 
				
			|||
@ -0,0 +1,67 @@ | 
				
			|||
"""This module inherits stock.location model.""" | 
				
			|||
# -*- coding: utf-8 -*- | 
				
			|||
############################################################################# | 
				
			|||
# | 
				
			|||
#    Cybrosys Technologies Pvt. Ltd. | 
				
			|||
# | 
				
			|||
#    Copyright (C) 2023-TODAY Cybrosys Technologies(<https://www.cybrosys.com>) | 
				
			|||
#    Author: Cybrosys Techno Solutions(<https://www.cybrosys.com>) | 
				
			|||
# | 
				
			|||
#    You can modify it under the terms of the GNU LESSER | 
				
			|||
#    GENERAL PUBLIC LICENSE (LGPL v3), Version 3. | 
				
			|||
# | 
				
			|||
#    This program is distributed in the hope that it will be useful, | 
				
			|||
#    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
				
			|||
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
				
			|||
#    GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. | 
				
			|||
# | 
				
			|||
#    You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE | 
				
			|||
#    (LGPL v3) along with this program. | 
				
			|||
#    If not, see <http://www.gnu.org/licenses/>. | 
				
			|||
# | 
				
			|||
############################################################################# | 
				
			|||
from odoo import fields, models | 
				
			|||
 | 
				
			|||
 | 
				
			|||
class StockLocation(models.Model): | 
				
			|||
    """Class for adding fields to stock.location""" | 
				
			|||
    _inherit = 'stock.location' | 
				
			|||
 | 
				
			|||
    length = fields.Float(string="Length (M)", | 
				
			|||
                          help="Length of the location in meters") | 
				
			|||
    width = fields.Float(string="Width (M)", | 
				
			|||
                         help="Width of the location in meters") | 
				
			|||
    height = fields.Float(string="Height (M)", | 
				
			|||
                          help="Height of the location in meters") | 
				
			|||
    pos_x = fields.Float(string="X (in px)", | 
				
			|||
                         help="Position of the location along X-axis") | 
				
			|||
    pos_y = fields.Float(string="Y (in px)", | 
				
			|||
                         help="Position of the location along Y-axis") | 
				
			|||
    pos_z = fields.Float(string="Z (in px)", | 
				
			|||
                         help="Position of the location along Z-axis") | 
				
			|||
    unique_code = fields.Char(string="Location Code", | 
				
			|||
                              help="Unique code of the location") | 
				
			|||
    max_capacity = fields.Integer(string="Capacity (Units)", | 
				
			|||
                                  help="Maximum capacity of the location in " | 
				
			|||
                                       "terms of Units") | 
				
			|||
 | 
				
			|||
    _sql_constraints = [ | 
				
			|||
        ('unique_code', 'UNIQUE(unique_code)', | 
				
			|||
         "The location code must be unique per company !"), | 
				
			|||
    ] | 
				
			|||
 | 
				
			|||
    def action_view_location_3d_button(self): | 
				
			|||
        """ | 
				
			|||
        This method is used to handle the view_location_3d_button button action. | 
				
			|||
        ------------------------------------------------ | 
				
			|||
        @param self: object pointer. | 
				
			|||
        @return: client action with location id and company id to display. | 
				
			|||
        """ | 
				
			|||
        return { | 
				
			|||
            'type': 'ir.actions.client', | 
				
			|||
            'tag': 'open_form_3d_view', | 
				
			|||
            'context': { | 
				
			|||
                'loc_id': self.id, | 
				
			|||
                'company_id': self.company_id.id, | 
				
			|||
            } | 
				
			|||
        } | 
				
			|||
| 
		 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: 3.4 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: 60 KiB  | 
| 
		 After Width: | Height: | Size: 62 KiB  | 
| 
		 After Width: | Height: | Size: 58 KiB  | 
| 
		 After Width: | Height: | Size: 61 KiB  | 
| 
		 After Width: | Height: | Size: 82 KiB  | 
| 
		 After Width: | Height: | Size: 60 KiB  | 
| 
		 After Width: | Height: | Size: 84 KiB  | 
| 
		 After Width: | Height: | Size: 159 KiB  | 
| 
		 After Width: | Height: | Size: 195 KiB  | 
| 
		 After Width: | Height: | Size: 85 KiB  | 
| 
		 After Width: | Height: | Size: 180 KiB  | 
| 
		 After Width: | Height: | Size: 116 KiB  | 
| 
		 After Width: | Height: | Size: 130 KiB  | 
| 
		 After Width: | Height: | Size: 194 KiB  | 
| 
		 After Width: | Height: | Size: 84 KiB  | 
| 
		 After Width: | Height: | Size: 8.2 KiB  | 
@ -0,0 +1,806 @@ | 
				
			|||
<div class="container" | 
				
			|||
     style="padding: 1rem !important; margin-bottom: 1rem !important;"> | 
				
			|||
    <div class="row"> | 
				
			|||
        <div class="col-sm-12 col-md-12 col-lg-12 d-flex justify-content-between" | 
				
			|||
             style="border-bottom: 1px solid #d5d5d5;"> | 
				
			|||
            <div class="my-3"> | 
				
			|||
                <img src="./assets/icons/logo.png" | 
				
			|||
                     style="width: auto !important; height: 40px !important;"> | 
				
			|||
            </div> | 
				
			|||
            <div class="my-3 d-flex align-items-center"> | 
				
			|||
                <div | 
				
			|||
                        style="background-color: #7C7BAD !important; color: #fff !important; font-weight: 600 !important; padding: 5px 15px 8px !important; margin: 0 5px !important;"> | 
				
			|||
                    <i class="fa fa-check mr-1"></i>Community | 
				
			|||
                </div> | 
				
			|||
                <div | 
				
			|||
                        style="background-color: #875A7B !important; color: #fff !important; font-weight: 600 !important; padding: 5px 15px 8px !important; margin: 0 5px !important;"> | 
				
			|||
                    <i class="fa fa-check mr-1"></i>Enterprise | 
				
			|||
                </div> | 
				
			|||
                <div | 
				
			|||
                        style="background-color: #875A7B !important; color: #fff !important; font-weight: 600 !important; padding: 5px 15px 8px !important; margin: 0 5px !important;"> | 
				
			|||
                    <i class="fa fa-check mr-1"></i>Odoo.sh | 
				
			|||
                </div> | 
				
			|||
            </div> | 
				
			|||
        </div> | 
				
			|||
    </div> | 
				
			|||
</div> | 
				
			|||
 | 
				
			|||
<div class="container" style="padding: 0rem 1.5rem 4rem !important"> | 
				
			|||
    <div class="row" style="height: 900px !important;"> | 
				
			|||
        <div class="col-sm-12 col-md-12 col-lg-12" | 
				
			|||
             style="padding: 4rem 1rem !important; background-color: #714B67 !important; height: 600px !important; border-radius: 20px !important;"> | 
				
			|||
            <h1 | 
				
			|||
                    style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #FFFFFF !important;  font-size: 3.5rem !important; text-align: center !important;"> | 
				
			|||
                Stock 3D View | 
				
			|||
            </h1> | 
				
			|||
            <p | 
				
			|||
                    style="font-family: 'Montserrat', sans-serif !important; font-weight: 300 !important; color: #FFFFFF !important;  font-size: 1.4rem !important; text-align: center !important;"> | 
				
			|||
                Virtual 3D Visualization of Warehouses and Locations | 
				
			|||
            </p> | 
				
			|||
            <img src="assets/screenshots/hero.gif" class="img-responsive" width="100%" | 
				
			|||
                 height="auto"/> | 
				
			|||
        </div> | 
				
			|||
    </div> | 
				
			|||
 | 
				
			|||
    <div class="row"> | 
				
			|||
        <div class="col-md-12" | 
				
			|||
             style="border-bottom: 1px solid #d5d5d5 !important; margin-bottom: 2rem !important"> | 
				
			|||
            <h2 | 
				
			|||
                    style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;"> | 
				
			|||
                <i class="fa fa-compass mr-2"></i>Explore this module | 
				
			|||
            </h2> | 
				
			|||
        </div> | 
				
			|||
        <div class="col-md-6"> | 
				
			|||
            <a href="#overview" style="text-decoration: none !important;"> | 
				
			|||
                <div class="row" | 
				
			|||
                     style="background-color: #f5f2f5 !important; border-radius: 10px !important; margin: 1rem !important; padding: 1.5em !important; height: 100px !important;"> | 
				
			|||
                    <div class="col-8"> | 
				
			|||
                        <h3 | 
				
			|||
                                style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.2rem !important;"> | 
				
			|||
                            Overview</h3> | 
				
			|||
                        <p | 
				
			|||
                                style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #714B67 !important; font-size: 0.9rem !important;"> | 
				
			|||
                            Learn more about this module | 
				
			|||
                        </p> | 
				
			|||
                    </div> | 
				
			|||
                    <div class="col-4 text-right d-flex justify-content-end align-items-center"> | 
				
			|||
                        <i class="fa fa-chevron-right" | 
				
			|||
                           style="color: #714B67 !important;"></i> | 
				
			|||
                    </div> | 
				
			|||
                </div> | 
				
			|||
            </a> | 
				
			|||
        </div> | 
				
			|||
        <div class="col-md-6"> | 
				
			|||
            <a href="#configuration" style="text-decoration: none !important;"> | 
				
			|||
                <div class="row" | 
				
			|||
                     style="background-color: #f5f2f5 !important; border-radius: 10px !important; margin: 1rem !important; padding: 1.5em !important; height: 100px !important;"> | 
				
			|||
                    <div class="col-8"> | 
				
			|||
                        <h3 | 
				
			|||
                                style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.2rem !important;"> | 
				
			|||
                            Configuration</h3> | 
				
			|||
                        <p | 
				
			|||
                                style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #714B67 !important; font-size: 0.9rem !important;"> | 
				
			|||
                            View configurations for this module | 
				
			|||
                        </p> | 
				
			|||
                    </div> | 
				
			|||
                    <div class="col-4 text-right d-flex justify-content-end align-items-center"> | 
				
			|||
                        <i class="fa fa-chevron-right" | 
				
			|||
                           style="color: #714B67 !important;"></i> | 
				
			|||
                    </div> | 
				
			|||
                </div> | 
				
			|||
            </a> | 
				
			|||
        </div> | 
				
			|||
        <div class="col-md-6"> | 
				
			|||
            <a href="#features" style="text-decoration: none !important;"> | 
				
			|||
                <div class="row" | 
				
			|||
                     style="background-color: #f5f2f5 !important; border-radius: 10px !important; margin: 1rem !important; padding: 1.5em !important; height: 100px !important;"> | 
				
			|||
                    <div class="col-8"> | 
				
			|||
                        <h3 | 
				
			|||
                                style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.2rem !important;"> | 
				
			|||
                            Features</h3> | 
				
			|||
                        <p | 
				
			|||
                                style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #714B67 !important; font-size: 0.9rem !important;"> | 
				
			|||
                            View features of this module | 
				
			|||
                        </p> | 
				
			|||
                    </div> | 
				
			|||
                    <div class="col-4 text-right d-flex justify-content-end align-items-center"> | 
				
			|||
                        <i class="fa fa-chevron-right" | 
				
			|||
                           style="color: #714B67 !important;"></i> | 
				
			|||
                    </div> | 
				
			|||
                </div> | 
				
			|||
            </a> | 
				
			|||
        </div> | 
				
			|||
        <div class="col-md-6"> | 
				
			|||
            <a href="#screenshots" style="text-decoration: none !important;"> | 
				
			|||
                <div class="row" | 
				
			|||
                     style="background-color: #f5f2f5 !important; border-radius: 10px !important; margin: 1rem !important; padding: 1.5em !important; height: 100px !important;"> | 
				
			|||
                    <div class="col-8"> | 
				
			|||
                        <h3 | 
				
			|||
                                style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.2rem !important;"> | 
				
			|||
                            Screenshots</h3> | 
				
			|||
                        <p | 
				
			|||
                                style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #714B67 !important; font-size: 0.9rem !important;"> | 
				
			|||
                            See key screenshots of this module | 
				
			|||
                        </p> | 
				
			|||
                    </div> | 
				
			|||
                    <div class="col-4 text-right d-flex justify-content-end align-items-center"> | 
				
			|||
                        <i class="fa fa-chevron-right" | 
				
			|||
                           style="color: #714B67 !important;"></i> | 
				
			|||
                    </div> | 
				
			|||
                </div> | 
				
			|||
            </a> | 
				
			|||
        </div> | 
				
			|||
    </div> | 
				
			|||
 | 
				
			|||
    <div class="row" id="overview"> | 
				
			|||
        <div class="col-md-12" | 
				
			|||
             style="border-bottom: 1px solid #d5d5d5 !important; margin: 2rem 0 !important"> | 
				
			|||
            <h2 | 
				
			|||
                    style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;"> | 
				
			|||
                <i class="fa fa-pie-chart mr-2"></i>Overview | 
				
			|||
            </h2> | 
				
			|||
        </div> | 
				
			|||
 | 
				
			|||
        <div class="col-mg-12 pl-3"> | 
				
			|||
            <p | 
				
			|||
                    style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important; line-height: 30px !important;"> | 
				
			|||
                This app helps users to visualize their stock and locations | 
				
			|||
                virtually with integrated features. | 
				
			|||
                One can view and manipulate the 3D structure of a stock location | 
				
			|||
                using this app. | 
				
			|||
                Nowadays warehouse management is hard to handle manually. | 
				
			|||
                So, users can handle warehouse management virtually with the | 
				
			|||
                help of this app. | 
				
			|||
                This app visualizes a 3D view based on multiple warehouses and | 
				
			|||
                locations. | 
				
			|||
                This app enables users to view, rotate 360° and zoom multi | 
				
			|||
                warehouse locations in a 3D space. | 
				
			|||
            </p> | 
				
			|||
        </div> | 
				
			|||
    </div> | 
				
			|||
 | 
				
			|||
    <div class="row" id="configuration"> | 
				
			|||
        <div class="col-md-12" | 
				
			|||
             style="border-bottom: 1px solid #d5d5d5 !important; margin: 2rem 0 !important"> | 
				
			|||
            <h2 | 
				
			|||
                    style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;"> | 
				
			|||
                <i class="fa fa-cogs mr-2"></i>Configuration | 
				
			|||
            </h2> | 
				
			|||
        </div> | 
				
			|||
        <div class="col-md-6 pl-3 py-3 d-flex"> | 
				
			|||
            <div> | 
				
			|||
                <h4 | 
				
			|||
                        style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> | 
				
			|||
                    <i class="fa fa-laptop mr-4"></i>Hardware Requirements</h4> | 
				
			|||
                <p | 
				
			|||
                        style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> | 
				
			|||
                    RAM : 16GB or Above | 
				
			|||
                </p> | 
				
			|||
                <p | 
				
			|||
                        style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> | 
				
			|||
                    Graphics card : 4 GB additional | 
				
			|||
                </p> | 
				
			|||
                <p | 
				
			|||
                        style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> | 
				
			|||
                    Processor : Intel i5 or above, AMD Ryzen 5 or above | 
				
			|||
                </p> | 
				
			|||
            </div> | 
				
			|||
        </div> | 
				
			|||
        <div class="col-md-6 pl-3 py-3 d-flex"> | 
				
			|||
            <div> | 
				
			|||
                <h4 | 
				
			|||
                        style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> | 
				
			|||
                    <i class="fa fa-laptop mr-4"></i>Software Requirements</h4> | 
				
			|||
                <p | 
				
			|||
                        style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> | 
				
			|||
                    Web Browser capable of running WebGL: WebGL is a JavaScript | 
				
			|||
                    API, or programmable interface, for | 
				
			|||
                    drawing interactive 2D and 3D | 
				
			|||
                    graphics in web pages. WebGL connects your web browser up to | 
				
			|||
                    your device’s graphics | 
				
			|||
                    card, providing you with far more graphical processing power | 
				
			|||
                    than is available on a | 
				
			|||
                    traditional website. | 
				
			|||
                </p> | 
				
			|||
            </div> | 
				
			|||
        </div> | 
				
			|||
    </div> | 
				
			|||
 | 
				
			|||
    <div class="row" id="features"> | 
				
			|||
        <div class="col-md-12" | 
				
			|||
             style="border-bottom: 1px solid #d5d5d5 !important; margin: 2rem 0 !important"> | 
				
			|||
            <h2 | 
				
			|||
                    style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;"> | 
				
			|||
                <i class="fa fa-star mr-2"></i>Features | 
				
			|||
            </h2> | 
				
			|||
        </div> | 
				
			|||
        <div class="col-md-6 pl-3 py-3 d-flex"> | 
				
			|||
            <div> | 
				
			|||
                <img src="assets/icons/check.png"> | 
				
			|||
            </div> | 
				
			|||
            <div> | 
				
			|||
                <h4 | 
				
			|||
                        style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> | 
				
			|||
                    Multiple Warehouse Selection</h4> | 
				
			|||
                <p | 
				
			|||
                        style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> | 
				
			|||
                    Users can view 3d visualization of all locations based | 
				
			|||
                    multiple warehouses. | 
				
			|||
                </p> | 
				
			|||
            </div> | 
				
			|||
        </div> | 
				
			|||
        <div class="col-md-6 pl-3 py-3 d-flex"> | 
				
			|||
            <div> | 
				
			|||
                <img src="assets/icons/check.png"> | 
				
			|||
            </div> | 
				
			|||
            <div> | 
				
			|||
                <h4 | 
				
			|||
                        style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> | 
				
			|||
                    Location Specific 3D View</h4> | 
				
			|||
                <p | 
				
			|||
                        style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> | 
				
			|||
                    Users can view 3d visualization of individual locations as | 
				
			|||
                    highlighted in the entire warehouse. | 
				
			|||
                </p> | 
				
			|||
            </div> | 
				
			|||
        </div> | 
				
			|||
        <div class="col-md-6 pl-3 py-3 d-flex"> | 
				
			|||
            <div> | 
				
			|||
                <img src="assets/icons/check.png"> | 
				
			|||
            </div> | 
				
			|||
            <div> | 
				
			|||
                <h4 | 
				
			|||
                        style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> | 
				
			|||
                    Actual Warehouse into Virtual Warehouse</h4> | 
				
			|||
                <p | 
				
			|||
                        style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> | 
				
			|||
                    Users can enter dimension and position of a Location. | 
				
			|||
                </p> | 
				
			|||
            </div> | 
				
			|||
        </div> | 
				
			|||
        <div class="col-md-6 pl-3 py-3 d-flex"> | 
				
			|||
            <div> | 
				
			|||
                <img src="assets/icons/check.png"> | 
				
			|||
            </div> | 
				
			|||
            <div> | 
				
			|||
                <h4 | 
				
			|||
                        style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> | 
				
			|||
                    Status of each Location</h4> | 
				
			|||
                <p | 
				
			|||
                        style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> | 
				
			|||
                    Users can quickly identify the status of location like free | 
				
			|||
                    space/overloaded through their indexing | 
				
			|||
                    based on their load and capacity. | 
				
			|||
                </p> | 
				
			|||
            </div> | 
				
			|||
        </div> | 
				
			|||
        <div class="col-md-6 pl-3 py-3 d-flex"> | 
				
			|||
            <div> | 
				
			|||
                <img src="assets/icons/check.png"> | 
				
			|||
            </div> | 
				
			|||
            <div> | 
				
			|||
                <h4 | 
				
			|||
                        style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> | 
				
			|||
                    Current Stock of each Location</h4> | 
				
			|||
                <p | 
				
			|||
                        style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> | 
				
			|||
                    Users can easily get the data about current stock of each | 
				
			|||
                    location by tapping twice on them. | 
				
			|||
                </p> | 
				
			|||
            </div> | 
				
			|||
        </div> | 
				
			|||
    </div> | 
				
			|||
 | 
				
			|||
    <div class="row" id="screenshots"> | 
				
			|||
        <div class="col-md-12" | 
				
			|||
             style="border-bottom: 1px solid #d5d5d5 !important; margin: 2rem 0 !important"> | 
				
			|||
            <h2 | 
				
			|||
                    style="font-family: 'Montserrat', sans-serif !important; font-weight: 600 !important; color: #714B67 !important; font-size: 1.5rem !important;"> | 
				
			|||
                <i class="fa fa-image mr-2"></i>Screenshots | 
				
			|||
            </h2> | 
				
			|||
        </div> | 
				
			|||
        <div class="col-lg-12 my-2"> | 
				
			|||
            <h4 class="mt-2" | 
				
			|||
                style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> | 
				
			|||
                Location Form View</h4> | 
				
			|||
            <p | 
				
			|||
                    style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> | 
				
			|||
                Enter the location properties such as location Code, Capacity, | 
				
			|||
                Dimension and Position along X,Y and Z | 
				
			|||
                axis. | 
				
			|||
            </p> | 
				
			|||
            <img src="assets/screenshots/1.png" | 
				
			|||
                 class="img-responsive img-thumbnail border" width="100%" | 
				
			|||
                 height="auto"/> | 
				
			|||
        </div> | 
				
			|||
        <div class="col-lg-12 my-2"> | 
				
			|||
            <h4 class="mt-2" | 
				
			|||
                style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> | 
				
			|||
                3D View Based on Warehouses</h4> | 
				
			|||
            <p | 
				
			|||
                    style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> | 
				
			|||
                Click on the 3D button marked below to open 3D view based on | 
				
			|||
                warehouses. | 
				
			|||
            </p> | 
				
			|||
            <img src="assets/screenshots/2.png" | 
				
			|||
                 class="img-responsive img-thumbnail border" width="100%" | 
				
			|||
                 height="auto"/> | 
				
			|||
        </div> | 
				
			|||
        <div class="col-lg-12 my-2"> | 
				
			|||
            <h4 class="mt-2" | 
				
			|||
                style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> | 
				
			|||
                Multiple Warehouse Selection</h4> | 
				
			|||
            <p | 
				
			|||
                    style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> | 
				
			|||
                Users can switch to any warehouse by using the dropdown option | 
				
			|||
                highlighted below. | 
				
			|||
            </p> | 
				
			|||
            <img src="assets/screenshots/3.png" | 
				
			|||
                 class="img-responsive img-thumbnail border" width="100%" | 
				
			|||
                 height="auto"/> | 
				
			|||
        </div> | 
				
			|||
        <div class="col-lg-12 my-2"> | 
				
			|||
            <h4 class="mt-2" | 
				
			|||
                style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> | 
				
			|||
                Location Specific 3D View</h4> | 
				
			|||
            <p | 
				
			|||
                    style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> | 
				
			|||
                Please open a location and provide a proper dimension, position, | 
				
			|||
                code and parent stock. Click on the | 
				
			|||
                button "3D" located inside header. | 
				
			|||
            </p> | 
				
			|||
            <img src="assets/screenshots/4.png" | 
				
			|||
                 class="img-responsive img-thumbnail border" width="100%" | 
				
			|||
                 height="auto"/> | 
				
			|||
        </div> | 
				
			|||
        <div class="col-lg-12 my-2"> | 
				
			|||
            <h4 class="mt-2" | 
				
			|||
                style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> | 
				
			|||
                Individual Location Highlight</h4> | 
				
			|||
            <p | 
				
			|||
                    style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> | 
				
			|||
                Users can view the selected location's 3D view individually. The | 
				
			|||
                location is indexed based on its load | 
				
			|||
                and capacity. | 
				
			|||
            </p> | 
				
			|||
            <img src="assets/screenshots/5.png" | 
				
			|||
                 class="img-responsive img-thumbnail border" width="100%" | 
				
			|||
                 height="auto"/> | 
				
			|||
        </div> | 
				
			|||
        <div class="col-lg-12 my-2"> | 
				
			|||
            <h4 class="mt-2" | 
				
			|||
                style="font-family: 'Roboto', sans-serif !important; font-weight: 600 !important; color: #282F33 !important; font-size: 1.3rem !important;"> | 
				
			|||
                Get Stock Data</h4> | 
				
			|||
            <p | 
				
			|||
                    style="font-family: 'Roboto', sans-serif !important; font-weight: 400 !important; color: #282F33 !important; font-size: 1rem !important;"> | 
				
			|||
                Double tap on the location to get its stock data. | 
				
			|||
            </p> | 
				
			|||
            <img src="assets/screenshots/66.png" | 
				
			|||
                 class="img-responsive img-thumbnail border" width="100%" | 
				
			|||
                 height="auto"/> | 
				
			|||
            <br/> | 
				
			|||
            <br/> | 
				
			|||
            <img src="assets/screenshots/77.png" | 
				
			|||
                 class="img-responsive img-thumbnail border" width="100%" | 
				
			|||
                 height="auto"/> | 
				
			|||
        </div> | 
				
			|||
    </div> | 
				
			|||
 | 
				
			|||
    <!-- SUGGESTED PRODUCTS --> | 
				
			|||
    <div class="row"> | 
				
			|||
        <div class="col-lg-12 d-flex flex-column justify-content-center" | 
				
			|||
             style="text-align: center; padding: 2.5rem 1rem !important;"> | 
				
			|||
            <h2 style="color: #212529 !important;">Suggested Products</h2> | 
				
			|||
            <hr | 
				
			|||
                    style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;"/> | 
				
			|||
            <div id="demo1" class="row carousel slide" data-ride="carousel"> | 
				
			|||
                <!-- The slideshow --> | 
				
			|||
                <div class="carousel-inner"> | 
				
			|||
                    <div class="carousel-item active" style="min-height:0px"> | 
				
			|||
                        <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" | 
				
			|||
                             style="float:left"> | 
				
			|||
                            <a href="https://apps.odoo.com/apps/modules/15.0/export_stockinfo_xls/" | 
				
			|||
                               target="_blank"> | 
				
			|||
                                <div style="border-radius:10px"> | 
				
			|||
                                    <img class="img img-responsive center-block" | 
				
			|||
                                         style="border-top-left-radius:10px; border-top-right-radius:10px" | 
				
			|||
                                         src="./assets/modules/module_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/stock_intercompany_transfer/" | 
				
			|||
                               target="_blank"> | 
				
			|||
                                <div style="border-radius:10px"> | 
				
			|||
                                    <img class="img img-responsive center-block" | 
				
			|||
                                         style="border-top-left-radius:10px; border-top-right-radius:10px" | 
				
			|||
                                         src="./assets/modules/module_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/product_brand_inventory/" | 
				
			|||
                               target="_blank"> | 
				
			|||
                                <div style="border-radius:10px"> | 
				
			|||
                                    <img class="img img-responsive center-block" | 
				
			|||
                                         style="border-top-left-radius:10px; border-top-right-radius:10px" | 
				
			|||
                                         src="./assets/modules/module_3.png"> | 
				
			|||
                                </div> | 
				
			|||
                            </a> | 
				
			|||
                        </div> | 
				
			|||
                    </div> | 
				
			|||
                    <div class="carousel-item" style="min-height:0px"> | 
				
			|||
                        <div class="col-xs-12 col-sm-4 col-md-4 mb16 mt16" | 
				
			|||
                             style="float:left"> | 
				
			|||
                            <a href="https://apps.odoo.com/apps/modules/15.0/product_batch_report/" | 
				
			|||
                               target="_blank"> | 
				
			|||
                                <div style="border-radius:10px"> | 
				
			|||
                                    <img class="img img-responsive center-block" | 
				
			|||
                                         style="border-top-left-radius:10px; border-top-right-radius:10px" | 
				
			|||
                                         src="./assets/modules/module_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/merge_picking_orders/" | 
				
			|||
                               target="_blank"> | 
				
			|||
                                <div style="border-radius:10px"> | 
				
			|||
                                    <img class="img img-responsive center-block" | 
				
			|||
                                         style="border-top-left-radius:10px; border-top-right-radius:10px" | 
				
			|||
                                         src="./assets/modules/module_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/stock_valuation_report/" | 
				
			|||
                               target="_blank"> | 
				
			|||
                                <div style="border-radius:10px"> | 
				
			|||
                                    <img class="img img-responsive center-block" | 
				
			|||
                                         style="border-top-left-radius:10px; border-top-right-radius:10px" | 
				
			|||
                                         src="./assets/modules/module_6.png"> | 
				
			|||
                                </div> | 
				
			|||
                            </a> | 
				
			|||
                        </div> | 
				
			|||
                    </div> | 
				
			|||
                </div> | 
				
			|||
                <!-- Left and right controls --> | 
				
			|||
                <a class="carousel-control-prev" href="#demo1" data-slide="prev" | 
				
			|||
                   style="left:-25px;width: 35px;color: #000;"> | 
				
			|||
                    <span class="carousel-control-prev-icon"><i | 
				
			|||
                            class="fa fa-chevron-left" | 
				
			|||
                            style="font-size:24px"></i></span> | 
				
			|||
                </a> | 
				
			|||
                <a class="carousel-control-next" href="#demo1" data-slide="next" | 
				
			|||
                   style="right:-25px;width: 35px;color: #000;"> | 
				
			|||
                    <span class="carousel-control-next-icon"><i | 
				
			|||
                            class="fa fa-chevron-right" | 
				
			|||
                            style="font-size:24px"></i></span> | 
				
			|||
                </a> | 
				
			|||
            </div> | 
				
			|||
        </div> | 
				
			|||
    </div> | 
				
			|||
    <!-- END OF SUGGESTED PRODUCTS --> | 
				
			|||
 | 
				
			|||
    <!-- OUR SERVICES --> | 
				
			|||
    <section class="container" style="margin-top: 6rem !important;"> | 
				
			|||
        <div class="row"> | 
				
			|||
            <div class="col-lg-12 d-flex flex-column justify-content-center align-items-center"> | 
				
			|||
                <h2 style="color: #212529 !important;">Our Services</h2> | 
				
			|||
                <hr | 
				
			|||
                        style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;"/> | 
				
			|||
            </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: #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> | 
				
			|||
    </section> | 
				
			|||
    <!-- END OF OUR SERVICES --> | 
				
			|||
 | 
				
			|||
    <!-- OUR INDUSTRIES --> | 
				
			|||
    <section class="container" style="margin-top: 6rem !important;"> | 
				
			|||
        <div class="row"> | 
				
			|||
            <div class="col-lg-12 d-flex flex-column justify-content-center align-items-center"> | 
				
			|||
                <h2 style="color: #212529 !important;">Our Industries</h2> | 
				
			|||
                <hr | 
				
			|||
                        style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;"/> | 
				
			|||
            </div> | 
				
			|||
 | 
				
			|||
            <div class="col-lg-3"> | 
				
			|||
                <div class="my-4 d-flex flex-column justify-content-center" | 
				
			|||
                     style="background-color: #f6f8f9 !important; border-radius: 10px; 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: 10px; 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: 10px; 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: 10px; 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: 10px; 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: 10px; 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: 10px; 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: 10px; 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> | 
				
			|||
    </section> | 
				
			|||
 | 
				
			|||
    <!-- END OF OUR INDUSTRIES --> | 
				
			|||
 | 
				
			|||
    <!-- FOOTER --> | 
				
			|||
    <!-- Footer Section --> | 
				
			|||
    <section class="container" style="margin: 5rem auto 2rem;"> | 
				
			|||
        <div class="row" style="max-width:1540px;"> | 
				
			|||
            <div class="col-lg-12 d-flex flex-column justify-content-center align-items-center"> | 
				
			|||
                <h2 style="color: #212529 !important;">Need Help?</h2> | 
				
			|||
                <hr | 
				
			|||
                        style="border: 3px solid #714B67 !important; background-color: #714B67 !important; width: 80px !important; margin-bottom: 2rem !important;"/> | 
				
			|||
            </div> | 
				
			|||
        </div> | 
				
			|||
 | 
				
			|||
        <!-- Contact Cards --> | 
				
			|||
        <div class="row d-flex justify-content-center align-items-center" | 
				
			|||
             style="max-width:1540px; margin: 0 auto 2rem auto;"> | 
				
			|||
 | 
				
			|||
            <div class="col-lg-12" | 
				
			|||
                 style="padding: 0rem 3rem 2rem; border-radius: 10px; margin-right: 3rem; "> | 
				
			|||
 | 
				
			|||
                <div class="row mt-4"> | 
				
			|||
                    <div class="col-lg-6"> | 
				
			|||
                        <a href="mailto:odoo@cybrosys.com" target="_blank" | 
				
			|||
                           class="btn btn-block mb-2 deep_hover" | 
				
			|||
                           style="text-decoration: none;  background-color: #4d4d4d; color: #FFF;  border-radius: 4px;"> | 
				
			|||
                            <i class="fa fa-envelope mr-2"></i>odoo@cybrosys.com | 
				
			|||
                        </a> | 
				
			|||
                    </div> | 
				
			|||
                    <div class="col-lg-6"> | 
				
			|||
                        <a href="https://api.whatsapp.com/send?phone=918606827707" | 
				
			|||
                           target="_blank" | 
				
			|||
                           class="btn btn-block mb-2 deep_hover" | 
				
			|||
                           style="text-decoration: none;  background-color: #25D366; color: #FFF;  border-radius: 4px;"> | 
				
			|||
                            <i class="fa fa-whatsapp mr-2"></i>WhatsApp | 
				
			|||
                        </a> | 
				
			|||
                    </div> | 
				
			|||
                </div> | 
				
			|||
            </div> | 
				
			|||
 | 
				
			|||
        </div> | 
				
			|||
        <!-- End of Contact Cards --> | 
				
			|||
    </section> | 
				
			|||
    <!-- Footer --> | 
				
			|||
    <section class="oe_container" style="padding: 2rem 3rem 1rem;"> | 
				
			|||
        <div class="row" | 
				
			|||
             style="max-width:1540px; margin: 0 auto; margin-right: 3rem; "> | 
				
			|||
            <!-- Logo --> | 
				
			|||
            <div class="col-lg-12 d-flex justify-content-center align-items-center" | 
				
			|||
                 style="margin-top: 3rem;"> | 
				
			|||
                <img src="https://www.cybrosys.com/images/logo.png" | 
				
			|||
                     width="200px" height="auto"/> | 
				
			|||
            </div> | 
				
			|||
            <!-- End of Logo --> | 
				
			|||
            <div class="col-lg-12"> | 
				
			|||
                <hr | 
				
			|||
                        style="margin-top: 3rem;background: linear-gradient(90deg, rgba(2,0,36,0) 0%, rgba(229,229,229,1) 33%, rgba(229,229,229,1) 58%, rgba(0,212,255,0) 100%); height: 2px; border-style: none;"> | 
				
			|||
                <!-- End of Footer Section --> | 
				
			|||
            </div> | 
				
			|||
        </div> | 
				
			|||
    </section> | 
				
			|||
    <!-- END OF FOOTER --> | 
				
			|||
 | 
				
			|||
</div> | 
				
			|||
@ -0,0 +1,125 @@ | 
				
			|||
canvas { | 
				
			|||
  border: 7px solid #666666; | 
				
			|||
  background-color: white; | 
				
			|||
  position: relative; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.customselect{ | 
				
			|||
bottom: 744px; | 
				
			|||
left: 44px; | 
				
			|||
height: 25px; | 
				
			|||
width: 150px; | 
				
			|||
position: absolute; | 
				
			|||
color: indigo; | 
				
			|||
font-size: 15px; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
 | 
				
			|||
.rectangle { | 
				
			|||
bottom: 650px; | 
				
			|||
right: 7px; | 
				
			|||
  height: 140px; | 
				
			|||
  width: 180px; | 
				
			|||
  position: absolute; | 
				
			|||
 | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.square1 { | 
				
			|||
  height: 20px; | 
				
			|||
  width: 20px; | 
				
			|||
  background-color: #cc0000; | 
				
			|||
  border-radius: 5px; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.squareText1 { | 
				
			|||
  height: 20px; | 
				
			|||
  width: 170px; | 
				
			|||
  color: black; | 
				
			|||
  margin-top: -19px; | 
				
			|||
  padding-left: 30px; | 
				
			|||
  font-weight: 600; | 
				
			|||
  font-size: 13px; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.square2 { | 
				
			|||
  height: 20px; | 
				
			|||
  width: 20px; | 
				
			|||
  background-color: #e6b800; | 
				
			|||
  border-radius: 5px; | 
				
			|||
  margin-top: 2px; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.squareText2 { | 
				
			|||
  height: 20px; | 
				
			|||
  width: 170px; | 
				
			|||
  color: black; | 
				
			|||
  margin-top: -19px; | 
				
			|||
  padding-left: 30px; | 
				
			|||
  font-weight: 600; | 
				
			|||
  font-size: 13px; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.square3 { | 
				
			|||
  height: 20px; | 
				
			|||
  width: 20px; | 
				
			|||
  background-color: #00802b; | 
				
			|||
  border-radius: 5px; | 
				
			|||
  margin-top: 2px; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.squareText3 { | 
				
			|||
  height: 20px; | 
				
			|||
  width: 170px; | 
				
			|||
  color: black; | 
				
			|||
  margin-top: -19px; | 
				
			|||
  padding-left: 30px; | 
				
			|||
  font-weight: 600; | 
				
			|||
  font-size: 13px; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.square4 { | 
				
			|||
  height: 20px; | 
				
			|||
  width: 20px; | 
				
			|||
  background-color: #8c8c8c; | 
				
			|||
  border-radius: 5px; | 
				
			|||
  margin-top: 2px; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.square4blue { | 
				
			|||
  height: 20px; | 
				
			|||
  width: 20px; | 
				
			|||
  background-color: #0066ff; | 
				
			|||
  border-radius: 5px; | 
				
			|||
  margin-top: 2px; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.squareText4 { | 
				
			|||
  height: 20px; | 
				
			|||
  width: 170px; | 
				
			|||
  color: black; | 
				
			|||
  margin-top: -19px; | 
				
			|||
  padding-left: 30px; | 
				
			|||
  font-weight: 600; | 
				
			|||
  font-size: 13px; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.closeBtn { | 
				
			|||
    bottom: 759px; | 
				
			|||
    left: 10px; | 
				
			|||
  font-size: 33px; | 
				
			|||
  font-weight: 600; | 
				
			|||
  position: absolute; | 
				
			|||
  color: indigo; | 
				
			|||
  background: transparent; | 
				
			|||
  border: none; | 
				
			|||
   outline: none; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.closeBtn:focus { | 
				
			|||
    outline: 0 !important; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
.closeBtn:hover { | 
				
			|||
  animation: pulse 1s; | 
				
			|||
  box-shadow: 0 0 0 2em rgba(#fff,0); | 
				
			|||
} | 
				
			|||
@ -0,0 +1,387 @@ | 
				
			|||
odoo.define('stock_3d_view.action_open_form_3d_view', function(require) { | 
				
			|||
	'use strict'; | 
				
			|||
	var AbstractAction = require('web.AbstractAction'); | 
				
			|||
	var core = require('web.core'); | 
				
			|||
	var rpc = require('web.rpc'); | 
				
			|||
	var QWeb = core.qweb; | 
				
			|||
	var Dialog = require('web.Dialog'); | 
				
			|||
	var ajax = require('web.ajax'); | 
				
			|||
	var PositionDialog = Dialog.extend({ | 
				
			|||
		/** | 
				
			|||
		 * Initializes the PositionDialog instance. | 
				
			|||
		 * | 
				
			|||
		 * @constructor | 
				
			|||
		 * @param {Object} parent - The parent object. | 
				
			|||
		 * @param {Object} options - Configuration options. | 
				
			|||
		 * @param {Object} options.pointer - The pointer object. | 
				
			|||
		 * @param {Function} options.close - Callback function for closing the dialog. | 
				
			|||
		 */ | 
				
			|||
		init: function(parent, options) { | 
				
			|||
			var opt = options; | 
				
			|||
			this._super(...arguments) | 
				
			|||
			this.pointer = opt.pointer | 
				
			|||
			this.onClickClose = opt.close | 
				
			|||
		}, | 
				
			|||
		/** | 
				
			|||
		 * Renders the element and sets its position. | 
				
			|||
		 * | 
				
			|||
		 */ | 
				
			|||
		renderElement: function() { | 
				
			|||
			this._super() | 
				
			|||
			this.$modal.find('.modal-dialog').css({ | 
				
			|||
				position: 'absolute', | 
				
			|||
				left: this.pointer.x, | 
				
			|||
				top: this.pointer.y, | 
				
			|||
			}) | 
				
			|||
		} | 
				
			|||
	}) | 
				
			|||
	//Extends abstract action class to add event listener for 3D button.
 | 
				
			|||
	var open_form_3d_view = AbstractAction.extend({ | 
				
			|||
		template: 'Location3DFormView', | 
				
			|||
		events: _.extend({}, AbstractAction.prototype.events, { | 
				
			|||
			'click .breadcrumb-item a': 'onBreadcrumbClick' | 
				
			|||
		}), | 
				
			|||
		/** | 
				
			|||
		 * Handles the click event on breadcrumbs. | 
				
			|||
		 * | 
				
			|||
		 * @param {Event} ev - The click event object. | 
				
			|||
		 */ | 
				
			|||
		onBreadcrumbClick: function(ev) { | 
				
			|||
			let jsId = this.$(ev.target).attr('jsId'); | 
				
			|||
			this.actionService.restore(jsId); | 
				
			|||
		}, | 
				
			|||
		/** | 
				
			|||
		 * Initializes the open_form_3d_view instance. | 
				
			|||
		 * | 
				
			|||
		 * @constructor | 
				
			|||
		 * @param {Object} parent - The parent object. | 
				
			|||
		 * @param {Object} action - The action configuration. | 
				
			|||
		 */ | 
				
			|||
		init: function(parent, action) { | 
				
			|||
			this._super(...arguments) | 
				
			|||
			this.breadcrumbs = parent.wowlEnv.config.breadcrumbs | 
				
			|||
			this.actionService = parent.actionService; | 
				
			|||
		}, | 
				
			|||
		/** | 
				
			|||
		 * Starts the open_form_3d_view action. | 
				
			|||
		 */ | 
				
			|||
		start: function() { | 
				
			|||
			this.Open3DView(); | 
				
			|||
		}, | 
				
			|||
		/** | 
				
			|||
		 * Starts the process of displaying rendered 3D object of stock.location. | 
				
			|||
		 */ | 
				
			|||
		Open3DView: function() { | 
				
			|||
			var self = this; | 
				
			|||
			var wh_data; | 
				
			|||
			var data; | 
				
			|||
			var loc_quant; | 
				
			|||
			let controls, renderer, clock, scene, camera, pointer, raycaster; | 
				
			|||
			var mesh, group; | 
				
			|||
			var material; | 
				
			|||
			var loc_color; | 
				
			|||
			var loc_opacity = 0.5; | 
				
			|||
			var textSize; | 
				
			|||
			let selectedObject = null; | 
				
			|||
			var dialogs = null; | 
				
			|||
			var wh_id; | 
				
			|||
			var location_id = self.searchModel.config.context.loc_id || localStorage.getItem("location_id"); | 
				
			|||
			//sets location_id and company_id in local storage
 | 
				
			|||
			if (self.searchModel.config.context.loc_id != null) { | 
				
			|||
				localStorage.setItem("location_id", self.searchModel.config.context.loc_id); | 
				
			|||
				localStorage.setItem("company_id", self.searchModel.config.context.company_id); | 
				
			|||
			} | 
				
			|||
 | 
				
			|||
			var colorDiv = document.createElement("div"); | 
				
			|||
			colorDiv.classList.add("rectangle"); | 
				
			|||
			var color1 = document.createElement("div"); | 
				
			|||
			color1.classList.add("square1"); | 
				
			|||
			colorDiv.appendChild(color1); | 
				
			|||
			var colorText1 = document.createElement("div"); | 
				
			|||
			colorText1.classList.add("squareText1"); | 
				
			|||
			colorText1.innerHTML = "Overload"; | 
				
			|||
			colorDiv.appendChild(colorText1); | 
				
			|||
			var color2 = document.createElement("div"); | 
				
			|||
			color2.classList.add("square2"); | 
				
			|||
			colorDiv.appendChild(color2); | 
				
			|||
			var colorText2 = document.createElement("div"); | 
				
			|||
			colorText2.classList.add("squareText2"); | 
				
			|||
			colorText2.innerHTML = "Almost Full"; | 
				
			|||
			colorDiv.appendChild(colorText2); | 
				
			|||
			var color3 = document.createElement("div"); | 
				
			|||
			color3.classList.add("square3"); | 
				
			|||
			colorDiv.appendChild(color3); | 
				
			|||
			var colorText3 = document.createElement("div"); | 
				
			|||
			colorText3.classList.add("squareText3"); | 
				
			|||
			colorText3.innerHTML = "Free Space Available"; | 
				
			|||
			colorDiv.appendChild(colorText3); | 
				
			|||
			var color4 = document.createElement("div"); | 
				
			|||
			color4.classList.add("square4blue"); | 
				
			|||
			colorDiv.appendChild(color4); | 
				
			|||
			var colorText4 = document.createElement("div"); | 
				
			|||
			colorText4.classList.add("squareText4"); | 
				
			|||
			colorText4.innerHTML = "No Product/Load"; | 
				
			|||
			colorDiv.appendChild(colorText4); | 
				
			|||
 | 
				
			|||
			start(); | 
				
			|||
			/** | 
				
			|||
			 * The complete working of fetching data from stock.location and displaying them in the form of 3d objects. | 
				
			|||
			 * | 
				
			|||
			 * @async | 
				
			|||
			 */ | 
				
			|||
			async function start() { | 
				
			|||
				/** | 
				
			|||
				 * Make a jsonRpc call to fetch location details. | 
				
			|||
				 * | 
				
			|||
				 * @await | 
				
			|||
				 * @param {integer} company_id | 
				
			|||
				 * @param {integer} loc_id | 
				
			|||
				 */ | 
				
			|||
				await ajax.jsonRpc('/3Dstock/data/standalone', 'call', { | 
				
			|||
					'company_id': self.searchModel.config.context.company_id || localStorage.getItem("company_id"), | 
				
			|||
					'loc_id': self.searchModel.config.context.loc_id || localStorage.getItem("location_id"), | 
				
			|||
				}).then(function(incoming_data) { | 
				
			|||
					data = incoming_data; | 
				
			|||
				}); | 
				
			|||
				//creating a new three.scene
 | 
				
			|||
				scene = new THREE.Scene(); | 
				
			|||
				scene.background = new THREE.Color(0xdfdfdf); | 
				
			|||
				clock = new THREE.Clock(); | 
				
			|||
				camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.5, 6000); | 
				
			|||
				camera.position.set(0, 200, 300) | 
				
			|||
				renderer = new THREE.WebGLRenderer({ | 
				
			|||
					antialias: true | 
				
			|||
				}); | 
				
			|||
				//setting size and pixel ratio for the renderer.
 | 
				
			|||
				renderer.setSize(window.innerWidth, window.innerHeight / 1.163); | 
				
			|||
				renderer.setPixelRatio(window.devicePixelRatio); | 
				
			|||
				renderer.render(scene, camera); | 
				
			|||
				var o_content = self.$('.o_content') | 
				
			|||
				o_content.append(renderer.domElement); | 
				
			|||
				self.$el.find('.o_content').append(colorDiv); | 
				
			|||
				controls = new THREE.OrbitControls(camera, renderer.domElement); | 
				
			|||
				const baseGeometry = new THREE.BoxGeometry(800, 0, 800); | 
				
			|||
				const baseMaterial = new THREE.MeshBasicMaterial({ | 
				
			|||
					color: 0xffffff, | 
				
			|||
					transparent: false, | 
				
			|||
					opacity: 1, | 
				
			|||
					side: THREE.FrontSide, | 
				
			|||
				}); | 
				
			|||
				const baseCube = new THREE.Mesh(baseGeometry, baseMaterial); | 
				
			|||
				scene.add(baseCube); | 
				
			|||
				group = new THREE.Group(); | 
				
			|||
				//traversing through each location object
 | 
				
			|||
				for (let [key, value] of Object.entries(data)) { | 
				
			|||
					//checks if the dimension values of the location are non zero
 | 
				
			|||
					if ((value[0] > 0) || (value[1] > 0) || (value[2] > 0) || (value[3] > 0) || (value[4] > 0) || (value[5] > 0)) { | 
				
			|||
						const geometry = new THREE.BoxGeometry(value[3], value[5], value[4]); | 
				
			|||
						geometry.translate(0, (value[5] / 2), 0); | 
				
			|||
						const edges = new THREE.EdgesGeometry(geometry); | 
				
			|||
						/** | 
				
			|||
						 * Make a jsonRpc call to fetch the stock details of particular location. | 
				
			|||
						 * | 
				
			|||
						 * @await | 
				
			|||
						 * @param {integer} loc_code | 
				
			|||
						 */ | 
				
			|||
						await ajax.jsonRpc('/3Dstock/data/quantity', 'call', { | 
				
			|||
							'loc_code': key, | 
				
			|||
						}).then(function(quant_data) { | 
				
			|||
							loc_quant = quant_data; | 
				
			|||
						}); | 
				
			|||
						//checking the quantity and capacity of the location to determine the color of the location
 | 
				
			|||
						if (localStorage.getItem("location_id") == value[6]) { | 
				
			|||
							if (loc_quant[0] > 0) { | 
				
			|||
								if (loc_quant[1] > 100) { | 
				
			|||
									loc_color = 0xcc0000; | 
				
			|||
									loc_opacity = 0.8; | 
				
			|||
								} else if (loc_quant[1] > 50) { | 
				
			|||
									loc_color = 0xe6b800; | 
				
			|||
									loc_opacity = 0.8; | 
				
			|||
								} else { | 
				
			|||
									loc_color = 0x00802b; | 
				
			|||
									loc_opacity = 0.8; | 
				
			|||
								} | 
				
			|||
							} else { | 
				
			|||
								if (loc_quant[1] == -1) { | 
				
			|||
									loc_color = 0x00802b; | 
				
			|||
									loc_opacity = 0.8; | 
				
			|||
								} else { | 
				
			|||
									loc_color = 0x0066ff; | 
				
			|||
									loc_opacity = 0.8; | 
				
			|||
								} | 
				
			|||
							} | 
				
			|||
						} else { | 
				
			|||
							loc_color = 0x8c8c8c; | 
				
			|||
							loc_opacity = 0.5; | 
				
			|||
						} | 
				
			|||
						//creating a 3D box geometry for each location
 | 
				
			|||
						material = new THREE.MeshBasicMaterial({ | 
				
			|||
							color: loc_color, | 
				
			|||
							transparent: true, | 
				
			|||
							opacity: loc_opacity | 
				
			|||
						}); | 
				
			|||
						mesh = new THREE.Mesh(geometry, material); | 
				
			|||
						const line = new THREE.LineSegments(edges, new THREE.LineBasicMaterial({ | 
				
			|||
							color: 0x404040 | 
				
			|||
						})); | 
				
			|||
						line.position.x = value[0]; | 
				
			|||
						line.position.y = value[1]; | 
				
			|||
						line.position.z = value[2]; | 
				
			|||
						mesh.position.x = value[0]; | 
				
			|||
						mesh.position.y = value[1]; | 
				
			|||
						mesh.position.z = value[2]; | 
				
			|||
						const loader = new THREE.FontLoader(); | 
				
			|||
						loader.load('https://threejs.org/examples/fonts/droid/droid_sans_bold.typeface.json', function(font) { | 
				
			|||
							const textcolor = 0x000000; | 
				
			|||
							const textMat = new THREE.MeshBasicMaterial({ | 
				
			|||
								color: textcolor, | 
				
			|||
								side: THREE.DoubleSide, | 
				
			|||
							}); | 
				
			|||
							const textmessage = key; | 
				
			|||
							if (value[3] > value[4]) { | 
				
			|||
								textSize = (value[4] / 2) - (value[4] / 2.9); | 
				
			|||
							} else { | 
				
			|||
								textSize = (value[3] / 2) - (value[3] / 2.9); | 
				
			|||
							} | 
				
			|||
							const textshapes = font.generateShapes(textmessage, textSize); | 
				
			|||
							const textgeometry = new THREE.ShapeGeometry(textshapes); | 
				
			|||
							textgeometry.translate(0, ((value[5] / 2) - (textSize / (textSize - 1.5))), 0); | 
				
			|||
							const text = new THREE.Mesh(textgeometry, textMat); | 
				
			|||
							if (value[4] > value[3]) { | 
				
			|||
								text.rotation.y = Math.PI / 2; | 
				
			|||
								text.position.x = value[0]; | 
				
			|||
								text.position.y = value[1]; | 
				
			|||
								text.position.z = value[2] + (textSize * 2) + ((value[3] / 3.779 / 2) / 2) + (textSize / 2); | 
				
			|||
							} else { | 
				
			|||
								text.position.x = value[0] - (textSize * 2) - ((value[4] / 3.779 / 2) / 2) - (textSize / 2); | 
				
			|||
								text.position.y = value[1]; | 
				
			|||
								text.position.z = value[2]; | 
				
			|||
							} | 
				
			|||
							scene.add(text); | 
				
			|||
						}); | 
				
			|||
						scene.add(mesh); | 
				
			|||
						scene.add(line); | 
				
			|||
						mesh.name = key; | 
				
			|||
						mesh.userData = { | 
				
			|||
							color: loc_color, | 
				
			|||
							loc_id: value[6], | 
				
			|||
						}; | 
				
			|||
						group.add(mesh); | 
				
			|||
					} | 
				
			|||
				} | 
				
			|||
				scene.add(group); | 
				
			|||
				raycaster = new THREE.Raycaster(); | 
				
			|||
				pointer = new THREE.Vector3(); | 
				
			|||
				animate(); | 
				
			|||
			} | 
				
			|||
			/** | 
				
			|||
			 * Handles the resizing and setting the pixel ration on window resize. | 
				
			|||
			 */ | 
				
			|||
			function onWindowResize() { | 
				
			|||
				camera.aspect = window.innerWidth / window.innerHeight; | 
				
			|||
				camera.updateProjectionMatrix(); | 
				
			|||
				renderer.setSize(window.innerWidth, window.innerHeight / 1.163); | 
				
			|||
			} | 
				
			|||
			/** | 
				
			|||
			 * Animates and renders the three.renderer object to make changes on the scene. | 
				
			|||
			 */ | 
				
			|||
			function animate() { | 
				
			|||
				requestAnimationFrame(animate); | 
				
			|||
				const delta = clock.getDelta(); | 
				
			|||
				renderer.render(scene, camera); | 
				
			|||
				var canvas = document.getElementsByTagName("canvas")[0]; | 
				
			|||
				var colorBox = document.querySelector(".rectangle"); | 
				
			|||
				//checking the canvas element adding event listener on canvas.
 | 
				
			|||
				if (canvas == null) { | 
				
			|||
					window.removeEventListener('dblclick', onPointerMove); | 
				
			|||
					window.removeEventListener('resize', onWindowResize); | 
				
			|||
					if (colorBox) { | 
				
			|||
						colorBox.style.display = "none"; | 
				
			|||
					} | 
				
			|||
				} else { | 
				
			|||
					window.addEventListener('dblclick', onPointerMove); | 
				
			|||
					window.addEventListener('resize', onWindowResize); | 
				
			|||
					if (colorBox) { | 
				
			|||
						colorBox.style.display = "block"; | 
				
			|||
					} | 
				
			|||
				} | 
				
			|||
			} | 
				
			|||
			/** | 
				
			|||
			 * gets the coordinates of the mouse point and checks for any objects. | 
				
			|||
			 * | 
				
			|||
			 * @async | 
				
			|||
			 * @param {object} event | 
				
			|||
			 */ | 
				
			|||
			async function onPointerMove(event) { | 
				
			|||
				var products; | 
				
			|||
				var button; | 
				
			|||
				if (dialogs == null) { | 
				
			|||
					if (selectedObject) { | 
				
			|||
						selectedObject.material.color.set(selectedObject.userData.color); | 
				
			|||
						selectedObject = null; | 
				
			|||
					} else { | 
				
			|||
						pointer.x = (event.clientX / window.innerWidth) * 2 - 1; | 
				
			|||
						pointer.y = -(event.clientY / (window.innerHeight)) * 2 + 1 + 0.13; | 
				
			|||
						raycaster.setFromCamera(pointer, camera); | 
				
			|||
						const intersects = raycaster.intersectObject(group, true); | 
				
			|||
						if (intersects.length > 0) { | 
				
			|||
							const res = intersects.filter(function(res) { | 
				
			|||
								return res && res.object; | 
				
			|||
							})[0]; | 
				
			|||
							if (res && res.object) { | 
				
			|||
								if (res.object.userData.loc_id == location_id) { | 
				
			|||
									/** | 
				
			|||
									 * Make a jsonRpc call to fetch the details of products and their quantity of selected location. | 
				
			|||
									 * | 
				
			|||
									 * @await | 
				
			|||
									 * @param {integer} loc_code | 
				
			|||
									 */ | 
				
			|||
									await ajax.jsonRpc('/3Dstock/data/product', 'call', { | 
				
			|||
										'loc_code': res.object.name, | 
				
			|||
									}).then(function(product_data) { | 
				
			|||
										products = product_data; | 
				
			|||
									}); | 
				
			|||
									selectedObject = res.object; | 
				
			|||
									selectedObject.material.color.set(0x00ffcc); | 
				
			|||
 | 
				
			|||
									function onClickClose() { | 
				
			|||
										if (selectedObject) { | 
				
			|||
											selectedObject.material.color.set(selectedObject.userData.color); | 
				
			|||
											selectedObject = null; | 
				
			|||
											dialogs.close(); | 
				
			|||
											dialogs = null; | 
				
			|||
										} | 
				
			|||
									} | 
				
			|||
									//opens a new dialogbox with proeduct and quantity details
 | 
				
			|||
									dialogs = new PositionDialog(this, { | 
				
			|||
										title: ('Location: ' + res.object.name), | 
				
			|||
										size: 'small', | 
				
			|||
										$content: $(QWeb.render('ViewLocationData', { | 
				
			|||
											data: products, | 
				
			|||
										})), | 
				
			|||
										placement: 'bottom', | 
				
			|||
										renderFooter: false, | 
				
			|||
										pointer: { | 
				
			|||
											x: event.clientX, | 
				
			|||
											y: event.clientY, | 
				
			|||
										}, | 
				
			|||
										close: onClickClose, | 
				
			|||
									}).open(); | 
				
			|||
 | 
				
			|||
									if (dialogs) { | 
				
			|||
										window.addEventListener('click', onClickClose); | 
				
			|||
									} else { | 
				
			|||
										window.removeEventListener('click', onClickClose); | 
				
			|||
									} | 
				
			|||
								} | 
				
			|||
							} | 
				
			|||
						} | 
				
			|||
					} | 
				
			|||
				} | 
				
			|||
			} | 
				
			|||
		} | 
				
			|||
 | 
				
			|||
	}); | 
				
			|||
	core.action_registry.add("open_form_3d_view", open_form_3d_view); | 
				
			|||
	return open_form_3d_view; | 
				
			|||
}); | 
				
			|||
@ -0,0 +1,412 @@ | 
				
			|||
odoo.define('button_near_create.tree_button', function(require) { | 
				
			|||
	"use strict"; | 
				
			|||
	var ListController = require('web.ListController'); | 
				
			|||
	var ListView = require('web.ListView'); | 
				
			|||
	var viewRegistry = require('web.view_registry'); | 
				
			|||
	var core = require('web.core'); | 
				
			|||
	var session = require('web.session'); | 
				
			|||
	var Dialog = require('web.Dialog'); | 
				
			|||
	var QWeb = core.qweb; | 
				
			|||
	var rpc = require('web.rpc'); | 
				
			|||
	var ajax = require('web.ajax'); | 
				
			|||
	var PositionDialog = Dialog.extend({ | 
				
			|||
		/** | 
				
			|||
		 * Initialize the PositionDialog. | 
				
			|||
		 * | 
				
			|||
		 * @param {Object} parent - The parent object. | 
				
			|||
		 * @param {Object} options - Dialog options. | 
				
			|||
		 * @param {Object} pointer - Object containing x and y coordinates. | 
				
			|||
		 * @param {Function} close - Function to be called on dialog close. | 
				
			|||
		 */ | 
				
			|||
		init: function(parent, options) { | 
				
			|||
			var opt = options; | 
				
			|||
			this._super(...arguments) | 
				
			|||
			this.pointer = opt.pointer | 
				
			|||
			this.onClickClose = opt.close | 
				
			|||
		}, | 
				
			|||
		/** | 
				
			|||
		 * Render the PositionDialog element. | 
				
			|||
		 * Set the dialog's position based on the provided coordinates. | 
				
			|||
		 */ | 
				
			|||
		renderElement: function() { | 
				
			|||
			this._super() | 
				
			|||
			this.$modal.find('.modal-dialog').css({ | 
				
			|||
				position: 'absolute', | 
				
			|||
				left: this.pointer.x, | 
				
			|||
				top: this.pointer.y, | 
				
			|||
			}) | 
				
			|||
		} | 
				
			|||
	}) | 
				
			|||
	//Extends list controller class to add event listener for 3D button.
 | 
				
			|||
	var TreeButton = ListController.extend({ | 
				
			|||
		buttons_template: 'StockLocationListView.buttons', | 
				
			|||
		events: _.extend({}, ListController.prototype.events, { | 
				
			|||
			'click .open_3d_view': '_Open3DView', | 
				
			|||
		}), | 
				
			|||
		/** | 
				
			|||
		 * Starts the process of displaying rendered 3D object of stock.location. | 
				
			|||
		 */ | 
				
			|||
		_Open3DView: async function(ev) { | 
				
			|||
			var self = this; | 
				
			|||
			var wh_data; | 
				
			|||
			var data; | 
				
			|||
			var loc_quant; | 
				
			|||
			let controls, renderer, clock, scene, camera, pointer, raycaster; | 
				
			|||
			var mesh, group; | 
				
			|||
			var material; | 
				
			|||
			var loc_color; | 
				
			|||
			var loc_opacity = 0.5; | 
				
			|||
			var textSize; | 
				
			|||
			let selectedObject = null; | 
				
			|||
			var dialogs = null; | 
				
			|||
			var wh_id; | 
				
			|||
			/** | 
				
			|||
			 * Make a jsonRpc call to fetch available warehouses and list it in the dropdown. | 
				
			|||
			 * | 
				
			|||
			 * @await | 
				
			|||
			 * @param {integer} company_id | 
				
			|||
			 */ | 
				
			|||
			await ajax.jsonRpc('/3Dstock/warehouse', 'call', { | 
				
			|||
				'company_id': session.user_context.allowed_company_ids[0], | 
				
			|||
			}).then(function(incoming_data) { | 
				
			|||
				wh_data = incoming_data; | 
				
			|||
			}); | 
				
			|||
			wh_id = wh_data[0][0]; | 
				
			|||
			var select = document.createElement("select"); | 
				
			|||
			select.name = "mySelect"; | 
				
			|||
			for (let i = 0; i < wh_data.length; i++) { | 
				
			|||
				var option = document.createElement("option"); | 
				
			|||
				option.value = wh_data[i][0]; | 
				
			|||
				option.text = wh_data[i][1]; | 
				
			|||
				select.appendChild(option); | 
				
			|||
				select.classList.add("customselect"); | 
				
			|||
			} | 
				
			|||
 | 
				
			|||
			var closeDiv = document.createElement("button"); | 
				
			|||
			closeDiv.classList.add("closeBtn"); | 
				
			|||
			closeDiv.innerHTML = "×" | 
				
			|||
			var colorDiv = document.createElement("div"); | 
				
			|||
			colorDiv.classList.add("rectangle"); | 
				
			|||
			var color1 = document.createElement("div"); | 
				
			|||
			color1.classList.add("square1"); | 
				
			|||
			colorDiv.appendChild(color1); | 
				
			|||
			var colorText1 = document.createElement("div"); | 
				
			|||
			colorText1.classList.add("squareText1"); | 
				
			|||
			colorText1.innerHTML = "Overload"; | 
				
			|||
			colorDiv.appendChild(colorText1); | 
				
			|||
			var color2 = document.createElement("div"); | 
				
			|||
			color2.classList.add("square2"); | 
				
			|||
			colorDiv.appendChild(color2); | 
				
			|||
			var colorText2 = document.createElement("div"); | 
				
			|||
			colorText2.classList.add("squareText2"); | 
				
			|||
			colorText2.innerHTML = "Almost Full"; | 
				
			|||
			colorDiv.appendChild(colorText2); | 
				
			|||
			var color3 = document.createElement("div"); | 
				
			|||
			color3.classList.add("square3"); | 
				
			|||
			colorDiv.appendChild(color3); | 
				
			|||
			var colorText3 = document.createElement("div"); | 
				
			|||
			colorText3.classList.add("squareText3"); | 
				
			|||
			colorText3.innerHTML = "Free Space Available"; | 
				
			|||
			colorDiv.appendChild(colorText3); | 
				
			|||
			var color4 = document.createElement("div"); | 
				
			|||
			color4.classList.add("square4"); | 
				
			|||
			colorDiv.appendChild(color4); | 
				
			|||
			var colorText4 = document.createElement("div"); | 
				
			|||
			colorText4.classList.add("squareText4"); | 
				
			|||
			colorText4.innerHTML = "No Product/Load"; | 
				
			|||
			colorDiv.appendChild(colorText4); | 
				
			|||
 | 
				
			|||
			start(); | 
				
			|||
			/** | 
				
			|||
			 * The complete working of fetching data from stock.location and displaying them in the form of 3d objects. | 
				
			|||
			 * | 
				
			|||
			 * @async | 
				
			|||
			 */ | 
				
			|||
			async function start() { | 
				
			|||
				/** | 
				
			|||
				 * Make a jsonRpc call to fetch location details of corresponding warehouse. | 
				
			|||
				 * | 
				
			|||
				 * @await | 
				
			|||
				 * @param {integer} company_id | 
				
			|||
				 * @param {integer} wh_id | 
				
			|||
				 */ | 
				
			|||
				await ajax.jsonRpc('/3Dstock/data', 'call', { | 
				
			|||
					'company_id': session.user_context.allowed_company_ids[0], | 
				
			|||
					'wh_id': wh_id, | 
				
			|||
				}).then(function(incoming_data) { | 
				
			|||
					data = incoming_data; | 
				
			|||
				}); | 
				
			|||
				scene = new THREE.Scene(); | 
				
			|||
				scene.background = new THREE.Color(0xdfdfdf); | 
				
			|||
				clock = new THREE.Clock(); | 
				
			|||
				camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.5, 6000); | 
				
			|||
				camera.position.set(0, 200, 300) | 
				
			|||
				renderer = new THREE.WebGLRenderer({ | 
				
			|||
					antialias: true | 
				
			|||
				}); | 
				
			|||
				renderer.setSize(window.innerWidth, window.innerHeight / 1.164); | 
				
			|||
				renderer.setPixelRatio(window.devicePixelRatio); | 
				
			|||
				renderer.render(scene, camera); | 
				
			|||
				self.$el.find('.o_content').html(renderer.domElement); | 
				
			|||
				self.$el.find('.o_content').append(select); | 
				
			|||
				self.$el.find('.o_content').append(colorDiv); | 
				
			|||
				self.$el.find('.o_content').append(closeDiv); | 
				
			|||
				var dropdown = document.querySelector(".customselect"); | 
				
			|||
				if (dropdown) { | 
				
			|||
					dropdown.addEventListener("change", warehouseChange); | 
				
			|||
				} | 
				
			|||
				var closeBtn = document.querySelector(".closeBtn"); | 
				
			|||
				if (closeBtn) { | 
				
			|||
					closeBtn.addEventListener("click", onWindowClose); | 
				
			|||
				} | 
				
			|||
				controls = new THREE.OrbitControls(camera, renderer.domElement); | 
				
			|||
				const baseGeometry = new THREE.BoxGeometry(800, 0, 800); | 
				
			|||
				const baseMaterial = new THREE.MeshBasicMaterial({ | 
				
			|||
					color: 0xffffff, | 
				
			|||
					transparent: false, | 
				
			|||
					opacity: 1, | 
				
			|||
					side: THREE.BackSide, | 
				
			|||
				}); | 
				
			|||
				const baseCube = new THREE.Mesh(baseGeometry, baseMaterial); | 
				
			|||
				scene.add(baseCube); | 
				
			|||
				group = new THREE.Group(); | 
				
			|||
				//traversing through each location object
 | 
				
			|||
				for (let [key, value] of Object.entries(data)) { | 
				
			|||
					//checks if the dimension values of the location are non zero
 | 
				
			|||
					if ((value[0] > 0) || (value[1] > 0) || (value[2] > 0) || (value[3] > 0) || (value[4] > 0) || (value[5] > 0)) { | 
				
			|||
						const geometry = new THREE.BoxGeometry(value[3], value[5], value[4]); | 
				
			|||
						geometry.translate(0, (value[5] / 2), 0); | 
				
			|||
						const edges = new THREE.EdgesGeometry(geometry); | 
				
			|||
						/** | 
				
			|||
						 * Make a jsonRpc call to fetch the stock details of particular location. | 
				
			|||
						 * | 
				
			|||
						 * @await | 
				
			|||
						 * @param {integer} loc_code | 
				
			|||
						 */ | 
				
			|||
						await ajax.jsonRpc('/3Dstock/data/quantity', 'call', { | 
				
			|||
							'loc_code': key, | 
				
			|||
						}).then(function(quant_data) { | 
				
			|||
							loc_quant = quant_data; | 
				
			|||
						}); | 
				
			|||
						//checking the quantity and capacity of the location to determine the color of the location
 | 
				
			|||
						if (loc_quant[0] > 0) { | 
				
			|||
							if (loc_quant[1] > 100) { | 
				
			|||
								loc_color = 0xcc0000; | 
				
			|||
								loc_opacity = 0.8; | 
				
			|||
							} else if (loc_quant[1] > 50) { | 
				
			|||
								loc_color = 0xe6b800; | 
				
			|||
								loc_opacity = 0.8; | 
				
			|||
							} else { | 
				
			|||
								loc_color = 0x00802b; | 
				
			|||
								loc_opacity = 0.8; | 
				
			|||
							} | 
				
			|||
						} else { | 
				
			|||
							if (loc_quant[1] == -1) { | 
				
			|||
								loc_color = 0x00802b; | 
				
			|||
								loc_opacity = 0.8; | 
				
			|||
							} else { | 
				
			|||
								loc_color = 0x8c8c8c; | 
				
			|||
								loc_opacity = 0.5; | 
				
			|||
							} | 
				
			|||
						} | 
				
			|||
						//creating a 3D box geometry for each location
 | 
				
			|||
						material = new THREE.MeshBasicMaterial({ | 
				
			|||
							color: loc_color, | 
				
			|||
							transparent: true, | 
				
			|||
							opacity: loc_opacity | 
				
			|||
						}); | 
				
			|||
						mesh = new THREE.Mesh(geometry, material); | 
				
			|||
						const line = new THREE.LineSegments(edges, new THREE.LineBasicMaterial({ | 
				
			|||
							color: 0x404040 | 
				
			|||
						})); | 
				
			|||
						line.position.x = value[0]; | 
				
			|||
						line.position.y = value[1]; | 
				
			|||
						line.position.z = value[2]; | 
				
			|||
						mesh.position.x = value[0]; | 
				
			|||
						mesh.position.y = value[1]; | 
				
			|||
						mesh.position.z = value[2]; | 
				
			|||
						const loader = new THREE.FontLoader(); | 
				
			|||
						loader.load('https://threejs.org/examples/fonts/droid/droid_sans_bold.typeface.json', function(font) { | 
				
			|||
							const textcolor = 0x000000; | 
				
			|||
							const textMat = new THREE.MeshBasicMaterial({ | 
				
			|||
								color: textcolor, | 
				
			|||
								side: THREE.DoubleSide, | 
				
			|||
							}); | 
				
			|||
							const textmessage = key; | 
				
			|||
							if (value[3] > value[4]) { | 
				
			|||
								textSize = (value[4] / 2) - (value[4] / 2.9); | 
				
			|||
							} else { | 
				
			|||
								textSize = (value[3] / 2) - (value[3] / 2.9); | 
				
			|||
							} | 
				
			|||
							const textshapes = font.generateShapes(textmessage, textSize); | 
				
			|||
							const textgeometry = new THREE.ShapeGeometry(textshapes); | 
				
			|||
							textgeometry.translate(0, ((value[5] / 2) - (textSize / (textSize - 1.5))), 0); | 
				
			|||
							const text = new THREE.Mesh(textgeometry, textMat); | 
				
			|||
							if (value[4] > value[3]) { | 
				
			|||
								text.rotation.y = Math.PI / 2; | 
				
			|||
								text.position.x = value[0]; | 
				
			|||
								text.position.y = value[1]; | 
				
			|||
								text.position.z = value[2] + (textSize * 2) + ((value[3] / 3.779 / 2) / 2) + (textSize / 2); | 
				
			|||
							} else { | 
				
			|||
								text.position.x = value[0] - (textSize * 2) - ((value[4] / 3.779 / 2) / 2) - (textSize / 2); | 
				
			|||
								text.position.y = value[1]; | 
				
			|||
								text.position.z = value[2]; | 
				
			|||
							} | 
				
			|||
							scene.add(text); | 
				
			|||
						}); | 
				
			|||
						scene.add(mesh); | 
				
			|||
						scene.add(line); | 
				
			|||
						mesh.name = key; | 
				
			|||
						mesh.userData = { | 
				
			|||
							color: loc_color | 
				
			|||
						}; | 
				
			|||
						group.add(mesh); | 
				
			|||
					} | 
				
			|||
				} | 
				
			|||
				scene.add(group); | 
				
			|||
				raycaster = new THREE.Raycaster(); | 
				
			|||
				pointer = new THREE.Vector3(); | 
				
			|||
 | 
				
			|||
				animate(); | 
				
			|||
			} | 
				
			|||
			/** | 
				
			|||
			 * Triggered when users change warehouse and calls the start() function with the latest warehouse id. | 
				
			|||
			 */ | 
				
			|||
			function warehouseChange() { | 
				
			|||
				var selectedBox = document.querySelector(".customselect"); | 
				
			|||
				var selectValue = selectedBox.value; | 
				
			|||
				wh_id = selectValue; | 
				
			|||
				start(); | 
				
			|||
			} | 
				
			|||
			/** | 
				
			|||
			 * Handles the resizing and setting the pixel ration on window resize. | 
				
			|||
			 */ | 
				
			|||
			function onWindowResize() { | 
				
			|||
				camera.aspect = window.innerWidth / window.innerHeight; | 
				
			|||
				camera.updateProjectionMatrix(); | 
				
			|||
				renderer.setSize(window.innerWidth, window.innerHeight / 1.164); | 
				
			|||
			} | 
				
			|||
			/** | 
				
			|||
			 * Triggered when user clicks on close button. | 
				
			|||
			 */ | 
				
			|||
			function onWindowClose() { | 
				
			|||
				window.location.reload(); | 
				
			|||
			} | 
				
			|||
			/** | 
				
			|||
			 * Animates and renders the three.renderer object to make changes on the scene. | 
				
			|||
			 */ | 
				
			|||
			function animate() { | 
				
			|||
				requestAnimationFrame(animate); | 
				
			|||
				const delta = clock.getDelta(); | 
				
			|||
				renderer.render(scene, camera); | 
				
			|||
				var canvas = document.getElementsByTagName("canvas")[0]; | 
				
			|||
				var selectedBox = document.querySelector(".customselect"); | 
				
			|||
				var colorBox = document.querySelector(".rectangle"); | 
				
			|||
				var closeDiv = document.querySelector(".closeBtn"); | 
				
			|||
				//checking the canvas element adding event listener on canvas.
 | 
				
			|||
				if (canvas == null) { | 
				
			|||
					window.removeEventListener('dblclick', onPointerMove); | 
				
			|||
					window.removeEventListener('resize', onWindowResize); | 
				
			|||
					if (selectedBox) { | 
				
			|||
						selectedBox.style.display = "none"; | 
				
			|||
					} | 
				
			|||
					if (colorBox) { | 
				
			|||
						colorBox.style.display = "none"; | 
				
			|||
					} | 
				
			|||
					if (closeDiv) { | 
				
			|||
						closeDiv.style.display = "none"; | 
				
			|||
					} | 
				
			|||
				} else { | 
				
			|||
					window.addEventListener('dblclick', onPointerMove); | 
				
			|||
					window.addEventListener('resize', onWindowResize); | 
				
			|||
					if (selectedBox) { | 
				
			|||
						selectedBox.style.display = "block"; | 
				
			|||
					} | 
				
			|||
					if (colorBox) { | 
				
			|||
						colorBox.style.display = "block"; | 
				
			|||
					} | 
				
			|||
					if (closeDiv) { | 
				
			|||
						closeDiv.style.display = "block"; | 
				
			|||
					} | 
				
			|||
				} | 
				
			|||
			} | 
				
			|||
			/** | 
				
			|||
			 * gets the coordinates of the mouse point and checks for any objects. | 
				
			|||
			 * | 
				
			|||
			 * @async | 
				
			|||
			 * @param {object} event | 
				
			|||
			 */ | 
				
			|||
			async function onPointerMove(event) { | 
				
			|||
				var products; | 
				
			|||
				var button; | 
				
			|||
				if (dialogs == null) { | 
				
			|||
					if (selectedObject) { | 
				
			|||
						selectedObject.material.color.set(selectedObject.userData.color); | 
				
			|||
						selectedObject = null; | 
				
			|||
					} else { | 
				
			|||
						pointer.x = (event.clientX / window.innerWidth) * 2 - 1; | 
				
			|||
						pointer.y = -(event.clientY / (window.innerHeight)) * 2 + 1 + 0.13; | 
				
			|||
						raycaster.setFromCamera(pointer, camera); | 
				
			|||
						const intersects = raycaster.intersectObject(group, true); | 
				
			|||
						if (intersects.length > 0) { | 
				
			|||
							const res = intersects.filter(function(res) { | 
				
			|||
								return res && res.object; | 
				
			|||
							})[0]; | 
				
			|||
							if (res && res.object) { | 
				
			|||
								/** | 
				
			|||
								 * Make a jsonRpc call to fetch the details of products and their quantity of selected location. | 
				
			|||
								 * | 
				
			|||
								 * @await | 
				
			|||
								 * @param {integer} loc_code | 
				
			|||
								 */ | 
				
			|||
								await ajax.jsonRpc('/3Dstock/data/product', 'call', { | 
				
			|||
									'loc_code': res.object.name, | 
				
			|||
								}).then(function(product_data) { | 
				
			|||
									products = product_data; | 
				
			|||
								}); | 
				
			|||
								selectedObject = res.object; | 
				
			|||
								selectedObject.material.color.set(0x00ffcc); | 
				
			|||
 | 
				
			|||
								function onClickClose() { | 
				
			|||
									if (selectedObject) { | 
				
			|||
										selectedObject.material.color.set(selectedObject.userData.color); | 
				
			|||
										selectedObject = null; | 
				
			|||
										dialogs.close(); | 
				
			|||
										dialogs = null; | 
				
			|||
									} | 
				
			|||
								} | 
				
			|||
								//opens a new dialogbox with proeduct and quantity details
 | 
				
			|||
								dialogs = new PositionDialog(this, { | 
				
			|||
									title: ('Location: ' + res.object.name), | 
				
			|||
									size: 'small', | 
				
			|||
									$content: $(QWeb.render('ViewLocationData', { | 
				
			|||
										data: products, | 
				
			|||
									})), | 
				
			|||
									placement: 'bottom', | 
				
			|||
									renderFooter: false, | 
				
			|||
									pointer: { | 
				
			|||
										x: event.clientX, | 
				
			|||
										y: event.clientY, | 
				
			|||
									}, | 
				
			|||
									close: onClickClose, | 
				
			|||
								}).open(); | 
				
			|||
 | 
				
			|||
								if (dialogs) { | 
				
			|||
									window.addEventListener('click', onClickClose); | 
				
			|||
								} else { | 
				
			|||
									window.removeEventListener('click', onClickClose); | 
				
			|||
								} | 
				
			|||
							} | 
				
			|||
						} | 
				
			|||
					} | 
				
			|||
				} | 
				
			|||
			} | 
				
			|||
		} | 
				
			|||
	}); | 
				
			|||
	var StockLocationTreeView = ListView.extend({ | 
				
			|||
		config: _.extend({}, ListView.prototype.config, { | 
				
			|||
			Controller: TreeButton, | 
				
			|||
		}), | 
				
			|||
	}); | 
				
			|||
	viewRegistry.add('3d_button_in_stock', StockLocationTreeView); | 
				
			|||
}); | 
				
			|||
@ -0,0 +1,12 @@ | 
				
			|||
<?xml version="1.0" encoding="UTF-8"?> | 
				
			|||
<templates> | 
				
			|||
    <!--extending listview button template to add 3D action button--> | 
				
			|||
    <t t-extend="ListView.buttons" t-name="StockLocationListView.buttons"> | 
				
			|||
        <t t-jquery="button.o_list_button_add" t-operation="after"> | 
				
			|||
            <button type="button" class="btn btn-primary fa fa-lg fa-cubes open_3d_view" | 
				
			|||
                    style="margin-left: 3px; margin-right: 3px;"> | 
				
			|||
                3D | 
				
			|||
            </button> | 
				
			|||
        </t> | 
				
			|||
    </t> | 
				
			|||
</templates> | 
				
			|||
@ -0,0 +1,30 @@ | 
				
			|||
<?xml version="1.0" encoding="utf-8" ?> | 
				
			|||
<template> | 
				
			|||
    <!--adding breadcrumbs manually in stock.location form view.--> | 
				
			|||
    <t t-name="Location3DFormView"> | 
				
			|||
        <div class="o_action"> | 
				
			|||
            <div class="o_control_panel"> | 
				
			|||
                <div class="o_cp_top"> | 
				
			|||
                    <div class="o_cp_top_left"> | 
				
			|||
                        <t t-slot="control-panel-top-left"> | 
				
			|||
                            <ol class="breadcrumb"> | 
				
			|||
                                <t t-foreach="widget.breadcrumbs" t-as="breadcrumb"> | 
				
			|||
                                    <li class="breadcrumb-item"> | 
				
			|||
                                        <a href="#" t-att-jsId="breadcrumb.jsId"> | 
				
			|||
                                            <t t-esc="breadcrumb.name"/> | 
				
			|||
                                        </a> | 
				
			|||
                                    </li> | 
				
			|||
                                </t> | 
				
			|||
                                <li class="breadcrumb-item active"> | 
				
			|||
                                    <span class="text-muted">3D view</span> | 
				
			|||
                                </li> | 
				
			|||
                            </ol> | 
				
			|||
                        </t> | 
				
			|||
                    </div> | 
				
			|||
                </div> | 
				
			|||
                <div class="o_cp_bottom"/> | 
				
			|||
            </div> | 
				
			|||
            <div class="o_content"/> | 
				
			|||
        </div> | 
				
			|||
    </t> | 
				
			|||
</template> | 
				
			|||
@ -0,0 +1,41 @@ | 
				
			|||
<?xml version="1.0" encoding="UTF-8" ?> | 
				
			|||
<templates xml:space="preserve"> | 
				
			|||
<!--template to display location details such as product and its quantity--> | 
				
			|||
    <div t-name="ViewLocationData"> | 
				
			|||
        <t t-if="data['capacity'] > 0"> | 
				
			|||
            <center><h6>Total Capacity: <span t-esc="data['capacity']"/> Units</h6></center> | 
				
			|||
            <center><h6>Available Space: <span t-esc="data['space']"/> Units</h6></center> | 
				
			|||
        </t> | 
				
			|||
        <t t-if="data['product_list'].length > 0"> | 
				
			|||
        <table> | 
				
			|||
            <thead> | 
				
			|||
                <tr> | 
				
			|||
                    <th>#</th> | 
				
			|||
                    <th style="padding-left: 10px;">Product</th> | 
				
			|||
                    <th style="padding-left: 10px;">Quantity</th> | 
				
			|||
                </tr> | 
				
			|||
            </thead> | 
				
			|||
            <tbody> | 
				
			|||
                <t t-set="num" t-value="1"/> | 
				
			|||
                <t t-foreach="data['product_list']" t-as="i"> | 
				
			|||
                    <tr> | 
				
			|||
                        <td> | 
				
			|||
                            <span t-esc="num"/> | 
				
			|||
                        </td> | 
				
			|||
                        <td style="padding-left: 10px;"> | 
				
			|||
                            <span t-esc="i['0']"/> | 
				
			|||
                        </td> | 
				
			|||
                        <td style="padding-left: 10px;"> | 
				
			|||
                            <span t-esc="i['1']"/> | 
				
			|||
                        </td> | 
				
			|||
                    </tr> | 
				
			|||
                    <t t-set="num" t-value="num + 1"/> | 
				
			|||
                </t> | 
				
			|||
            </tbody> | 
				
			|||
        </table> | 
				
			|||
        </t> | 
				
			|||
        <t t-else=""> | 
				
			|||
            <center><span>No Products Stored Here..!</span></center> | 
				
			|||
        </t> | 
				
			|||
    </div> | 
				
			|||
</templates> | 
				
			|||
@ -0,0 +1,75 @@ | 
				
			|||
<?xml version="1.0" encoding="UTF-8" ?> | 
				
			|||
<odoo> | 
				
			|||
    <record id="view_location_form" model="ir.ui.view"> | 
				
			|||
        <field name="name">stock.location.view.form.inherit.stock_3d_view | 
				
			|||
        </field> | 
				
			|||
        <field name="model">stock.location</field> | 
				
			|||
        <field name="inherit_id" ref="stock.view_location_form"/> | 
				
			|||
        <field name="arch" type="xml"> | 
				
			|||
            <!--adding a 3D button in stock.location form view.--> | 
				
			|||
            <xpath expr="//sheet" position="before"> | 
				
			|||
                <header> | 
				
			|||
                    <button type="object" name="action_view_location_3d_button" | 
				
			|||
                            string="3D" id="view_location_3d_button" | 
				
			|||
                            class="btn btn-primary fa fa-lg fa-cubes" | 
				
			|||
                            attrs="{'invisible':['|',('location_id', '=', False),('length','=',0),('width','=',0)]}"/> | 
				
			|||
                </header> | 
				
			|||
            </xpath> | 
				
			|||
            <!--adding location dimension fields in stock.location form view.--> | 
				
			|||
            <xpath expr="//sheet" position="inside"> | 
				
			|||
                <notebook> | 
				
			|||
                    <page string="3D Properties" | 
				
			|||
                          attrs="{'invisible': [('usage', '!=', 'internal')]}"> | 
				
			|||
                        <group> | 
				
			|||
                            <group string="Dimension"> | 
				
			|||
                                <field name="length" | 
				
			|||
                                       attrs="{'required': [('usage', '=', 'internal')]}"/> | 
				
			|||
                                <field name="width" | 
				
			|||
                                       attrs="{'required': [('usage', '=', 'internal')]}"/> | 
				
			|||
                                <field name="height" | 
				
			|||
                                       attrs="{'required': [('usage', '=', 'internal')]}"/> | 
				
			|||
                            </group> | 
				
			|||
                            <group string="Position"> | 
				
			|||
                                <field name="pos_x" | 
				
			|||
                                       attrs="{'required': [('usage', '=', 'internal')]}"/> | 
				
			|||
                                <field name="pos_y" | 
				
			|||
                                       attrs="{'required': [('usage', '=', 'internal')]}"/> | 
				
			|||
                                <field name="pos_z" | 
				
			|||
                                       attrs="{'required': [('usage', '=', 'internal')]}"/> | 
				
			|||
                            </group> | 
				
			|||
                        </group> | 
				
			|||
                    </page> | 
				
			|||
                </notebook> | 
				
			|||
            </xpath> | 
				
			|||
            <!--adding unique code field of the location inside the stock.location form view.--> | 
				
			|||
            <xpath expr="//field[@name='usage']" position="after"> | 
				
			|||
                <field name="unique_code" | 
				
			|||
                       attrs="{'invisible': [('usage', '!=', 'internal')], 'required': [('usage', '=', 'internal')]}"/> | 
				
			|||
            </xpath> | 
				
			|||
            <!--adding maximum capacity field of the location inside the stock.location form view.--> | 
				
			|||
            <xpath expr="//field[@name='storage_category_id']" position="after"> | 
				
			|||
                <field name="max_capacity" | 
				
			|||
                       attrs="{'invisible': [('usage', '!=', 'internal')]}"/> | 
				
			|||
            </xpath> | 
				
			|||
        </field> | 
				
			|||
    </record> | 
				
			|||
    <!--client action for 3d view of locations.--> | 
				
			|||
    <record id="stock_location_3d_action" model="ir.actions.client"> | 
				
			|||
        <field name="name">Location 3D View</field> | 
				
			|||
        <field name="tag">open_form_3d_view</field> | 
				
			|||
    </record> | 
				
			|||
    <data> | 
				
			|||
        <!--adding button to open 3d view in stock.location tree view--> | 
				
			|||
        <record id="view_location_tree2" model="ir.ui.view"> | 
				
			|||
            <field name="name">stock.location.view.tree.inherit.stock_3d_view | 
				
			|||
            </field> | 
				
			|||
            <field name="model">stock.location</field> | 
				
			|||
            <field name="inherit_id" ref="stock.view_location_tree2"/> | 
				
			|||
            <field name="arch" type="xml"> | 
				
			|||
                <xpath expr="//tree" position="attributes"> | 
				
			|||
                    <attribute name="js_class">3d_button_in_stock</attribute> | 
				
			|||
                </xpath> | 
				
			|||
            </field> | 
				
			|||
        </record> | 
				
			|||
    </data> | 
				
			|||
</odoo> | 
				
			|||