diff --git a/inventory_stock_dashboard_odoo/README.rst b/inventory_stock_dashboard_odoo/README.rst new file mode 100644 index 000000000..76dcf16f3 --- /dev/null +++ b/inventory_stock_dashboard_odoo/README.rst @@ -0,0 +1,47 @@ +.. 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 + +Inventory Dashboard Odoo 18 +=========================== +Dashboard for Inventory module. + +Configuration +============= +No additional configurations needed. + +Company +------- +* `Cybrosys Techno Solutions `__ + +License +------- +Lesser General Public License, Version 3 (LGPL v3) +(https://www.gnu.org/licenses/lgpl-3.0-standalone.html) + +Credits +------- +* Developer : (V18) Renu + 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 `__ + +Further information +=================== +HTML Description: ``__ diff --git a/inventory_stock_dashboard_odoo/__init__.py b/inventory_stock_dashboard_odoo/__init__.py new file mode 100644 index 000000000..70e9a10db --- /dev/null +++ b/inventory_stock_dashboard_odoo/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies() +# Author: Aysha Shalin (odoo@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 . +# +############################################################################# +from . import models diff --git a/inventory_stock_dashboard_odoo/__manifest__.py b/inventory_stock_dashboard_odoo/__manifest__.py new file mode 100644 index 000000000..4e24aee50 --- /dev/null +++ b/inventory_stock_dashboard_odoo/__manifest__.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies() +# Author: Aysha Shalin (odoo@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 . +# +############################################################################### +{ + 'name': 'Inventory Dashboard Odoo 18', + 'version': '18.0.1.0.0', + 'category': 'Warehouse', + 'summary': 'Detailed dashboard view for Inventory module.', + 'description': """This module presents a detailed dashboard view for the + Inventory module, delivering a compr ehensive and concise overview that + serves as a valuable tool for both inventory users and administrators.""", + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'website': "https://www.cybrosys.com", + 'depends': ['stock', 'base'], + 'data': [ + 'views/res_config_settings_views.xml', + 'views/dashboard_menu.xml', + ], + 'assets': { + 'web.assets_backend': [ + 'https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap', + 'inventory_stock_dashboard_odoo/static/src/css/dashboard.css', + 'inventory_stock_dashboard_odoo/static/src/js/dashboard.js', + 'inventory_stock_dashboard_odoo/static/src/xml/inventory_dashboard_template.xml', + 'https://cdn.jsdelivr.net/npm/chart.js', + ], + }, + 'images': ['static/description/banner.png'], + 'license': 'LGPL-3', + 'installable': True, + 'auto_install': False, + 'application': False, +} diff --git a/inventory_stock_dashboard_odoo/doc/RELEASE_NOTES.md b/inventory_stock_dashboard_odoo/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..2fe4f518d --- /dev/null +++ b/inventory_stock_dashboard_odoo/doc/RELEASE_NOTES.md @@ -0,0 +1,6 @@ +## Module + +#### 29.01.2025 +#### Version 18.0.1.0.0 +##### ADD +- Initial commit for Inventory Dashboard Odoo 18 diff --git a/inventory_stock_dashboard_odoo/models/__init__.py b/inventory_stock_dashboard_odoo/models/__init__.py new file mode 100644 index 000000000..ea7568fd9 --- /dev/null +++ b/inventory_stock_dashboard_odoo/models/__init__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies() +# Author: Aysha Shalin (odoo@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 . +# +############################################################################### +from . import res_config_settings +from . import stock_move +from . import stock_move_line +from . import stock_picking +from . import stock_quant diff --git a/inventory_stock_dashboard_odoo/models/res_config_settings.py b/inventory_stock_dashboard_odoo/models/res_config_settings.py new file mode 100644 index 000000000..5cd0fe70e --- /dev/null +++ b/inventory_stock_dashboard_odoo/models/res_config_settings.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies() +# Author: Aysha Shalin (odoo@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 . +# +############################################################################### +from odoo import fields, models + + +class ResConfigSettings(models.TransientModel): + """ Inheriting res.config.settings model for adding custom fields in + settings.""" + _inherit = "res.config.settings" + + out_of_stock = fields.Boolean( + string='Out of stock', + config_parameter='inventory_stock_dashboard_odoo.out_of_stock', + help="Enable if out of stock") + out_of_stock_quantity = fields.Integer( + string='Quantity', + config_parameter='inventory_stock_dashboard_odoo.out_of_stock_quantity', + required=True, + help='Set the minimum quantity for considering a product as out of' + 'stock.') + dead_stock_bol = fields.Boolean( + string='Enable dead stock', + config_parameter='inventory_stock_dashboard_odoo.dead_stock_bol', + help='Enable if you want to consider dead stock.') + dead_stock = fields.Integer( + string='Dead stock', + config_parameter='inventory_stock_dashboard_odoo.dead_stock', + required=True, + help='Set the threshold quantity for considering a product as dead ' + 'stock.') + dead_stock_type = fields.Selection( + [('day', 'Day'), ('week', 'Week'), ('month', 'Month')], + string='Type', default='day', + config_parameter='inventory_stock_dashboard_odoo.dead_stock_type', + required=True, + help='Select the time period to determine dead stock based on product' + 'sales.') diff --git a/inventory_stock_dashboard_odoo/models/stock_move.py b/inventory_stock_dashboard_odoo/models/stock_move.py new file mode 100644 index 000000000..865d3c8eb --- /dev/null +++ b/inventory_stock_dashboard_odoo/models/stock_move.py @@ -0,0 +1,277 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies() +# Author: Aysha Shalin (odoo@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 . +# +############################################################################### +from odoo import api, models + + +class StockMove(models.Model): + """ Extends 'stock.move' and provides methods for retrieving data for + dashboard.""" + _inherit = "stock.move" + + @api.model + def get_the_top_products(self): + """ Returns top ten products and done quantity.""" + company_id = self.env.company.id + query = '''select product_template.name,sum(product_uom_qty) from stock_move + inner join stock_picking on stock_move.picking_id = stock_picking.id + inner join stock_picking_type on stock_picking.picking_type_id = stock_picking_type.id + inner join product_product on stock_move.product_id = product_product.id + inner join product_template on product_template.id = product_product.product_tmpl_id + where stock_move.state = 'done' and stock_move.company_id=%s and stock_picking_type.code = 'outgoing' and + stock_move.create_date between (now() - interval '10 day') and now() + group by product_template.name ORDER BY sum DESC''' % company_id + self._cr.execute(query) + top_product = self._cr.dictfetchall() + total_quantity = [] + product_name = [] + for record in top_product[:10]: + total_quantity.append(record.get('sum')) + product_name.append(record.get('name')['en_US']) + value = {'products': product_name, 'count': total_quantity} + return value + + @api.model + def top_products_last_ten(self): + """ Returns top ten products and done quantity for last 10 days.""" + company_id = self.env.company.id + query = '''select product_template.name,sum(product_uom_qty) from stock_move + inner join stock_picking on stock_move.picking_id = stock_picking.id + inner join stock_picking_type on stock_picking.picking_type_id = stock_picking_type.id + inner join product_product on stock_move.product_id = product_product.id + inner join product_template on product_template.id = product_product.product_tmpl_id + where stock_move.state = 'done' and stock_move.company_id=%s and stock_picking_type.code = 'outgoing' and + stock_move.create_date between (now() - interval '10 day') and now() + group by product_template.name ORDER BY sum DESC''' % company_id + self._cr.execute(query) + top_product = self._cr.dictfetchall() + total_quantity = [] + product_name = [] + for record in top_product[:10]: + total_quantity.append(record.get('sum')) + product_name.append(record.get('name')['en_US']) + value = {'products': product_name, 'count': total_quantity} + return value + + @api.model + def top_products_last_thirty(self): + """ Returns top ten products and done quantity for last 30 days.""" + company_id = self.env.company.id + query = '''select product_template.name,sum(product_uom_qty) from stock_move + inner join stock_picking on stock_move.picking_id = stock_picking.id + inner join stock_picking_type on stock_picking.picking_type_id = stock_picking_type.id + inner join product_product on stock_move.product_id = product_product.id + inner join product_template on product_template.id = product_product.product_tmpl_id + where stock_move.state = 'done' and stock_move.company_id=%s and stock_picking_type.code = 'outgoing' + and stock_move.create_date between (now() - interval '30 day') and now() + group by product_template.name ORDER BY sum DESC''' % company_id + self._cr.execute(query) + top_product = self._cr.dictfetchall() + total_quantity = [] + product_name = [] + for record in top_product[:10]: + total_quantity.append(record.get('sum')) + product_name.append(record.get('name')['en_US']) + value = {'products': product_name, 'count': total_quantity} + return value + + @api.model + def top_products_last_three_months(self): + """ Returns top ten products and done quantity for last 3 months.""" + company_id = self.env.company.id + query = '''select product_template.name,sum(product_uom_qty) from stock_move + inner join stock_picking on stock_move.picking_id = stock_picking.id + inner join stock_picking_type on stock_picking.picking_type_id = stock_picking_type.id + inner join product_product on stock_move.product_id = product_product.id + inner join product_template on product_template.id = product_product.product_tmpl_id + where stock_move.state = 'done' and stock_move.company_id=%s and stock_picking_type.code ='outgoing' + and stock_move.create_date between (now() - interval '3 month') and now() + group by product_template.name ORDER BY sum DESC''' % company_id + self._cr.execute(query) + top_product = self._cr.dictfetchall() + total_quantity = [] + product_name = [] + for record in top_product[:10]: + total_quantity.append(record.get('sum')) + product_name.append(record.get('name')['en_US']) + value = {'products': product_name, 'count': total_quantity} + return value + + @api.model + def top_products_last_year(self): + """ Returns top ten products and done quantity for last year.""" + company_id = self.env.company.id + query = '''select product_template.name,sum(product_uom_qty) from stock_move + inner join stock_picking on stock_move.picking_id = stock_picking.id + inner join stock_picking_type on stock_picking.picking_type_id = stock_picking_type.id + inner join product_product on stock_move.product_id = product_product.id + inner join product_template on product_template.id = product_product.product_tmpl_id + where stock_move.state = 'done' and stock_move.company_id=%s and + stock_picking_type.code = 'outgoing' and + stock_move.create_date between (now() - interval '1 year') and now() + group by product_template.name ORDER BY sum DESC''' % company_id + self._cr.execute(query) + top_product = self._cr.dictfetchall() + total_quantity = [] + product_name = [] + for record in top_product[:10]: + total_quantity.append(record.get('sum')) + product_name.append(record.get('name')['en_US']) + value = {'products': product_name, 'count': total_quantity} + return value + + @api.model + def get_stock_moves(self): + """ Returns location name and quantity_done of stock moves graph""" + company_id = self.env.company.id + query = ('''select stock_location.complete_name, count(stock_move.id) from stock_move + inner join stock_location on stock_move.location_id = stock_location.id where stock_move.state = 'done' + and stock_move.company_id = %s group by stock_location.complete_name''' % company_id) + self._cr.execute(query) + stock_move = self._cr.dictfetchall() + count = [] + complete_name = [] + for record in stock_move: + count.append(record.get('count')) + complete_name.append(record.get('complete_name')) + value = {'name': complete_name, 'count': count} + return value + + @api.model + def stock_move_last_ten_days(self, post): + """ Returns location name and quantity_done of stock moves graph last + ten days.""" + company_id = self.env.company.id + query = ('''select stock_location.name,sum(stock_move_line.quantity) from stock_move_line + inner join stock_location on stock_move_line.location_id = stock_location.id + where stock_move_line.state = 'done' and stock_move_line.company_id = %s + and stock_move_line.create_date between (now() - interval '10 day') and now() + group by stock_location.name''' % company_id) + self._cr.execute(query) + location_quantity = self._cr.dictfetchall() + quantity_done = [] + name = [] + for record in location_quantity: + quantity_done.append(record.get('sum')) + name.append(record.get('name')) + value = {'name': name, 'count': quantity_done} + return value + + @api.model + def this_month(self, post): + """ Returns location name and quantity_done of stock moves graph for + current month.""" + company_id = self.env.company.id + query = ('''select stock_location.name,sum(stock_move_line.quantity) from stock_move_line + inner join stock_location on stock_move_line.location_id = stock_location.id + where stock_move_line.state = 'done' and stock_move_line.company_id = %s + and stock_move_line.create_date between (now() - interval '1 months') and now() + group by stock_location.name''' % company_id) + self._cr.execute(query) + location_quantity = self._cr.dictfetchall() + quantity_done = [] + name = [] + for record in location_quantity: + quantity_done.append(record.get('sum')) + name.append(record.get('name')) + value = {'name': name, 'count': quantity_done} + return value + + @api.model + def last_three_month(self, post): + """ Returns location name and quantity_done of stock moves graph for + last three months.""" + company_id = self.env.company.id + query = ('''select stock_location.name,sum(stock_move_line.quantity) from stock_move_line + inner join stock_location on stock_move_line.location_id = stock_location.id + where stock_move_line.state = 'done' and stock_move_line.company_id = %s + and stock_move_line.create_date between (now() - interval '3 months') and now() + group by stock_location.name''' % company_id) + self._cr.execute(query) + location_quantity = self._cr.dictfetchall() + quantity_done = [] + name = [] + for record in location_quantity: + quantity_done.append(record.get('sum')) + name.append(record.get('name')) + value = {'name': name, 'count': quantity_done} + return value + + @api.model + def last_year(self, post): + """ Returns location name and quantity_done of stock moves graph for + last year.""" + company_id = self.env.company.id + query = ('''select stock_location.name,sum(stock_move_line.quantity) from stock_move_line + inner join stock_location on stock_move_line.location_id = stock_location.id + where stock_move_line.state = 'done' and stock_move_line.company_id = %s + and stock_move_line.create_date between (now() - interval '12 months') and now() + group by stock_location.name''' % company_id) + self._cr.execute(query) + location_quantity = self._cr.dictfetchall() + quantity_done = [] + name = [] + for record in location_quantity: + quantity_done.append(record.get('sum')) + name.append(record.get('name')) + value = {'name': name, 'count': quantity_done} + return value + + @api.model + def get_dead_of_stock(self): + """ Returns product name and dead quantity of dead stock graph.""" + company_id = self.env.company.id + sett_dead_stock_bool = self.env['ir.config_parameter'].sudo(). \ + get_param("inventory_stock_dashboard_odoo.dead_stock_bol", default="") + sett_dead_stock_quantity = self.env['ir.config_parameter'].sudo().get_param( + "inventory_stock_dashboard_odoo.dead_stock", + default="") + sett_dead_stock_type = self.env['ir.config_parameter'].sudo().get_param( + "inventory_stock_dashboard_odoo.dead_stock_type", + default="") + if sett_dead_stock_bool == "True": + if sett_dead_stock_quantity: + out_stock_value = int(sett_dead_stock_quantity) + query = '''select product_product.id,stock_quant.quantity from product_product + inner join stock_quant on product_product.id = stock_quant.product_id + where stock_quant.company_id = %s and product_product.create_date not between (now() - interval '%s %s') + and now() and product_product.id NOT IN (select product_id from stock_move + inner join stock_picking on stock_move.picking_id = stock_picking.id + inner join stock_picking_type on stock_picking.picking_type_id = stock_picking_type.id + where stock_move.company_id = %s and stock_picking_type.code = 'outgoing' and + stock_move.state = 'done' and stock_move.create_date between (now() - interval '%s %s') and now() + group by product_id)''' % \ + (company_id, out_stock_value, sett_dead_stock_type, company_id, out_stock_value, + sett_dead_stock_type) + self._cr.execute(query) + result = self._cr.fetchall() + total_quantity = [] + product_name = [] + for record in result: + if record[1] > 0: + complete_name = self.env['product.product'].browse(record[0]).display_name + product_name.append(complete_name) + total_quantity.append(record[1]) + value = { + 'product_name': product_name, + 'total_quantity': total_quantity + } + return value diff --git a/inventory_stock_dashboard_odoo/models/stock_move_line.py b/inventory_stock_dashboard_odoo/models/stock_move_line.py new file mode 100644 index 000000000..eeb4e6c7e --- /dev/null +++ b/inventory_stock_dashboard_odoo/models/stock_move_line.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies() +# Author: Aysha Shalin (odoo@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 . +# +############################################################################### +from odoo import api, models + + +class StockMoveLine(models.Model): + """ Extends 'stock.move.line' and provides methods for retrieving data for + dashboard.""" + _inherit = "stock.move.line" + + @api.model + def get_product_moves(self): + """ Returns product move and quantity_done.""" + company_id = self.env.company.id + query = ('''select product_template.name,sum(stock_move_line.quantity) from stock_move_line + inner join product_product on stock_move_line.product_id = product_product.id + inner join product_template on product_product.product_tmpl_id = product_template.id + where stock_move_line.company_id = %s group by product_template.name''' % company_id) + self._cr.execute(query) + products_quantity = self._cr.dictfetchall() + quantity_done = [] + name = [] + for record in products_quantity: + quantity_done.append(record.get('sum')) + name.append(record.get('name')) + value = {'name': name, 'count': quantity_done} + category_query = '''select product_category.id,product_category.name from stock_move_line + inner join product_product on stock_move_line.product_id = product_product.id + inner join product_template on product_product.product_tmpl_id = product_template.id + inner join product_category on product_template.categ_id = product_category.id + where stock_move_line.company_id = %s and stock_move_line.state = 'done' + group by product_category.id''' % company_id + self._cr.execute(category_query) + category = self._cr.dictfetchall() + category_id = [] + category_name = [] + for record in category: + category_id.append(record.get('id')) + category_name.append(record.get('name')) + value1 = {'category_id': category_id, 'category_name': category_name} + return value, value1 + + @api.model + def product_move_by_category(self, option): + """ Returns category name and quantity_done.""" + if option is None: + return {} + category_id = int(option) + company_id = self.env.company.id + query = ('''select product_template.name,sum(stock_move_line.quantity) from stock_move_line + inner join product_product on stock_move_line.product_id = product_product.id + inner join product_template on product_product.product_tmpl_id = product_template.id + inner join product_category on product_template.categ_id = product_category.id + where stock_move_line.company_id = %s and product_category.id = %s group by product_template.name''' % + (company_id, category_id)) + self._cr.execute(query) + product_move = self._cr.dictfetchall() + quantity_done = [] + name = [] + for record in product_move: + quantity_done.append(record.get('sum')) + name.append(record.get('name')['en_US']) + value = { + 'name': name, + 'count': quantity_done, + } + return value diff --git a/inventory_stock_dashboard_odoo/models/stock_picking.py b/inventory_stock_dashboard_odoo/models/stock_picking.py new file mode 100644 index 000000000..1358defff --- /dev/null +++ b/inventory_stock_dashboard_odoo/models/stock_picking.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies() +# Author: Aysha Shalin (odoo@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 . +# +############################################################################### +from odoo import api, models + + +class StockPicking(models.Model): + """ Extends 'stock.picking' for retrieving stock picking data for + dashboard.""" + _inherit = "stock.picking" + + @api.model + def get_operation_types(self): + """ Method for retrieving operation type tiles, operation type graph and + returns operation type details. + no_transfer - count of transfers for each operation type, + late - count of late occurrences for each operation type, + waiting - count of waiting operations for each operation type, + operation_type_name - retrieve all operation type names, + backorder - count the number of backorders for each operation type. + """ + no_transfer = {} + stock_picking_type = self.env['stock.picking.type'].search([]) + stock_picking = self.env['stock.picking'].search([]) + stock = [] + length = [] + names = [] + late = {} + query = '''select stock_picking.picking_type_id, count(stock_picking.picking_type_id) from stock_picking + inner join stock_picking_type on stock_picking.picking_type_id = stock_picking_type.id + where stock_picking.company_id = %s and + stock_picking.state in ('assigned', 'waiting', 'confirmed') and (has_deadline_issue = true or + date_deadline <= now() or scheduled_date <= now()) + group by stock_picking.picking_type_id''' % self.env.company.id + self._cr.execute(query) + lates = self._cr.dictfetchall() + for rec in lates: + late.update({rec.get('picking_type_id'): rec.get('count')}) + waiting = {} + backorder = {} + operation_type_name = {} + for i in stock_picking_type: + names.append(i.name) + orders = stock_picking.filtered(lambda r: r.picking_type_id.id == i.id) + stock.append(len(orders)) + length_stock_picking = len(orders) + length.append(len(stock_picking.filtered(lambda r: r.picking_type_id.id == i.id))) + no_transfer.update({i.id: length_stock_picking}) + operation_type_name.update({i.id: i.name}) + if len(orders) > 0: + if len(orders.filtered(lambda r: r.state == 'confirmed')) > 0: + waiting.update({i.id: len(orders.filtered(lambda r: r.state == 'confirmed'))}) + if len(orders.mapped('backorder_id')) > 0: + backorder.update({i.id: len(orders.mapped('backorder_id'))}) + return no_transfer, late, waiting, operation_type_name, backorder + + @api.model + def get_product_category(self): + """ Return product categories and categories that have on-hand product + quantities.""" + category_ids = self.env['product.category'].search([]) + category_name = [] + product_count = [] + for rec in category_ids: + name = rec.name + category_name.append(name) + count = rec.product_count + product_count.append(count) + value = {'name': category_name, 'count': product_count} + return value + + @api.model + def get_locations(self): + """ Returns locations and locations that have on-hand product + quantities.""" + stock_quant_ids = self.env['stock.quant'].search([]) + locations = stock_quant_ids.mapped('location_id') + value = {} + for rec in locations: + loc_stock_quant = stock_quant_ids.filtered(lambda x: x.location_id == rec) + on_hand_quantity = sum(loc_stock_quant.mapped('inventory_quantity_auto_apply')) + value[rec.name] = on_hand_quantity + return value diff --git a/inventory_stock_dashboard_odoo/models/stock_quant.py b/inventory_stock_dashboard_odoo/models/stock_quant.py new file mode 100644 index 000000000..801bc26a9 --- /dev/null +++ b/inventory_stock_dashboard_odoo/models/stock_quant.py @@ -0,0 +1,59 @@ +# -*- coding: utf-8 -*- +############################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2025-TODAY Cybrosys Technologies() +# Author: Aysha Shalin (odoo@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 . +# +############################################################################### +from odoo import api, models + + +class StockQuant(models.Model): + """ Extends 'stock.quant' for retrieving data of products that are out of + stock.""" + _inherit = "stock.quant" + + @api.model + def get_out_of_stock(self): + """ Returns products and quantities that are out of stock.""" + company_id = self.env.company.id + sett_out_stock_bool = self.env['ir.config_parameter'].sudo(). \ + get_param("inventory_stock_dashboard_odoo.out_of_stock", default="") + sett_out_stock_quantity = self.env['ir.config_parameter'].sudo().\ + get_param("inventory_stock_dashboard_odoo.out_of_stock_quantity", default="") + if sett_out_stock_bool == "True": + if sett_out_stock_quantity: + out_stock_value = int(sett_out_stock_quantity) + query = '''select product_product.id,sum(stock_quant.quantity) from product_product + inner join stock_quant on product_product.id = stock_quant.product_id + where stock_quant.quantity < %s and stock_quant.company_id = %s group by product_product.id''' \ + % (out_stock_value, company_id) + self._cr.execute(query) + result = self._cr.fetchall() + total_quantity = [] + product_name = [] + for record in result: + total_quantity.append(record[1]) + for record in result: + complete_name = self.env['product.product'].browse( + record[0]).display_name + product_name.append(complete_name) + value = { + 'product_name': product_name, + 'total_quantity': total_quantity + } + return value diff --git a/inventory_stock_dashboard_odoo/static/description/assets/cybro-icon.png b/inventory_stock_dashboard_odoo/static/description/assets/cybro-icon.png new file mode 100755 index 000000000..06e73e11d Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/cybro-icon.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/cybro-odoo.png b/inventory_stock_dashboard_odoo/static/description/assets/cybro-odoo.png new file mode 100755 index 000000000..ed02e07a4 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/cybro-odoo.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/h2.png b/inventory_stock_dashboard_odoo/static/description/assets/h2.png new file mode 100755 index 000000000..0bfc4707d Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/h2.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/arrows-repeat.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/arrows-repeat.svg new file mode 100755 index 000000000..1d7efabc5 --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/arrows-repeat.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-1.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-1.png new file mode 100755 index 000000000..c180db172 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-1.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-2.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-2.svg new file mode 100755 index 000000000..e606d97d9 --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-2.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-bg.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-bg.png new file mode 100755 index 000000000..a8238d3c0 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-bg.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-bg.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-bg.svg new file mode 100755 index 000000000..b1378103e --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-bg.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-call.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-call.svg new file mode 100755 index 000000000..96c687e81 --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-call.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-mail.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-mail.svg new file mode 100755 index 000000000..cbf0d158d --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-mail.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-pattern.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-pattern.svg new file mode 100755 index 000000000..9c1c7e101 --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-pattern.svg @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-promo.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-promo.svg new file mode 100755 index 000000000..d52791b11 --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/banner-promo.svg @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/brand-pair.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/brand-pair.svg new file mode 100755 index 000000000..d8db7fc1e --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/brand-pair.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/check.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/check.png new file mode 100755 index 000000000..c8e85f51d Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/check.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/chevron.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/chevron.png new file mode 100755 index 000000000..2089293d6 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/chevron.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/close-icon.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/close-icon.svg new file mode 100755 index 000000000..df8cce37a --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/close-icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/cogs.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/cogs.png new file mode 100755 index 000000000..95d0bad62 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/cogs.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/collabarate-icon.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/collabarate-icon.svg new file mode 100755 index 000000000..dd4e10518 --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/collabarate-icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/consultation.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/consultation.png new file mode 100755 index 000000000..8319d4baa Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/consultation.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/cybro-logo.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/cybro-logo.png new file mode 100755 index 000000000..ff4b78220 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/cybro-logo.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/down.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/down.svg new file mode 100755 index 000000000..f21c36271 --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/ecom-black.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/ecom-black.png new file mode 100755 index 000000000..a9385ff13 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/ecom-black.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/education-black.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/education-black.png new file mode 100755 index 000000000..3eb09b27b Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/education-black.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/faq.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/faq.png new file mode 100755 index 000000000..4250b5b81 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/faq.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/feature-icon.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/feature-icon.svg new file mode 100755 index 000000000..fa0ea6850 --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/feature-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/feature.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/feature.png new file mode 100755 index 000000000..ac7a785c0 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/feature.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/gear.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/gear.svg new file mode 100755 index 000000000..0cc66b6ea --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/gear.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/hero.gif b/inventory_stock_dashboard_odoo/static/description/assets/icons/hero.gif new file mode 100755 index 000000000..380654dfe Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/hero.gif differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/hire-odoo.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/hire-odoo.svg new file mode 100755 index 000000000..e1ac089b0 --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/hire-odoo.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/hotel-black.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/hotel-black.png new file mode 100755 index 000000000..130f613be Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/hotel-black.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/license.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/license.png new file mode 100755 index 000000000..a5869797e Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/license.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/life-ring-icon.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/life-ring-icon.svg new file mode 100755 index 000000000..3ae6e1d89 --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/life-ring-icon.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/lifebuoy.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/lifebuoy.png new file mode 100755 index 000000000..658d56ccc Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/lifebuoy.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/mail.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/mail.svg new file mode 100755 index 000000000..1eedde695 --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/mail.svg @@ -0,0 +1,3 @@ + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/manufacturing-black.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/manufacturing-black.png new file mode 100755 index 000000000..697eb0e9f Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/manufacturing-black.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/notes.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/notes.png new file mode 100755 index 000000000..ee5e95404 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/notes.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/notification icon.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/notification icon.svg new file mode 100755 index 000000000..053189973 --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/notification icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/odoo-consultancy.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/odoo-consultancy.svg new file mode 100755 index 000000000..e05f65bde --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/odoo-consultancy.svg @@ -0,0 +1,4 @@ + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/odoo-licencing.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/odoo-licencing.svg new file mode 100755 index 000000000..2606c88b0 --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/odoo-licencing.svg @@ -0,0 +1,3 @@ + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/odoo-logo.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/odoo-logo.png new file mode 100755 index 000000000..0e4d0eb5a Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/odoo-logo.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/patter.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/patter.svg new file mode 100755 index 000000000..25c9c0a8f --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/patter.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/pattern1.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/pattern1.png new file mode 100755 index 000000000..09ab0fb2d Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/pattern1.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/pos-black.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/pos-black.png new file mode 100755 index 000000000..97c0f90c1 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/pos-black.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/puzzle-piece-icon.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/puzzle-piece-icon.svg new file mode 100755 index 000000000..3e9ad9373 --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/puzzle-piece-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/puzzle.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/puzzle.png new file mode 100755 index 000000000..65cf854e7 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/puzzle.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/replace-icon.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/replace-icon.svg new file mode 100755 index 000000000..d0e3a7af1 --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/replace-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/restaurant-black.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/restaurant-black.png new file mode 100755 index 000000000..4a35eb939 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/restaurant-black.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/screenshot-main.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/screenshot-main.png new file mode 100755 index 000000000..575f8e676 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/screenshot-main.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/screenshot.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/screenshot.png new file mode 100755 index 000000000..cef272529 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/screenshot.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/service-black.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/service-black.png new file mode 100755 index 000000000..301ab51cb Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/service-black.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/skype-fill.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/skype-fill.svg new file mode 100755 index 000000000..c17423639 --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/skype-fill.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/skype.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/skype.png new file mode 100755 index 000000000..51b409fb3 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/skype.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/skype.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/skype.svg new file mode 100755 index 000000000..df3dad39b --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/skype.svg @@ -0,0 +1,3 @@ + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/star-1.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/star-1.svg new file mode 100755 index 000000000..7e55ab162 --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/star-1.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/star-2.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/star-2.svg new file mode 100755 index 000000000..5ae9f507a --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/star-2.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/support.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/support.png new file mode 100755 index 000000000..4f18b8b82 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/support.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/test-1 - Copy.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/test-1 - Copy.png new file mode 100755 index 000000000..f6a902663 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/test-1 - Copy.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/test-1.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/test-1.png new file mode 100755 index 000000000..0908add2b Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/test-1.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/test-2.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/test-2.png new file mode 100755 index 000000000..4671fe91e Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/test-2.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/trading-black.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/trading-black.png new file mode 100755 index 000000000..9398ba2f1 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/trading-black.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/training.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/training.png new file mode 100755 index 000000000..884ca024d Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/training.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/translate.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/translate.svg new file mode 100755 index 000000000..af9c8a1aa --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/translate.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/update.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/update.png new file mode 100755 index 000000000..ecbc5a01a Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/update.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/user.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/user.png new file mode 100755 index 000000000..6ffb23d9f Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/user.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/video.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/video.png new file mode 100755 index 000000000..576705b17 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/video.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/whatsapp.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/whatsapp.png new file mode 100755 index 000000000..d513a5356 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/whatsapp.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/wrench-icon.svg b/inventory_stock_dashboard_odoo/static/description/assets/icons/wrench-icon.svg new file mode 100755 index 000000000..174b5a465 --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/assets/icons/wrench-icon.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/inventory_stock_dashboard_odoo/static/description/assets/icons/wrench.png b/inventory_stock_dashboard_odoo/static/description/assets/icons/wrench.png new file mode 100755 index 000000000..6c04dea0f Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/icons/wrench.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/modules/1.jpg b/inventory_stock_dashboard_odoo/static/description/assets/modules/1.jpg new file mode 100644 index 000000000..3cb15fe01 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/modules/1.jpg differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/modules/2.jpg b/inventory_stock_dashboard_odoo/static/description/assets/modules/2.jpg new file mode 100644 index 000000000..662cadcc3 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/modules/2.jpg differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/modules/3.jpg b/inventory_stock_dashboard_odoo/static/description/assets/modules/3.jpg new file mode 100644 index 000000000..717a00443 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/modules/3.jpg differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/modules/4.png b/inventory_stock_dashboard_odoo/static/description/assets/modules/4.png new file mode 100644 index 000000000..00ebf54ad Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/modules/4.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/modules/5.jpg b/inventory_stock_dashboard_odoo/static/description/assets/modules/5.jpg new file mode 100644 index 000000000..7c67e2eec Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/modules/5.jpg differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/modules/6.gif b/inventory_stock_dashboard_odoo/static/description/assets/modules/6.gif new file mode 100644 index 000000000..a35ece8df Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/modules/6.gif differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/screenshots/1.png b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/1.png new file mode 100644 index 000000000..b6a4e9d01 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/1.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/screenshots/10.png b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/10.png new file mode 100644 index 000000000..502efd7bd Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/10.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/screenshots/11.png b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/11.png new file mode 100644 index 000000000..8f02ad75d Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/11.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/screenshots/12.png b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/12.png new file mode 100644 index 000000000..b5f349b5b Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/12.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/screenshots/13.png b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/13.png new file mode 100644 index 000000000..9459ddbcf Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/13.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/screenshots/14.png b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/14.png new file mode 100644 index 000000000..6796e06d2 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/14.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/screenshots/2.png b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/2.png new file mode 100644 index 000000000..283ce9253 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/2.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/screenshots/3.png b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/3.png new file mode 100644 index 000000000..9c0c7386d Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/3.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/screenshots/4.png b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/4.png new file mode 100644 index 000000000..89e8ac335 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/4.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/screenshots/5.png b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/5.png new file mode 100644 index 000000000..069289bc5 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/5.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/screenshots/6.png b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/6.png new file mode 100644 index 000000000..d02d7f290 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/6.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/screenshots/7.png b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/7.png new file mode 100644 index 000000000..b06853173 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/7.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/screenshots/8.png b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/8.png new file mode 100644 index 000000000..2aa559e09 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/8.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/screenshots/9.png b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/9.png new file mode 100644 index 000000000..96965210e Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/9.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/screenshots/hero.gif b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/hero.gif new file mode 100644 index 000000000..0b80e3f56 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/screenshots/hero.gif differ diff --git a/inventory_stock_dashboard_odoo/static/description/assets/y18.jpg b/inventory_stock_dashboard_odoo/static/description/assets/y18.jpg new file mode 100755 index 000000000..eea1714f2 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/assets/y18.jpg differ diff --git a/inventory_stock_dashboard_odoo/static/description/banner.jpg b/inventory_stock_dashboard_odoo/static/description/banner.jpg new file mode 100644 index 000000000..34fccf8d0 Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/banner.jpg differ diff --git a/inventory_stock_dashboard_odoo/static/description/icon.png b/inventory_stock_dashboard_odoo/static/description/icon.png new file mode 100644 index 000000000..5f6ad456e Binary files /dev/null and b/inventory_stock_dashboard_odoo/static/description/icon.png differ diff --git a/inventory_stock_dashboard_odoo/static/description/index.html b/inventory_stock_dashboard_odoo/static/description/index.html new file mode 100644 index 000000000..bb34821eb --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/description/index.html @@ -0,0 +1,1325 @@ + + + + + + Accounting Dashboard Odoo18 + + + + + + + + + + +
+
+ + + +
+
+ Community +
+
+ Enterprise +
+
+ Odoo.sh +
+
+
+ +
+
+
+
+

+ Inventory Dashboard V18 +

+

Inventory Dashboard Odoo 18 +

+
+
+ +
+ +
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+

Key + Highlights

+
+
+
+
+ +
+
+ Detailed View for Users and Admins. +
+

+ This Module Offers a Comprehensive and + Concise Overview of the Inventory Module at + a Glance, Serving as a Valuable Tool for + Both Inventory Users and + Administrators.

+
+
+
+
+
+ +
+
+ Simplifies the Analysis of the Inventory + Module's Functions. +
+

+ Allows to Easily Analyse the + Functionalities of Inventory Module Using + this Dashboard. +

+
+
+
+
+
+ +
+
+ Dashboard Tiles and Various Graphs. +
+

+ Dynamic and clickable Dashboard Tiles, + Along with a Variety of Graphs, Greatly + Enhance the Analysis Process. +

+
+
+
+
+
+ +
+
+ Filtering Options for Specific Graphs. +
+

+ Graphs can be Filtered According to Various + Time Periods. +

+
+
+
+
+ +
+
+
+ Inventory Dashboard Odoo 18 +

+ Are you ready to make your business more + organized? +
Improve now! +

+ +
+
+ +
+
+
+ + + + +
+
+ +
+
+
+
+ acc_bg +
+ +
+
+
+
+

+ Dynamic And Clickable Dashboard Tiles. + +

+
+
+

+ Click the Tiles and States in + Tile,That shows the Detailed + View of Corresponding Operation + Type. +

+
+
+
+ +
+
+
+
+
+
+
+
+
+

+ Inventory Dashboard have Different Types of Graphs that will Give You Complete Analysis of the Inventory Module. + +

+
+
+
+ +
+
+
+
+
+
+
+
+
+

+ The Inventory Dashboard Features a Variety of Graphs that Provide a Comprehensive Analysis of the Inventory Module. +

+
+
+
+ +
+
+
+
+
+
+
+
+
+

+ + Graphs can be Filtered According to Various Time Periods. + +

+
+
+
+ +
+
+
+
+
+
+
+
+
+

+ 1. Top Moving Products. + +

+
+
+

+ The Ten Best-selling Products + Along with their Corresponding + Sales Counts. +

+
+
+
+ +
+
+
+
+
+
+
+
+
+

+ 2. Product Categories. + +

+
+
+

+ Displaying Product Categories + and the Product Count Within + their Respective Categories. +

+
+
+
+ +
+
+
+
+
+
+
+
+
+

+ 3. Product Moves By Category. + +

+
+
+
+ +
+
+
+
+
+
+
+
+
+

+ 4. Stock Moves By Location. + +

+
+
+
+ +
+
+
+
+
+
+
+
+
+

+ 5. Operation Types. + +

+
+
+
+ +
+
+
+
+
+
+
+
+
+

+ 6. Dead Stock. + +

+
+
+
+ +
+
+
+
+
+
+
+
+
+

+ The Graph Displays Dead Stock Products and their Current Stock. + +

+
+
+
+ +
+
+
+
+
+
+
+
+
+

+ 7. Out of Stock Products. + +

+
+
+
+ +
+
+
+
+
+
+
+
+
+

+ The Graph Displays Out-of-stock Products and Their Current Stock. + +

+
+
+
+ +
+
+
+
+
+
+
+
+
+

+ 8. Locations Table. + +

+
+
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+
+ +
+

+ Purchase By Month

+
+ +
+
+
+
+
+
+ +
+

+ Purchase Vendor Analysis

+
+
+
+
+
+
+
+ +
+

+ Product Category Analysis

+
+
+
+
+
+
+
+ +
+

+ Pending Arrivals

+
+
+
+
+
+
+
+ +
+

+ Upcoming Arrivals

+
+
+
+
+
+
+
+ +
+

+ Top Charts

+
+
+
+
+
+
+
+
+
+
+ +
+ +
+ +
+

+ The purpose of the + Inventory + Dashboard Module is + to provide a + comprehensive, + user-friendly + interface for + monitoring and + analyzing + inventory-related + data in real time. +

+
+
+ +
+ +
+

+ The dashboard + display + summarized data + of inventory, + including: + + Top moving + products. + Product categories. + Product moves by + category. + Stock moves by + location. + Operation types + etc. + +

+
+
+
+ +
+
+
+
+
+
+ +
+
+

+ Latest Release 18.0.1.0.0 +

+ + 7th May, 2025 + +
+
+
+
+
+ Add +
+
+
+
    +
  • + Initial Commit +
  • + +
+
+
+
+
+
+
+
+
+
+ + + +
+

+ Related Products +

+ +
+ + +
+

+ Our Services

+ +
+ +
+
+ .... +
+
+ +
+ + +
+
+ + + + + + \ No newline at end of file diff --git a/inventory_stock_dashboard_odoo/static/src/css/dashboard.css b/inventory_stock_dashboard_odoo/static/src/css/dashboard.css new file mode 100644 index 000000000..4b0ad4843 --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/src/css/dashboard.css @@ -0,0 +1,880 @@ +.item-container { + background-image: -webkit-linear-gradient(white, white); +} +.item-header { + padding-left: 30px; + background-image: -webkit-linear-gradient(white, #c3c9d4); +} +.col-sm, +.col-sm-1, +.col-sm-10, +.col-sm-11, +.col-sm-12, +.col-sm-2, +.col-sm-3, +.col-sm-4, +.col-xl-auto { + position: relative; + padding-right: 7.5px; + padding-left: 7.5px; +} +#location_table thead th { + border-bottom: none; + background-color: #67b7dc; + color: white; + width: 250px; + height: 30px; +} +.accounts-dashboard-wrap .card-header { + background-color: + transparent; + border-bottom: 1px solid rgba(0, 0, 0, .125); + padding: .75rem 1.25rem; + position: relative; + border-top-left-radius: .25rem; + border-top-right-radius: .25rem; +} +.accounts-dashboard-wrap .fa:hover { + -ms-transform: scale(1.5); + /* IE 9 */ + -webkit-transform: scale(1.5); + /* Safari 3-8 */ + transform: scale(1.5); +} +.accounts-dashboard-wrap .card-header>.card-tools { + float: right; + margin-right: -.625rem; +} +.right { + float: left; +} +.accounts-dashboard-wrap .tooltip:hover .tooltiptext { + visibility: visible; +} +.accounts-dashboard-wrap .col-6 { + -ms-flex: 0 0 50%; + flex: 0 0 50%; + max-width: 50%; +} +.accounts-dashboard-wrap .fa-cog { + content: "\f013" +} +.accounts-dashboard-wrap .fa, +.accounts-dashboard-wrap .fas { + font-weight: 900; +} +.accounts-dashboard-wrap .fa, +.accounts-dashboard-wrap .fab, +.accounts-dashboard-wrap .fad, +.accounts-dashboard-wrap .fal, +.accounts-dashboard-wrap .far, +.accounts-dashboard-wrap .fas { + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + display: inline-block; + font-style: normal; + font-variant: normal; + text-rendering: auto; + line-height: 1; +} +.accounts-dashboard-wrap .info-box .info-box-icon { + + border-radius: .25rem; + -ms-flex-align: center; + align-items: center; + display: -ms-flexbox; + display: flex; + font-size: 1.875rem; + -ms-flex-pack: center; + justify-content: center; + text-align: center; + width: 70px; +} +.accounts-dashboard-wrap .info-box { + box-shadow: 0 0 1px rgba(0, 0, 0, .125), 0 1px 3px rgba(0, 0, 0, .2); + border-radius: .25rem; + background: #fff; + display: -ms-flexbox; + display: flex; + margin-bottom: 1rem; + min-height: 80px; + padding: .5rem; + position: relative; +} +.accounts-dashboard-wrap .o_datepicker .o_datepicker_input { + width: 100%; + cursor: pointer; +} +.accounts-dashboard-wrap #overdue { + width: 100%; + cursor: pointer; +} +.accounts-dashboard-wrap .o_input { + border: 1px solid #cfcfcf; + border-top-style: none; + border-right-style: none; + border-left-style: none; +} +.accounts-dashboard-wrap .in_graph { + padding-left: 90px; + height: auto; + padding-bottom: 65px; + text-align: center !important; +} +.accounts-dashboard-wrap .oh_dashboards { + padding-top: 15px; + background-color: #f8faff !important; +} +.accounts-dashboard-wrap .container-fluid.o_in_dashboard { + padding: 0px !important; +} +.accounts-dashboard-wrap .o_action_manager { + overflow-y: scroll !important; + max-width: 100%; +} +// new tile + +.oh_dashboards { + background-color: #ececec; +} +.accounts-dashboard-wrap .container { + margin: 50px 0 0 100px; +} +.accounts-dashboard-wrap .o_dashboards { + color: #2a2a2a; + background-color: #f2f2f2 !important; +} +.accounts-dashboard-wrap .dash-header { + margin: 15px 0px 12px 0 !important; + display: block; + padding: 7px 25px 7px 0; + color: #0e1319; + font-size: 2rem; + font-weight: 400; + background-color: + rgba(255, 255, 255, 0.9) !important; + color: #212529; + padding: 1.5rem; + border-radius: 3px; + box-shadow: 0 0px 10px 0px rgba(0, 0, 0, 0.05) !important; + display: flex; + justify-content: space-between; + align-items: center; +} +.accounts-dashboard-wrap .dashboard-h1 { + display: block; + padding: 7px 25px 7px 0; + color: #0e1319; + font-size: 2rem; + font-weight: 400; + color: #212529; + float: left; + margin-bottom: 0; +} +.accounts-dashboard-wrap .card { + position: relative !important; + border-top: 0 !important; + margin-bottom: 30px !important; + width: 100% !important; + background-color: #ffffff !important; + border-radius: 0.25rem !important; + padding: 0px !important; + -webkit-transition: .5s !important; + transition: .5s !important; + display: -ms-flexbox !important; + display: flex !important; + -ms-flex-direction: column !important; + flex-direction: column !important; + box-shadow: 0 0px 10px 0px rgba(0, 0, 0, 0.05) !important; + border-radius: 0.25rem; +} +.accounts-dashboard-wrap .card-header { + border: 0; + padding: 0; +} +.accounts-dashboard-wrap .card-header>.card-tools { + float: right; + margin-right: 0.375rem; + margin-top: 5px; + margin-bottom: 10px; +} +.accounts-dashboard-wrap .card-header i.fa { + font-size: 1.3rem; + display: inline-block; + padding: 0 0px; + margin: 0 0px; + color: #57769c; + opacity: .8; + -webkit-transition: 0.3s linear; + transition: 0.3s linear; +} +.accounts-dashboard-wrap .dropdown-toggle::after { + display: inline-block; + margin-left: 0.255em; + vertical-align: 0.255em; + content: ""; + border-top: 0.3em solid; + border-right: 0.3em solid transparent; + border-bottom: 0; + border-left: 0.3em solid transparent; + color: #7891af; +} +.accounts-dashboard-wrap .account-details { + display: flex; +} +.main-title { + color: #a3a3a3; + display: block; + margin-bottom: 5px; + font-size: 20px; + font-weight: 400; +} +.accounts-dashboard-wrap .main-title { + display: block; + margin-bottom: 5px; + font-size: 13px; + font-weight: 600; + color: #fff !important; + text-transform: uppercase; + padding: 1rem; + border-radius: 5px; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; +} +.accounts-dashboard-wrap .card-body { + background-color: rgba(255, 255, 255, 0.9) !important; + color: #212529; + padding-top: 0; +} +.accounts-dashboard-wrap .tile.wide.invoice { + margin-bottom: 27px; + -webkit-box-shadow: 1px 5px 24px 0 rgba(68, 102, 242, 0.05); + box-shadow: 1px 5px 24px 0 rgba(68, 102, 242, 0); + background-color: #ffffff; + border-radius: 5px; + position: relative; + width: 100%; + padding: 0rem 0rem; + border: 1px solid rgba(0, 0, 0, 0.07); + height: 140px; +} +.accounts-dashboard-wrap .box-1 .main-title { + background: #67b7dc; + color: #fff; +} +.accounts-dashboard-wrap .box-2 .main-title { + background: #6794dc !important; + color: #fff; +} +.accounts-dashboard-wrap .box-3 .main-title { + background: #8067dc; + color: #fff; +} +.accounts-dashboard-wrap .box-4 .main-title { + background: #c767dc; + color: #fff; +} +.accounts-dashboard-wrap .count { + margin-bottom: 1rem; +} +.accounts-dashboard-wrap .main-title~div { + display: flex; + justify-content: space-between; + margin-top: 1rem; + padding: 1rem; + background: #fff; +} +#location_table { + background-color: #fff; + color: (--mauve); +} +#tile_main_div:hover { + border-top-left-radius: 10px; + border-bottom-left-radius: 10px; + animation-name: example; + animation-duration: 0.25s; + border-left: 8px solid var(--mauve); + box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22); +} +#tiles:hover { + border-top-left-radius: 10px; + border-bottom-left-radius: 10px; + animation-name: example; + animation-duration: 0.25s; + box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22); +} +.details_table{ +align-content: left; +} +.graph_details_table{ + position: absolute; + top: 45px; + right: 15px; + background-color: white; + border-collapse: collapse; + border: 1px solid #ddd; +} +.graph_details_table th{ + background-color:#67b7dc; + color: white; + width: 250px; + height: 30px; +} +.graph_details_table td{ +border: 1px solid #ddd; +height: 20px; +} +.graph_details_table tr:nth-child(even){background-color: #f2f2f2;} +.graph_details_table tr:hover {background-color: #ddd;} +#product_moves_selection{ + position: relative; + right: 10px; + top: 5px; +} +:root { + /* Primary */ + --mauve: #7D7EAF; + --pink-dark: #BD85BA; + --pink: #F78EAD; + --peach: #FFA48E; + --orange: #FFCA71; + --gold: #CEA716; + --green: #1EC198; + --grey: #a0a0a0; + /* Light */ + --mauve-light: #e5e5ef; + --pink-dark-light: #f2e7f1; + --pink-light: #fde8ef; + --peach-light: #ffede8; + --orange-light: #fff4e3; + --gold-light: #faf6e8; + --green-light: #e9f9f5; + --grey-light: #e0e0e0; + + /*Lighter*/ + --grey-lighter: #fafafa; + --grey-dark-lighter: #f3f3f3; +} +/* Background */ +.bg-mauve-light { + background-color: var(--mauve-light); +} +.bg-pink-dark-light { + background-color: var(--pink-dark-light); +} +.bg-pink-light { + background-color: var(--pink-light); +} +.bg-peach-light { + background-color: var(--peach-light); +} +.bg-orange-light { + background-color: var(--orange-light); +} +.bg-gold-light { + background-color: var(--gold-light); +} +.bg-green-light { + background-color: var(--green-light); +} +/* Text */ +.text-mauve { + color: var(--mauve); +} +.text-pink-dark { + color: var(--pink-dark); +} +.text-pink { + color: var(--pink); +} +.text-peach { + color: var(--peach); +} +.text-orange { + color: var(--orange); +} +.text-gold { + color: var(--gold); +} +.text-green { + color: var(--green); +} +/* Cards */ +/*.dashboard-card { + border-radius: 0.3rem; + display: flex; + justify-content: center; + padding: 1.7rem 1.5rem 1.5rem 1.5rem; + margin: 1rem auto; + height: 90px; +}*/ +.dashboard-card__icon-container { + height: 50px; + width: 50px; + border-radius: 50%; +} +.dashboard-card__icon-container i { + font-size: 20px; +} +.dashboard-card__details { + margin-left: 0rem !important; + max-width: 120px; +} +.dashboard-card__details h3 { + font-weight: 700; + font-size: 1.5rem; +} +.dashboard-card__details h4 { + font-weight: 700; + font-size: 0.7rem; + color: var(--grey); + margin-top: -5px; +} +h2.section-header { + font-weight: 700; + font-size: 1.5rem; +} +.chart-container { + border-radius: 0.3rem; + padding: 1rem; + margin: 1rem auto; +} +.chart-container.card-shadow { + height: 100%; +} +.half_chart.chart-container.card-shadow { + height: 49%; +} +.chart-container h2 { + font-weight: 700; + font-size: 1.125rem; +} +.item-container { + background-color: var(--grey-lighter); + border-radius: 0.3rem; + padding: 1.2rem 1rem; + margin: 1rem auto; +} +.item-container:hover { + background-color: var(--grey-dark-lighter); + transition: all 0.3s ease-in-out; + cursor: pointer; +} +.count-container { + font-weight: 700; + font-size: 2rem; + background-color: var(--mauve-light); + color: var(--mauve); + height: 60px !important; + width: 60px !important; + border-radius: 50%; + display: -webkit-box; + display: -webkit-flex; + display: flex; + justify-content: center; + align-items: center; +} +.item-header { + display: flex; + align-items: flex-start; +} +.item-title h3 { + font-size: 1.3rem; + font-weight: 700; +} +.item-content ul { + list-style: none; + padding-left: 0px; +} +.item-content ul>li { + font-size: 0.9rem; + color: var(--grey); + font-weight: 700; +} +/* Misc */ +.card-shadow { + -webkit-box-shadow: 1px 3px 5px 0px rgba(222, 222, 222, 1); + -moz-box-shadow: 1px 3px 5px 0px rgba(222, 222, 222, 1); + box-shadow: 1px 3px 5px 0px rgba(222, 222, 222, 1); +} +.table td, +.table th { + border-top: 1px solid #eceff2; +} +.crm_scroll_table { + max-height: 395px; + overflow-y: auto; +} +.recent_activity_div .crm_scroll_table { + max-height: 435px; +} +.crm_scroll_table thead { + position: sticky; + top: 0; +} +.dashboard-card__stat_late:hover { + border-bottom-color: darkgray; +} +.dashboard-card__stat_waiting:hover { + border-bottom-color: darkgray; +} +.dashboard-card__stat_backorder:hover { + border-bottom-color: darkgray; +} + +.location_value { + font-weight: 700; + font-size: 1.2rem; + text-align: center; +} +.btn__custom-info{ + background-color: #e9ebf6; + color: #070920; + border-radius: 1.5rem; + padding: 0.15rem 2rem; + border: 1px solid #dddfea; + position: absolute; + right: 0px; + top: -3px; +} +.btn__custom-info:hover{ + background-color: #dddfea; + border: 1px solid #d2d4dd; + transition: all 0.3s ease-in-out; +} +.btn_info { + position: absolute; + top: 18px; + right: 17px; + background-color: #e9ebf6; + height: 28px; + width: 26px; + border-radius: 24%; +} +#top_product_selection { + position: absolute; + top: 18px; +} +#top_product_button { + position: absolute; + top: 1px; + right: 63px; +} +#product_move_select { + position: absolute; + top: 1px; + right: 63px; +} +#product_move_selection { + position: absolute; + top: 18px; +} +#stock_move_select { + position: absolute; + top: 1px; + right: 63px; +} +#stock_moves_selection { + position: absolute; + top: 18px; +} +.location_table_value{ +text-align: center; +} +/* X-Small devices (portrait phones, less than 576px)*/ +@media (max-width: 575.98px) { + #top_product_selection{ + width: 180%; + margin-left: -100%; + } + #product_move_selection{ + width: 180%; + margin-left: -100%; + } + #stock_move_selection{ + width: 180%; + margin-left: -100%; + } +} +.tile-container { + padding: 1rem; + display: flex; + justify-content: space-around; + align-items: center; + flex-wrap: wrap; + border-radius: 0.5rem; + background-image: url('./assets/background.png'); + background-repeat: no-repeat; + background-size: cover; + background-position-x: right; +} +.tile-container:hover { + opacity: 0.9; + cursor: pointer; + transition: all 0.4s ease-in-out; +} +.title-container__icon-container { + padding: 1.3rem 1rem; + border-radius: 0.5rem; +} +.title-container__icon { + font-size: 1.5rem; +} +.title-container__count { + font-size: 1.6rem; + font-weight: 600; +} +.title-container__title { + font-size: 1rem; + font-weight: 600; +} +/* Colors */ +.red-bkg { + background-color: #FFE1E2; +} +.red-font { + color: #E8565E; +} +.blue-bkg { + background-color: #C2D5FF; +} +.blue-font { + color: #225AE3; +} +.green-bkg { + background-color: #BDE4E0; +} +.green-font { + color: #2CA79A; +} +.pink-bkg { + background-color: #FFE4EF; +} +.pink-font { + color: #CE3372; +} +.yellow-bkg { + background-color: #F9ECC6; +} +.yellow-font { + color: #CBA846; +} +.white-bkg { + background-color: #FFFFFF; +} +.white-font { + color: #FFFFFF; +} +/*Second Section CSS */ +.card-contianer__header { + background-color: #37274B; + padding: 0.4rem; + border-top: 3px solid #D84315; +} +.card-container__content { + padding: 1rem; +} +.card-container__normal-header { + font-size: 1.2rem; + color: #000000; + font-weight: 600; +} +.card-container__header-text { + font-size: 1.2rem; + color: #FFFFFF; + font-weight: 400; + text-align: center; +} +.dashboard-card { + box-shadow: rgba(60, 64, 67, 0.3) 0px 1px 2px 0px, rgba(60, 64, 67, 0.15) 0px 2px 6px 2px; + padding: 1.5rem; + margin: 0.5rem auto; + min-height: 185px; + display: flex !important; + justify-content: space-between !important; + align-items: flex-start !important; +} +.dashboard-card--border-top { + border-top: 5px solid #000; +} +.dashboard-card--border-top-red { + border-color: #D32F2F; +} +.dashboard-card--border-top-blue { + border-color: #2962FF; +} +.dashboard-card--border-top-green { + border-color: #00FF00; +} +.dashboard-card--border-top-purple { + border-color: #800080; +} +.dashboard-card--border-top-brown { + border-color: #964B00; +} +.dashboard-card--border-top-pink { + border-color: #FFC0CB; +} +.dashboard-card--border-top-grey { + border-color: #696969; +} +.dashboard-card--border-top-black { + border-color: black; +} +.dashboard-card--border-top-rebecca { + border-color: #663399; +} +.dashboard-card--border-top-steel { + border-color: #607D8B; +} +.dashboard-card--border-top-orange { + border-color: #FFA500; +} +.dashboard-card__title { + font-weight: bold; + display: block; + margin-top: 0.5rem; +} +.dashboard-card__count { + font-size: 3rem; +} +.dashboard-card__stats { + list-style: none; + padding-left: 0; + width: 50% +} +.dashboard-card__stat_late { + padding: 0.5rem 0rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} +.dashboard-card__stat_waiting { + padding: 0.5rem 0rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} +.dashboard-card__stat_backorder { + padding: 0.5rem 0rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); +} +.dashboard-card__stat-count_late { + min-width: 25px; + min-height: 20px; + background-color: rgba(0, 0, 0, 0.1); + font-size: 0.9rem; + font-weight: bold; + color: rgba(0, 0, 0, 0.6); + display: flex; + justify-content: center; + align-items: center; + border-radius: 50%; +} +.dashboard-card__stat-count_waiting { + min-width: 25px; + min-height: 20px; + background-color: rgba(0, 0, 0, 0.1); + font-size: 0.9rem; + font-weight: bold; + color: rgba(0, 0, 0, 0.6); + display: flex; + justify-content: center; + align-items: center; + border-radius: 50%; +} +.dashboard-card__stat-count_backorder { + min-width: 25px; + min-height: 20px; + background-color: rgba(0, 0, 0, 0.1); + font-size: 0.9rem; + font-weight: bold; + color: rgba(0, 0, 0, 0.6); + display: flex; + justify-content: center; + align-items: center; + border-radius: 50%; +} +.oh_dashboards { +font-family: 'Raleway', sans-serif; +} +.main-part{ +width:100%; +margin:0 auto; +text-align: center; +padding: 0px 5px; +} +.cpanel{ +width:32%; +display: inline-block; +background-color:#34495E; +color:#fff; +margin-top: 50px; +} +.icon-part i{ +font-size: 30px; +padding:10px; +border:1px solid #fff; +border-radius:50%; +margin-top:-25px; +margin-bottom: 10px; +background-color:#34495E; +} +.icon-part p{ +margin:0px; +font-size: 20px; +padding-bottom: 10px; +} +.card-content-part{ +background-color: #2F4254; +padding: 5px 0px; +} +.cpanel .card-content-part:hover{ +background-color: #5a5a5a; +cursor: pointer; +} +.card-content-part a{ +color:#fff; +text-decoration: none; +} +.cpanel-green .icon-part,.cpanel-green .icon-part i{ +background-color: #16A085; +} +.cpanel-green .card-content-part{ +background-color: #149077; +} +.cpanel-orange .icon-part,.cpanel-orange .icon-part i{ +background-color: #F39C12; +} +.cpanel-orange .card-content-part{ +background-color: #DA8C10; +} +.cpanel-blue .icon-part,.cpanel-blue .icon-part i{ +background-color: #2980B9; +} +.cpanel-blue .card-content-part{ +background-color:#2573A6; +} +.cpanel-red .icon-part,.cpanel-red .icon-part i{ +background-color:#E74C3C; +} +.cpanel-red .card-content-part{ +background-color:#CF4436; +} +.cpanel-skyblue .icon-part,.cpanel-skyblue .icon-part i{ +background-color:#8E44AD; +} +.cpanel-skyblue .card-content-part{ +background-color:#803D9B; +} +.icon-part{ + height: 121px; + background-color: #16A085; + min-height: 120px; +} +.col-lg-3:hover { + -ms-transform: scale(1); + /* IE 9 */ + -webkit-transform: scale(1); + /* Safari 3-8 */ + transform: scale(1.05); +} +option { + color: black; +} diff --git a/inventory_stock_dashboard_odoo/static/src/js/dashboard.js b/inventory_stock_dashboard_odoo/static/src/js/dashboard.js new file mode 100644 index 000000000..f028dd916 --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/src/js/dashboard.js @@ -0,0 +1,1023 @@ +/** @odoo-module **/ +import { registry } from "@web/core/registry"; +import { onWillStart, onMounted, useState, useRef } from "@odoo/owl"; +import { useService } from "@web/core/utils/hooks"; +const actionRegistry = registry.category("actions"); +import { _t } from "@web/core/l10n/translation"; +const { DateTime } = luxon; +var op_type; +/* This class represents dashboard in Inventory. */ +class Dashboard extends owl.Component{ + setup() { + this.orm = useService('orm') + this.rootRef = useRef('root') + this.state = useState({ + countDictionary : [], + op_types: [], + operations: [], + colors: [], + late_status: [], + waiting_status: [], + backorder_status: [], + MoveData: [], + operationDict: [], + category: [], + categCountDict: [], + categName: [], + location_data: [], + monthly_stock: [], + monthly_stock_count: [], + out_stock: [], + out_stock_count: [], + dead_stock_name: [], + }); + // When the component is about to start, fetch data in tiles + onWillStart(async () => { + this.props.title = 'Dashboard'; + }); + // When the component is mounted, render various charts + onMounted(async () => { + await this.render_graphs(); + }); + } + render_graphs(){ + this.render_operation_tile(); + this.render_top_product_bar_graph(); + this.render_stock_moves(); + this.render_product_move_graph_this_month(); + this.render_product_category(); + this.render_storage_location(); + this.render_out_of_stock_graph(); + this.render_dead_of_stock_graph(); + } + // Fetch data operation type tiles and graphs + render_operation_tile(){ + var result = this.orm.call('stock.picking', 'get_operation_types', [] + ).then( (result) => { + op_type = result[3]; + const colors = ["red", "blue","green","orange","purple","steel","rebecca","brown","pink","grey","black"]; + this.state.op_types = result[0]; + this.state.operations = result[3]; + this.state.colors = colors; + this.state.late_status = result[1]; + this.state.waiting_status = result[2]; + this.state.backorder_status = result[4]; + var ctx = this.rootRef.el.querySelector("#operation") + var name = Object.values(result[3]) + var count = Object.values(result[0]) + var operationDict = {} + for (var i = 0; i < name.length; i++) { + var operation = name[i]; + var operationCount = count[i]; + operationDict[operation] = operationCount; + } + this.state.operationDict = operationDict + this.rootRef.el.querySelector('#operation_type_table').style.display = 'none'; + var myChart = new Chart(ctx, { + type: 'bar', + data: { + labels: name, + datasets: [{ + label: 'Count', + data: count, + backgroundColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + borderColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, // Specify bar border width + type: 'bar', // Set this data to a line chart + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + responsive: true, // Instruct chart js to respond nicely. + maintainAspectRatio: false, // Add to prevent default behaviour of full-width/height + } + }); + }); + } + // Top moving products bar graph + async render_top_product_bar_graph(){ + const ctx = this.rootRef.el.querySelector("#canvaspie"); + await this.orm.call("stock.move", "get_the_top_products", [] + ).then( (result) => { + var products = result.products + var count = result.count; + var countDictionary = {}; + for (var i = 0; i < products.length; i++) { + var product = products[i]; + var productCount = count[i]; + countDictionary[product] = productCount; + } + this.state.countDictionary = countDictionary; + this.rootRef.el.querySelector("#pro_info").style.display = 'none'; + var myChart = new Chart(ctx, { + type: 'bar', + data: { + labels: products, + datasets: [{ + label: 'Count', + data: count, + backgroundColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + borderColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'bar', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + responsive: true, + maintainAspectRatio: false, + } + }); + }); + } + // Stock moves pie graph + async render_stock_moves(){ + this.orm.call("stock.move", "get_stock_moves", [] + ).then( (result) => { + var name = result.name + var count = result.count; + var stockMoveDict = {} + for (var i = 0; i < name.length; i++) { + var location = name[i]; + var stockCount = count[i]; + stockMoveDict[location] = stockCount; + } + this.state.MoveData = stockMoveDict; + this.rootRef.el.querySelector('#stock_move_table').style.display = 'none'; + var ctx = this.rootRef.el.querySelector("#stock_moves"); + var myChart = new Chart(ctx, { + type: 'pie', + data: { + labels: name, + datasets: [{ + label: 'Count', + data: count, + backgroundColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + borderColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'pie', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + responsive: true, + maintainAspectRatio: false, + } + }); + }); + } + // Product move line graph + render_product_move_graph_this_month(){ + this.orm.call("stock.move.line", "get_product_moves", [] + ).then((result) => { + var ctx = this.rootRef.el.querySelector("#product_move_graph"); + var name = result[0].name + var count = result[0].count + var category_name = result[1].category_name + var category_id = result[1].category_id + this.state.category = category_name + this.state.categoryId = category_id + var option = this.state.categoryId[0] + this.rootRef.el.querySelector('#product_move_table').style.display = 'none'; + this.orm.call("stock.move.line", "product_move_by_category", [option] + ).then( (result) => { + var ctx = this.rootRef.el.querySelector("#product_move_graph"); + var name = result.name + var count = result.count; + this.state.monthly_stock = name + this.state.monthly_stock_count = count + this.rootRef.el.querySelector("#product_move_table").style.display = 'none'; + var myChart = new Chart(ctx, { + type: 'line', + data: { + labels: name, + datasets: [{ + label: 'Quantity Done', + data: count, + backgroundColor: '#003f5c', + borderColor: '#003f5c', + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'line', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + responsive: true, + maintainAspectRatio: false, + } + }); + }); + }); + } + // Product categories doughnut graph + render_product_category(){ + this.orm.call("stock.picking", "get_product_category", []). + then((result) => { + var ctx = this.rootRef.el.querySelector("#product_category"); + var name = result.name + var count = result.count + var categCountDict = {} + this.state.categCountDict = name; + this.state.categName = count; + this.rootRef.el.querySelector("#category_table").style.display = 'none'; + var myChart = new Chart(ctx, { + type: 'doughnut', + data: { + labels: name, + datasets: [{ + label: 'Quantity Done', + data: count, + backgroundColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + borderColor: [ + "#003f5c", + ], + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'doughnut', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + responsive: true, + maintainAspectRatio: false, + } + }); + }); + } + // Location-on hand table + render_storage_location(){ + this.orm.call("stock.picking", "get_locations", + ).then((result) => { + this.state.location_data = result + }); + } + // Dead stock graph + render_dead_of_stock_graph(){ + this.orm.call("stock.move", "get_dead_of_stock",[] + ).then( (result) => { + if (result) { + this.rootRef.el.querySelector("#dead_stock").style.display = 'block'; + var ctx = this.rootRef.el.querySelector("#dead_stock_graph"); + var name = result.product_name + var count = result.total_quantity + this.state.dead_stock_name = name + this.state.dead_stock_count = count + this.rootRef.el.querySelector('#dead_stock_table').style.display = 'none'; + var myChart = new Chart(ctx, { + type: 'line', + data: { + labels: name, + datasets: [{ + label: 'Current Stock', + data: count, + backgroundColor: '#003f5c', + borderColor: '#003f5c', + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'line', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + responsive: true, + maintainAspectRatio: false, + } + }); + } + else{ + this.rootRef.el.querySelector('#dead_stock').style.display = 'none'; + } + }); + } + // Out of stock graph + render_out_of_stock_graph(){ + this.orm.call("stock.quant", "get_out_of_stock",[] + ).then( (result) => { + if (result) { + var ctx = this.rootRef.el.querySelector("#out_of_stock_graph"); + var name = result.product_name + var count = result.total_quantity + this.state.out_stock = name + this.state.out_stock_count = count + this.rootRef.el.querySelector("#out_of_stock").style.display = 'block'; + this.rootRef.el.querySelector("#out_of_stock_table").style.display = 'none'; + var myChart = new Chart(ctx, { + type: 'bar', + data: { + labels: name, + datasets: [{ + label: 'Current Stock', + data: count, + backgroundColor: '#003f5c', + borderColor: '#003f5c', + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'bar', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + responsive: true, + maintainAspectRatio: false, + } + }); + } + else{ + this.rootRef.el.querySelector("#out_of_stock").style.display = 'none'; + } + }); + } + // Top ten products details button click + async onclick_top_product_info(event) { + var pro_info = this.rootRef.el.querySelector("#pro_info"); + if (pro_info.style.display === "none") { + pro_info.style.display = 'block'; + } else { + pro_info.style.display = 'none'; + } + } + // Stock move details button click + onclick_stock_move_info() { + var move_info = this.rootRef.el.querySelector("#stock_move_table"); + if (move_info.style.display === "none") { + move_info.style.display = 'block'; + } else { + move_info.style.display = 'none'; + } + } + // Operation types table details button click + onclick_operation_type_info() { + var operation_type_table = this.rootRef.el.querySelector("#operation_type_table"); + if (operation_type_table.style.display === "none") { + operation_type_table.style.display = 'block'; + } else { + operation_type_table.style.display = 'none'; + } + } + // Product category graph details button click + onclick_product_category_info() { + var category = this.rootRef.el.querySelector("#category_table"); + if (category.style.display === "none") { + category.style.display = 'block'; + } else { + category.style.display = 'none'; + } + } + // Product move info button + onclick_product_move_info() { + var category = this.rootRef.el.querySelector("#product_move_table"); + if (category.style.display === "none") { + category.style.display = 'block'; + } else { + category.style.display = 'none'; + } + } + // Out of stock table details button + onclick_out_of_stock_info() { + var out_of_stock_table = this.rootRef.el.querySelector("#out_of_stock_table"); + if (out_of_stock_table.style.display === "none") { + out_of_stock_table.style.display = 'block'; + } else { + out_of_stock_table.style.display = 'none'; + } + } + // Dead stock table details button + onclick_dead_stock_info() { + var dead_stock_table = this.rootRef.el.querySelector("#dead_stock_table"); + if (dead_stock_table.style.display === "none") { + dead_stock_table.style.display = 'block'; + } else { + dead_stock_table.style.display = 'none'; + } + } + // Top product selection filters + onchange_top_product_selection(events){ + var option = events.currentTarget.value; + // Top product moves in 10 days + if (option == 'top_last_10_days'){ + this.orm.call("stock.move", "top_products_last_ten", [] + ).then((result) => { + var ctx = this.rootRef.el.querySelector("#canvaspie"); + var products = result.products + var count = result.count; + var countDictionary = {}; + for (var i = 0; i < products.length; i++) { + var product = products[i]; + var productCount = count[i]; + countDictionary[product] = productCount; + } + this.state.countDictionary = countDictionary; + this.rootRef.el.querySelector("#pro_info").style.display = 'none'; + var myChart = new Chart(ctx, { + type: 'bar', + data: { + labels: products, + datasets: [{ + label: 'Count', + data: count, + backgroundColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + borderColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'bar', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + responsive: true, + maintainAspectRatio: false, + } + }); + }); + } + // Top product moves in 30 days + if (option == 'top_last_30_days'){ + this.orm.call("stock.move", "top_products_last_thirty", [] + ).then( (result) => { + var ctx = this.rootRef.el.querySelector("#canvaspie"); + var products = result.products + var count = result.count; + var countDictionary = {}; + for (var i = 0; i < products.length; i++) { + var product = products[i]; + var productCount = count[i]; + countDictionary[product] = productCount; + } + this.state.countDictionary = countDictionary; + this.rootRef.el.querySelector("#pro_info").style.display = 'none'; + var myChart = new Chart(ctx, { + type: 'bar', + data: { + labels: products, + datasets: [{ + label: 'Count', + data: count, + backgroundColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + borderColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'bar', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + responsive: true, + maintainAspectRatio: false, + } + }); + }); + } + // Top product moves in 3 months + if (option == 'top_last_3_month'){ + this.orm.call("stock.move", "top_products_last_three_months", [] + ).then( (result) => { + var ctx = this.rootRef.el.querySelector("#canvaspie"); + var products = result.products + var count = result.count; + var countDictionary = {}; + for (var i = 0; i < products.length; i++) { + var product = products[i]; + var productCount = count[i]; + countDictionary[product] = productCount; + } + this.state.countDictionary = countDictionary; + this.rootRef.el.querySelector("#pro_info").style.display = 'none'; + var myChart = new Chart(ctx, { + type: 'bar', + data: { + labels: products, + datasets: [{ + label: 'Count', + data: count, + backgroundColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + borderColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'bar', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + responsive: true, + maintainAspectRatio: false, + } + }); + }); + } + // Top product moves in last year + if (option == 'top_last_year'){ + this.orm.call("stock.move", "top_products_last_year",[] + ).then( (result) => { + var ctx = this.rootRef.el.querySelector("#canvaspie"); + var products = result.products + var count = result.count; + var countDictionary = {}; + for (var i = 0; i < products.length; i++) { + var product = products[i]; + var productCount = count[i]; + countDictionary[product] = productCount; + } + this.state.countDictionary = countDictionary; + this.rootRef.el.querySelector("#pro_info").style.display = 'none'; + var myChart = new Chart(ctx, { + type: 'bar', + data: { + labels: products, + datasets: [{ + label: 'Count', + data: count, + backgroundColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + borderColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'bar', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + responsive: true, + maintainAspectRatio: false, + } + }); + }); + } + } + // Stock moves filter + async onchange_stock_moves_selection(events){ + var option = events.currentTarget.value; + // Stock moves in 10 days + if (option == 'last_10_days'){ + this.orm.call("stock.move", "stock_move_last_ten_days", [option] + ).then( (result) => { + var ctx = this.rootRef.el.querySelector("#stock_moves"); + var name = result.name + var count = result.count; + var stockMoveDict = {} + for (var i = 0; i < name.length; i++) { + var location = name[i]; + var stockCount = count[i]; + stockMoveDict[location] = stockCount; + } + this.state.MoveData = stockMoveDict; + var myChart = new Chart(ctx, { + type: 'pie', + data: { + labels: name, + datasets: [{ + label: 'Count', + data: count, + backgroundColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + borderColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'pie', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + responsive: true, + maintainAspectRatio: false, + } + }); + }); + } + // Stock moves in current month + if (option == 'this_month'){ + this.orm.call("stock.move", "this_month",[option] + ).then( (result) => { + var ctx = this.rootRef.el.querySelector("#stock_moves"); + var name = result.name + var count = result.count; + var stockMoveDict = {} + for (var i = 0; i < name.length; i++) { + var location = name[i]; + var stockCount = count[i]; + stockMoveDict[location] = stockCount; + } + this.state.MoveData = stockMoveDict; + this.rootRef.el.querySelector("#stock_move_table").style.display = 'none'; + var myChart = new Chart(ctx, { + type: 'pie', + data: { + labels: name, + datasets: [{ + label: 'Count', + data: count, + backgroundColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + borderColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'pie', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + responsive: true, + maintainAspectRatio: false, + } + }); + }); + } + // Stock moves in last 3 months + if (option == 'last_3_month'){ + this.orm.call("stock.move", "last_three_month", [option] + ).then( (result) => { + var ctx = this.rootRef.el.querySelector("#stock_moves"); + var name = result.name + var count = result.count; + var stockMoveDict = {} + for (var i = 0; i < name.length; i++) { + var location = name[i]; + var stockCount = count[i]; + stockMoveDict[location] = stockCount; + } + this.state.MoveData = stockMoveDict; + this.rootRef.el.querySelector("#stock_move_table").style.display = 'none'; + var myChart = new Chart(ctx, { + type: 'pie', + data: { + labels: name, + datasets: [{ + label: 'Count', + data: count, + backgroundColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + borderColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'pie', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + responsive: true, + maintainAspectRatio: false, + } + }); + }); + } + // Stock moves in last year + else if (option == 'last_year'){ + this.orm.call("stock.move", "last_year", [option] + ).then( (result) => { + var ctx = this.rootRef.el.querySelector("#stock_moves"); + var name = result.name + var count = result.count; + this.rootRef.el.querySelector("#stock_move_table").style.display = 'none'; + var stockMoveDict = {} + for (var i = 0; i < name.length; i++) { + var location = name[i]; + var stockCount = count[i]; + stockMoveDict[location] = stockCount; + } + this.state.MoveData = stockMoveDict; + var myChart = new Chart(ctx, { + type: 'pie', + data: { + labels: name, + datasets: [{ + label: 'Count', + data: count, + backgroundColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + borderColor: [ + "#003f5c","#2f4b7c","#f95d6a","#665191", + "#d45087","#ff7c43","#ffa600","#a05195", + "#6d5c16","#CCCCFF" + ], + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'pie', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + responsive: true, + maintainAspectRatio: false, + } + }); + }); + } + } + // Product move selection + onchange_product_moves_selection(events){ + var option = $(events.target).val(); + this.orm.call("stock.move.line", "product_move_by_category", [option] + ).then( (result) => { + var ctx = this.rootRef.el.querySelector("#product_move_graph"); + var name = result.name + var count = result.count; + this.state.monthly_stock = name + this.state.monthly_stock_count = count + this.rootRef.el.querySelector("#product_move_table").style.display = 'none'; + var myChart = new Chart(ctx, { + type: 'line', + data: { + labels: name, + datasets: [{ + label: 'Quantity Done', + data: count, + backgroundColor: '#003f5c', + borderColor: '#003f5c', + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'line', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + responsive: true, + maintainAspectRatio: false, + } + }); + }); + } + // On clicking tiles + async onclick_tiles (f) { + var id = parseInt(f.currentTarget.getAttribute('id')); + var options = { + on_reverse_breadcrumb: this.on_reverse_breadcrumb, + }; + this.env.services['action'].doAction({ + name: _t(op_type[f.currentTarget.getAttribute('id')]), + type: 'ir.actions.act_window', + res_model: 'stock.picking', + views: [[false, 'list'], [false, 'form']], + view_mode: 'tree,form,calendar', + domain: [['picking_type_id', '=', id]], + target: 'current', + }, options); + } + // On clicking tile of late status + onclick_late_status (f) { + f.stopPropagation(); + var id = parseInt(f.currentTarget.getAttribute('id')); + var options = { + on_reverse_breadcrumb: this.on_reverse_breadcrumb, + }; + this.env.services['action'].doAction({ + name: _t(op_type[id]+'/Late'), + type: 'ir.actions.act_window', + res_model: 'stock.picking', + view_mode: 'tree,form,calendar', + views: [[false, 'list'],[false, 'form']], + domain: [['picking_type_id', '=', id],['state', 'in', ['assigned', 'waiting', 'confirmed']], + ['scheduled_date', '<=', DateTime.local().toFormat('yyyy-MM-dd')],], + target: 'current', + }, options) + } + // Onc licking of tile waiting status + onclick_waiting_status (f) { + f.stopPropagation(); + var id = parseInt(f.currentTarget.getAttribute('id')); + var options = { + on_reverse_breadcrumb: this.on_reverse_breadcrumb, + }; + this.env.services['action'].doAction({ + name: _t(op_type[id]+'/Waiting'), + type: 'ir.actions.act_window', + res_model: 'stock.picking', + view_mode: 'tree,form,calendar', + views: [[false, 'list'],[false, 'form']], + domain: [['picking_type_id', '=', id],['state', '=', 'confirmed']], + target: 'current', + }, options) + } + // On clicking of tile backorder status + onclick_backorders_status (f) { + f.stopPropagation(); + var id = parseInt(f.currentTarget.getAttribute('id')); + var options = { + on_reverse_breadcrumb: this.on_reverse_breadcrumb, + }; + this.env.services['action'].doAction({ + name: _t(op_type[id]+'/Backorders'), + type: 'ir.actions.act_window', + res_model: 'stock.picking', + view_mode: 'tree,form,calendar', + views: [[false, 'list'],[false, 'form']], + domain: [['picking_type_id', '=', id],['backorder_id', '!=', false]], + target: 'current', + }, options) + } +} +Dashboard.template = "Dashboard"; +actionRegistry.add('inventory_dashboard_tag', Dashboard); diff --git a/inventory_stock_dashboard_odoo/static/src/xml/inventory_dashboard_template.xml b/inventory_stock_dashboard_odoo/static/src/xml/inventory_dashboard_template.xml new file mode 100644 index 000000000..5f1663337 --- /dev/null +++ b/inventory_stock_dashboard_odoo/static/src/xml/inventory_dashboard_template.xml @@ -0,0 +1,344 @@ + + + + +
+ +
+
+
+ +
+
+
+ + + + +
+
    + +
  • +
    +
    + Late +
    +
    + +
    +
    +
  • +
    + +
  • +
    +
    + Waiting +
    +
    + +
    +
    +
  • +
    + +
  • +
    +
    + Backorder +
    +
    + +
    +
    +
  • +
    +
+
+
+
+
+
+
+ +
+ +
+
+
+

Top Moving Products

+
+ +
+ + + + + + + + + + + + + +
+
+
+ +
+
+
+ +
+
+
+

Product Categories

+ + + + + + + + + + + + +
CategoriesOnhand Quantity
+
+
+
+ +
+
+
+ +
+
+
+

Product Moves By Category

+
+ +
+ + + + + + + + + + + + +
ProductsQuantity Done
+
+
+
+ +
+
+
+ +
+
+
+

Stock Moves By Location

+
+ +
+ + + + + + + + + + + + + +
+
+
+ +
+
+
+ +
+
+
+

Operation Types

+ + + + + + + + + + + + +
Operation TypesTransfer Count
+
+
+
+ +
+
+
+ +
+
+
+

Locations

+
+
+ + + + + + + + + + + + + + + +

Location

On Hand Quantity

+ + + +
+
+
+ + + + +
+
+
+
diff --git a/inventory_stock_dashboard_odoo/views/dashboard_menu.xml b/inventory_stock_dashboard_odoo/views/dashboard_menu.xml new file mode 100644 index 000000000..885a9664e --- /dev/null +++ b/inventory_stock_dashboard_odoo/views/dashboard_menu.xml @@ -0,0 +1,14 @@ + + + + + Dashboard + inventory_dashboard_tag + + + + diff --git a/inventory_stock_dashboard_odoo/views/res_config_settings_views.xml b/inventory_stock_dashboard_odoo/views/res_config_settings_views.xml new file mode 100644 index 000000000..ac94c298f --- /dev/null +++ b/inventory_stock_dashboard_odoo/views/res_config_settings_views.xml @@ -0,0 +1,51 @@ + + + + + res.config.settings.view.form.inherit.inventory.stock.dashboard.odoo + res.config.settings + + + + +
+

Dashboard

+
+
+
+ +
+
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+