diff --git a/purchase_dashboard_advanced/README.rst b/purchase_dashboard_advanced/README.rst new file mode 100644 index 000000000..e1c2737a0 --- /dev/null +++ b/purchase_dashboard_advanced/README.rst @@ -0,0 +1,49 @@ +.. 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 + +Purchase Dashboard +================== +A dashboard for keeping track and evaluate various aspects of spending on purchases. + +Installation +============ + - www.odoo.com/documentation/15.0/setup/install.html + - Install our custom addon + +License +------- +General Public License, Version 3 (LGPL v3). +(https://www.gnu.org/licenses/lgpl-3.0-standalone.html) + +Company +------- +* `Cybrosys Techno Solutions `__ + +Credits +------- +* Developers:(V15) Neethu U M, + Anfas Faisal K , + 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/purchase_dashboard_advanced/__init__.py b/purchase_dashboard_advanced/__init__.py new file mode 100644 index 000000000..7b2c59c1c --- /dev/null +++ b/purchase_dashboard_advanced/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# 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/purchase_dashboard_advanced/__manifest__.py b/purchase_dashboard_advanced/__manifest__.py new file mode 100644 index 000000000..f265ca28c --- /dev/null +++ b/purchase_dashboard_advanced/__manifest__.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# 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': "Purchase Dashboard", + 'version': '15.0.1.0.0', + 'category': 'Purchases', + 'summary': "Elevate your financial awareness with our comprehensive " + "Purchase Analysis Dashboard", + 'description': "Empower your financial insights with our all-in-one " + "Purchase Analysis Dashboard. Effortlessly track and " + "evaluate purchase expenditures on a monthly and yearly " + "basis, identify top and priority products, and stay " + "informed about upcoming purchase details", + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'website': "https://www.cybrosys.com", + 'depends': ['purchase'], + 'data': [ + 'views/purchase_dashboard_menus.xml' + ], + 'assets': { + 'web.assets_backend': [ + 'purchase_dashboard_advanced/static/src/js/dashboard.js', + 'purchase_dashboard_advanced/static/src/css/style.css', + 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.js', + ], + 'web.assets_qweb': [ + 'purchase_dashboard_advanced/static/src/xml/purchase_dashboard_templates.xml', + ], + }, + 'images': ['static/description/banner.png'], + 'license': "LGPL-3", + 'installable': True, + 'auto_install': False, + 'application': False, +} diff --git a/purchase_dashboard_advanced/doc/RELEASE_NOTES.md b/purchase_dashboard_advanced/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..3ca1a3c49 --- /dev/null +++ b/purchase_dashboard_advanced/doc/RELEASE_NOTES.md @@ -0,0 +1,7 @@ +## Module + +#### 02.11.2023 +#### Version 15.0.1.0.0 +#### ADD + +- Initial commit for Purchase Dashboard diff --git a/purchase_dashboard_advanced/models/__init__.py b/purchase_dashboard_advanced/models/__init__.py new file mode 100644 index 000000000..7b96ff098 --- /dev/null +++ b/purchase_dashboard_advanced/models/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# 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 purchase_order diff --git a/purchase_dashboard_advanced/models/purchase_order.py b/purchase_dashboard_advanced/models/purchase_order.py new file mode 100644 index 000000000..fb060f331 --- /dev/null +++ b/purchase_dashboard_advanced/models/purchase_order.py @@ -0,0 +1,657 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2023-TODAY Cybrosys Technologies() +# Author: Cybrosys Techno Solutions() +# +# 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 . +# +############################################################################# +import calendar +from datetime import datetime +from odoo import api, models + + +class PurchaseOrder(models.Model): + """ + Inherits the Purchase Order Model and Extends Its Functionality. + This class extends the Odoo Purchase Order model to provide custom methods + for retrieving various purchase-related data, including purchase data for + display in tiles, yearly, monthly, weekly, and today's purchase data, + top chart data, orders by month, purchase vendors, purchase vendor details, + pending purchase data, and upcoming purchase data. + """ + _inherit = 'purchase.order' + + @api.model + def get_purchase_data(self): + """ + Get purchase data for display in tiles. + This method retrieves data related to purchase orders, including + the count of purchase orders in 'purchase' and 'done' states, + the total purchase amount, the count of priority orders, and + the total count of vendors associated with purchase orders. + Returns: + dict: A dictionary containing the following purchase data: + - 'purchase_orders': Count of purchase orders. + - 'purchase_amount': Total purchase amount. + - 'priority_orders': Count of priority orders. + - 'vendors': Total count of vendors. + """ + orders = self.env['purchase.order'].search_count([('state', 'in', [ + 'purchase', 'done'])]) + priority_orders = self.env['purchase.order'].search_count([ + ('priority', '=', '1')]) + vendor_count = self.env['purchase.order'].search_count([ + ('state', 'in', ['purchase', 'done'])]) + return { + 'purchase_orders': orders, + 'purchase_amount': sum(order.amount_total for order in + self.env['purchase.order'].search( + [('state', 'in', ['purchase', + 'done'])])), + 'priority_orders': priority_orders, + 'vendors': vendor_count + } + + def get_yearly_data(self): + """ + Get yearly purchase data for the current company. + Returns: + dict: A dictionary containing yearly purchase data, including + purchase orders count, purchase amount, priority orders count, and + new vendor count compared to the previous year. + """ + company = self.env.company.id + current_year = datetime.now().year + # Query to get purchase orders count and amount for the current year + query = """ + SELECT COUNT(*) as po_count, SUM(amount_total) as po_sum + FROM purchase_order + WHERE company_id = %s + AND state IN ('purchase', 'done') + AND EXTRACT(YEAR FROM date_order) = %s + """ + self.env.cr.execute(query, (company, current_year)) + data = self.env.cr.dictfetchall() + # Query to get priority purchase orders count for the current year + query = """ + SELECT COUNT(*) as po_count + FROM purchase_order + WHERE company_id = %s + AND state IN ('purchase', 'done') + AND EXTRACT(YEAR FROM date_order) = %s + AND priority = '1' + """ + self.env.cr.execute(query, (company, current_year)) + priority_orders = self.env.cr.dictfetchall() + # Query to get vendor count for the previous year + query = """ + SELECT COUNT(DISTINCT partner_id) as vendor_count + FROM purchase_order + WHERE company_id = %s + AND state IN ('purchase', 'done') + AND EXTRACT(YEAR FROM date_order) = %s - 1 + """ + self.env.cr.execute(query, (company, current_year)) + previous_vendors = self.env.cr.dictfetchall()[0]['vendor_count'] + # Query to get vendor count for the current year + query = """ + SELECT COUNT(DISTINCT partner_id) as vendor_count + FROM purchase_order + WHERE company_id = %s + AND state IN ('purchase', 'done') + AND EXTRACT(YEAR FROM date_order) = %s + """ + self.env.cr.execute(query, (company, current_year)) + current_vendors = self.env.cr.dictfetchall()[0]['vendor_count'] + # Calculate new vendors compared to the previous year + new_vendors = current_vendors - previous_vendors + yearly = { + 'purchase_orders': data[0]['po_count'], + 'purchase_amount': data[0]['po_sum'] or 0, + 'priority_orders': priority_orders[0]['po_count'], + 'vendors': new_vendors or 0, + } + return yearly + + def get_monthly_data(self): + """Get monthly purchase data for the current company. + Returns: + dict: A dictionary containing monthly purchase data, including + purchase orders count, purchase amount, priority orders count, + vendor count, and new vendor IDs for the current month. + """ + company = self.env.company.id + query = """ + SELECT COUNT(*), SUM(amount_total) + FROM purchase_order po + WHERE company_id = %s + AND state IN ('purchase', 'done') + AND EXTRACT(YEAR from date_order) = + EXTRACT(YEAR from CURRENT_DATE) + AND EXTRACT(MONTH from date_order) = + EXTRACT(MONTH from CURRENT_DATE) + """ + self.env.cr.execute(query, (company,)) + data = self.env.cr.dictfetchall() + query = """ + SELECT COUNT(*) + FROM purchase_order po + WHERE company_id = %s + AND EXTRACT(YEAR from date_order) = + EXTRACT(YEAR from CURRENT_DATE) + AND EXTRACT(MONTH from date_order) = + EXTRACT(MONTH from CURRENT_DATE) + AND priority = '1' + """ + self.env.cr.execute(query, (company,)) + priority_orders = self.env.cr.dictfetchall() + query = """ + SELECT DISTINCT partner_id + FROM purchase_order po + WHERE company_id = %s + AND state IN ('purchase', 'done') + AND EXTRACT(month from date_order) < + EXTRACT(month FROM CURRENT_DATE) + """ + self.env.cr.execute(query, (company,)) + previous_vendors = self.env.cr.dictfetchall() + previous = [rec['partner_id'] for rec in previous_vendors] + query = """ + SELECT DISTINCT partner_id + FROM purchase_order po + WHERE company_id = %s + AND state IN ('purchase', 'done') + AND EXTRACT(YEAR from date_order) = + EXTRACT(YEAR FROM CURRENT_DATE) + AND EXTRACT(month from date_order) = + EXTRACT(month FROM CURRENT_DATE) + """ + self.env.cr.execute(query, (company,)) + vendors = self.env.cr.dictfetchall() + new_vendors = [rec['partner_id'] for rec in vendors if + rec['partner_id'] not in previous] + monthly = { + 'purchase_orders': data[0]['count'] if data else 0, + 'purchase_amount': data[0]['sum'] if data else 0, + 'priority_orders': priority_orders[0][ + 'count'] if priority_orders else 0, + 'vendors': len(new_vendors), + 'vendor_id': new_vendors, + } + return monthly + + def get_weekly_data(self): + """ + Get weekly purchase data for the current company. + Returns: + dict: A dictionary containing weekly purchase data, including + purchase orders count, purchase amount, priority orders count, and + vendor count. + """ + company = self.env.company.id + query = """ + SELECT COUNT(*), SUM(amount_total), COUNT(CASE WHEN priority = '1' + THEN 1 ELSE NULL END) + FROM purchase_order + WHERE company_id = %s + AND state IN ('purchase', 'done') + AND EXTRACT(YEAR from date_order) = + EXTRACT(YEAR from CURRENT_DATE) + AND EXTRACT(WEEK from date_order) = + EXTRACT(WEEK from CURRENT_DATE) + """ + self.env.cr.execute(query, [company]) + data = self.env.cr.fetchone() + query = """ + SELECT DISTINCT partner_id + FROM purchase_order + WHERE company_id = %s + AND state IN ('purchase', 'done') + AND EXTRACT(WEEK from date_order) < + EXTRACT(WEEK FROM CURRENT_DATE) + """ + self.env.cr.execute(query, [company]) + previous_vendors = self.env.cr.dictfetchall() + previous = [rec['partner_id'] for rec in previous_vendors] + query = """ + SELECT DISTINCT partner_id + FROM purchase_order + WHERE company_id = %s + AND state IN ('purchase', 'done') + AND EXTRACT(YEAR from date_order) = + EXTRACT(YEAR FROM CURRENT_DATE) + AND EXTRACT(WEEK from date_order) = + EXTRACT(WEEK FROM CURRENT_DATE) + """ + self.env.cr.execute(query, [company]) + vendors = self.env.cr.dictfetchall() + new_vendors = [rec['partner_id'] for rec in vendors if rec[ + 'partner_id'] not in previous] + weekly = { + 'purchase_orders': data[0], + 'purchase_amount': data[1], + 'priority_orders': data[2], + 'vendors': len(new_vendors) + } + return weekly + + def get_today_data(self): + """Get today's purchase data for the current company. + Returns: + dict: A dictionary containing today's purchase data, including + purchase orders count, purchase amount, priority orders count, + vendor count, and vendor IDs for new vendors today. + """ + company = self.env.company.id + # Get data for today + query = """ + SELECT + COUNT(*) AS purchase_orders, + SUM(amount_total) AS purchase_amount, + COUNT(*) FILTER (WHERE priority = '1') AS priority_orders + FROM purchase_order + WHERE + company_id = %s + AND state IN ('purchase', 'done') + AND date_order::date = CURRENT_DATE + """ + self.env.cr.execute(query, (company,)) + today_data = self.env.cr.dictfetchall()[0] + # Get new vendors for today + query = """ + SELECT DISTINCT po.partner_id + FROM purchase_order po + LEFT JOIN purchase_order prior_po + ON po.partner_id = prior_po.partner_id + AND prior_po.company_id = %s + AND prior_po.state IN ('purchase', 'done') + AND prior_po.date_order::date < CURRENT_DATE + WHERE + po.company_id = %s + AND po.state IN ('purchase', 'done') + AND po.date_order::date = CURRENT_DATE + AND prior_po.partner_id IS NULL + """ + self.env.cr.execute(query, (company, company)) + new_vendors = [r['partner_id'] for r in self.env.cr.dictfetchall()] + return { + 'purchase_orders': today_data['purchase_orders'], + 'purchase_amount': today_data['purchase_amount'], + 'priority_orders': today_data['priority_orders'], + 'vendors': len(new_vendors), + 'vendor_id': new_vendors, + } + + @api.model + def get_select_mode_data(self, args): + """Get data based on the selected filters + Returns: + dict or False: A dictionary containing the corresponding purchase + data based on the selected filter or False if the filter is invalid. + """ + data = { + 'this_year': self.get_yearly_data, + 'this_month': self.get_monthly_data, + 'this_week': self.get_weekly_data, + 'today': self.get_today_data, + }.get(args) + return data() if data else False + + def execute_query(self, query, args): + """ Execute a database query and return the results based on the + provided arguments. + Returns: + list: A list of results based on the query and arguments.""" + self._cr.execute(query) + results = self._cr.dictfetchall() + final = [] + if args == 'top_product': + final = [[record.get('total_quantity') for record in results], + [record.get('product_name') for record in results]] + elif args == 'top_vendor': + final = [[record.get('count') for record in results], + [record.get('name') for record in results]] + elif args == 'top_rep': + final = [[record.get('count') for record in results], + [record.get('name') for record in results]] + return final + + @api.model + def get_top_chart_data(self, args): + """ + Get top chart data (e.g., top products, top vendors, + top representatives). + Returns: + list: A list of top chart data, including quantities or counts and + names. + """ + company_id = self.env.company.id + if args == 'top_product': + query = ''' + SELECT DISTINCT(product_template.name) as product_name, + SUM(product_qty) as total_quantity + FROM purchase_order_line + INNER JOIN product_product ON product_product.id = + purchase_order_line.product_id + INNER JOIN product_template ON product_product.product_tmpl_id = + product_template.id + WHERE purchase_order_line.company_id = %s + GROUP BY product_template.id + ORDER BY total_quantity DESC + LIMIT 10 + ''' % company_id + elif args == 'top_vendor': + query = ''' + SELECT partner.name, COUNT(po.id) as count + FROM purchase_order po + JOIN res_partner partner ON po.partner_id = partner.id + WHERE po.company_id = %s + GROUP BY partner.name + ORDER BY count DESC + LIMIT 10 + ''' % company_id + elif args == 'top_rep': + query = ''' + SELECT partner.name, COUNT(po.id) as count + FROM purchase_order po + JOIN res_users users ON po.user_id = users.id + JOIN res_partner partner ON users.partner_id = partner.id + WHERE po.company_id = %s + GROUP BY partner.name + ORDER BY count DESC + LIMIT 10 + ''' % company_id + final = self.execute_query(query, args) + return final + + @api.model + def get_orders_by_month(self): + """ + Get monthly purchase orders count for the current company. + Returns: + dict: A dictionary containing monthly purchase orders count + and month names. + """ + query = """select count(*), EXTRACT(month from date_order) as dates + from purchase_order po + where company_id = %s and state = 'purchase' + group by dates""" % self.env.company.id + self.env.cr.execute(query, (self.env.company.id,)) + cr = self.env.cr.dictfetchall() + month = [] + for rec in cr: + month.append(int(rec['dates'])) + rec.update({ + 'count': rec['count'], + 'dates': calendar.month_name[int(rec['dates'])], + 'month': int(rec['dates']) + }) + for rec in range(1, 13): + if rec not in month: + cr.append({ + 'count': 0, + 'dates': calendar.month_name[rec], + 'month': rec + }) + cr = sorted(cr, key=lambda i: i['month']) + return { + 'count': [rec['count'] for rec in cr], + 'dates': [rec['dates'] for rec in cr] + } + + @api.model + def purchase_vendors(self): + """Get a list of purchase vendors for the current company. + Returns: + dict: A dictionary containing partner IDs and partner names. + """ + company_id = self.env.company.id + query = """ + SELECT partner.id, partner.name + FROM purchase_order po + INNER JOIN res_partner partner ON po.partner_id = partner.id + WHERE po.company_id = %s + GROUP BY partner.id + """ + self._cr.execute(query, (company_id,)) + partners = self._cr.dictfetchall() + partner_ids = [partner['id'] for partner in partners] + partner_names = [partner['name'] for partner in partners] + return {'partner_id': partner_ids, 'partner_name': partner_names} + + @api.model + def purchase_vendor_details(self, args): + """ + Get vendor analysis data for a specific vendor. + Returns: + dict: A dictionary containing purchase amount, purchase order count, + draft amount, draft order count, approve amount, approve order + count, cancel amount, cancel order count, and month dates. + """ + company_id = self.env.company.id + partner = int(args) if args else 1 + query = """ + SELECT count(po.id),SUM(po.amount_total), EXTRACT(MONTH from + po.date_order) as dates + FROM purchase_order po + JOIN res_partner ON res_partner.id = po.partner_id + WHERE po.company_id = %s and po.partner_id = %s + GROUP BY dates + """ + self._cr.execute(query, (company_id, partner)) + partner_orders = self._cr.dictfetchall() + query_draft = """ + SELECT count(po.id),SUM(po.amount_total), EXTRACT(MONTH from + po.date_order) as dates + FROM purchase_order po + JOIN res_partner ON res_partner.id = po.partner_id + WHERE po.state in ('draft', 'sent') and po.company_id = %s and + po.partner_id = %s + GROUP BY dates + """ + self._cr.execute(query_draft, (company_id, partner)) + draft_orders = self._cr.dictfetchall() + approve_qry = """ + SELECT count(po.id),SUM(po.amount_total), EXTRACT(MONTH from + po.date_order) as dates + FROM purchase_order po + JOIN res_partner ON res_partner.id = po.partner_id + WHERE po.state = 'to approve' and po.company_id = %s and + po.partner_id = %s + GROUP BY dates + """ + self._cr.execute(approve_qry, (company_id, partner)) + approve_orders = self._cr.dictfetchall() + cancel_qry = """ + SELECT count(po.id),SUM(po.amount_total), EXTRACT(MONTH from + po.date_order) as dates + FROM purchase_order po + JOIN res_partner ON res_partner.id = po.partner_id + WHERE po.state = 'cancel' and po.company_id = + %s and po.partner_id = %s + GROUP BY dates + """ + self._cr.execute(cancel_qry, (company_id, partner)) + cancel_orders = self._cr.dictfetchall() + all_orders = { + 'partner_orders': partner_orders, 'draft_orders': draft_orders, + 'approve_orders': approve_orders, 'cancel_orders': cancel_orders} + for order_type, order_list in all_orders.items(): + order_months = [] + for rec in order_list: + order_months.append(int(rec.get('dates'))) + for rec in range(1, 13): + if rec not in order_months: + vals = {'sum': 0.0, 'dates': rec, 'count': 0} + order_list.append(vals) + all_orders[order_type] = sorted( + order_list, key=lambda order: order['dates']) + value = { + 'purchase_amount': [record.get('sum') for record in partner_orders], + 'po_count': [record.get('count') for record in partner_orders], + 'draft_amount': [record.get('sum') for record in draft_orders], + 'draft_count': [record.get('count') for record in draft_orders], + 'approve_amount': [record.get('sum') for record in approve_orders], + 'approve_count': [record.get('count') for record in approve_orders], + 'cancel_amount': [record.get('sum') for record in cancel_orders], + 'cancel_count': [record.get('count') for record in cancel_orders], + 'dates': [record.get('dates') for record in partner_orders], + } + return value + + @api.model + def get_pending_purchase_data(self): + """ + Get pending purchase orders for the current company. + Returns: + dict: A dictionary containing pending purchase order details, + including order names, vendor names, amounts, dates, and states. + """ + company = self.env.company.id + query = """ + SELECT po.name, po.id, rp.name as partner_name, po.date_planned, + po.amount_total, po.state + FROM purchase_order po + JOIN purchase_order_line pol ON pol.order_id = po.id + JOIN res_partner rp ON rp.id = po.partner_id + WHERE po.date_planned < CURRENT_DATE AND pol.qty_received < + pol.product_qty AND po.company_id = %s + GROUP BY po.id, rp.id + """ + self._cr.execute(query, (company,)) + orders = self._cr.dictfetchall() + value = { + 'order': [rec['name'] for rec in orders], + 'vendor': [rec['partner_name'] for rec in orders], + 'amount': [rec['amount_total'] for rec in orders], + 'date': [rec['date_planned'] for rec in orders], + 'state': [rec['state'] for rec in orders], + 'data': [list(val for val in rec.values()) for rec in orders] + } + return value + + @api.model + def get_upcoming_purchase_data(self): + """ + Get upcoming purchase orders for the current company. + Returns: + dict: A dictionary containing upcoming purchase order details, + including order names, vendor names, amounts, dates, and states. + """ + company = self.env.company.id + query = """ + SELECT po.name, po.id, rp.name as partner_name, po.date_planned, + po.amount_total, po.state + FROM purchase_order po + JOIN purchase_order_line pol ON pol.order_id = po.id + JOIN res_partner rp ON rp.id = po.partner_id + WHERE po.date_planned > CURRENT_DATE AND pol.qty_received < + pol.product_qty AND po.company_id = %s + GROUP BY po.id, rp.id + """ + self._cr.execute(query, (company,)) + orders = self._cr.dictfetchall() + value = { + 'order': [rec['name'] for rec in orders], + 'vendor': [rec['partner_name'] for rec in orders], + 'amount': [rec['amount_total'] for rec in orders], + 'date': [rec['date_planned'] for rec in orders], + 'state': [rec['state'] for rec in orders], + 'data': [list(val for val in rec.values()) for rec in orders], + } + return value + + +class PurchaseOrderLine(models.Model): + """ + Purchase Order Line Model for Extending Purchase Order Line + Functionality. This class extends the Odoo Purchase Order Line model + to add custom methods for product category analysis and retrieval of + product category data. + """ + _inherit = 'purchase.order.line' + + @api.model + def product_categ_analysis(self): + """ + Perform product category analysis for purchase order lines. This + method retrieves and analyzes purchase order line data to provide + information on product categories and their corresponding + quantities. + """ + company_id = self.env.user.company_id.id + # Query to get products quantity by name + quantity_query = """ + SELECT product_template.name, + SUM(pl.product_qty) as total_quantity + FROM purchase_order_line pl + JOIN product_product ON pl.product_id = product_product.id + JOIN product_template ON product_product.product_tmpl_id = + product_template.id + WHERE pl.company_id = %s + GROUP BY product_template.name + """ + self._cr.execute(quantity_query, (company_id,)) + products_quantity = self._cr.fetchall() + # Extract name and quantity values from query result + name, quantity_done = zip(*products_quantity) + # Query to get category ids and names + category_query = """ + SELECT pc.id, pc.name + FROM product_category pc + JOIN product_template pt ON pt.categ_id = pc.id + JOIN product_product pp ON pp.product_tmpl_id = pt.id + JOIN purchase_order_line pl ON pl.product_id = pp.id + WHERE pl.company_id = %s + GROUP BY pc.id, pc.name + """ + self._cr.execute(category_query, (company_id,)) + categories = self._cr.fetchall() + # Extract category ids and names from query result + category_ids, category_names = zip(*categories) + # Create dictionary values to return + value = {'name': name, 'count': quantity_done} + new_value = {'category_id': category_ids, + 'category_name': category_names} + return value, new_value + + @api.model + def product_categ_data(self, args): + """ + Retrieve product category data for a specific category. + Returns: + dict: A dictionary containing product data for the specified + category, including product names and their quantities. + """ + category_id = int(args or 1) + company_id = self.env.company.id + query = """ + SELECT product_template.name, SUM(pl.product_qty) + FROM purchase_order_line pl + INNER JOIN product_product ON pl.product_id = product_product.id + INNER JOIN product_template ON product_product.product_tmpl_id = + product_template.id + WHERE pl.company_id = %s AND product_template.categ_id = %s + GROUP BY product_template.name + """ + self._cr.execute(query, (company_id, category_id)) + product_move = self._cr.dictfetchall() + value = { + 'name': [record.get('name') for record in product_move], + 'count': [record.get('sum') for record in product_move], + } + return value diff --git a/purchase_dashboard_advanced/static/description/assets/icons/check.png b/purchase_dashboard_advanced/static/description/assets/icons/check.png new file mode 100644 index 000000000..c8e85f51d Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/icons/check.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/icons/chevron.png b/purchase_dashboard_advanced/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..2089293d6 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/icons/chevron.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/icons/cogs.png b/purchase_dashboard_advanced/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/icons/cogs.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/icons/consultation.png b/purchase_dashboard_advanced/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/icons/consultation.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/icons/ecom-black.png b/purchase_dashboard_advanced/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/icons/ecom-black.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/icons/education-black.png b/purchase_dashboard_advanced/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/icons/education-black.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/icons/hotel-black.png b/purchase_dashboard_advanced/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/icons/hotel-black.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/icons/license.png b/purchase_dashboard_advanced/static/description/assets/icons/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/icons/license.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/icons/lifebuoy.png b/purchase_dashboard_advanced/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/icons/lifebuoy.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/icons/manufacturing-black.png b/purchase_dashboard_advanced/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/icons/manufacturing-black.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/icons/pos-black.png b/purchase_dashboard_advanced/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/icons/pos-black.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/icons/puzzle.png b/purchase_dashboard_advanced/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/icons/puzzle.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/icons/restaurant-black.png b/purchase_dashboard_advanced/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/icons/restaurant-black.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/icons/service-black.png b/purchase_dashboard_advanced/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/icons/service-black.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/icons/trading-black.png b/purchase_dashboard_advanced/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/icons/trading-black.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/icons/training.png b/purchase_dashboard_advanced/static/description/assets/icons/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/icons/training.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/icons/update.png b/purchase_dashboard_advanced/static/description/assets/icons/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/icons/update.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/icons/user.png b/purchase_dashboard_advanced/static/description/assets/icons/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/icons/user.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/icons/wrench.png b/purchase_dashboard_advanced/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/icons/wrench.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/misc/categories.png b/purchase_dashboard_advanced/static/description/assets/misc/categories.png new file mode 100644 index 000000000..bedf1e0b1 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/misc/categories.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/misc/check-box.png b/purchase_dashboard_advanced/static/description/assets/misc/check-box.png new file mode 100644 index 000000000..42caf24b9 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/misc/check-box.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/misc/compass.png b/purchase_dashboard_advanced/static/description/assets/misc/compass.png new file mode 100644 index 000000000..d5fed8faa Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/misc/compass.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/misc/corporate.png b/purchase_dashboard_advanced/static/description/assets/misc/corporate.png new file mode 100644 index 000000000..2eb13edbf Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/misc/corporate.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/misc/customer-support.png b/purchase_dashboard_advanced/static/description/assets/misc/customer-support.png new file mode 100644 index 000000000..79efc72ed Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/misc/customer-support.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/misc/cybrosys-logo.png b/purchase_dashboard_advanced/static/description/assets/misc/cybrosys-logo.png new file mode 100644 index 000000000..cc3cc0ccf Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/misc/cybrosys-logo.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/misc/features.png b/purchase_dashboard_advanced/static/description/assets/misc/features.png new file mode 100644 index 000000000..b41769f77 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/misc/features.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/misc/logo.png b/purchase_dashboard_advanced/static/description/assets/misc/logo.png new file mode 100644 index 000000000..478462d3e Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/misc/logo.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/misc/pictures.png b/purchase_dashboard_advanced/static/description/assets/misc/pictures.png new file mode 100644 index 000000000..56d255fe9 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/misc/pictures.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/misc/pie-chart.png b/purchase_dashboard_advanced/static/description/assets/misc/pie-chart.png new file mode 100644 index 000000000..426e05244 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/misc/pie-chart.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/misc/right-arrow.png b/purchase_dashboard_advanced/static/description/assets/misc/right-arrow.png new file mode 100644 index 000000000..730984a06 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/misc/right-arrow.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/misc/star.png b/purchase_dashboard_advanced/static/description/assets/misc/star.png new file mode 100644 index 000000000..2eb9ab29f Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/misc/star.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/misc/support.png b/purchase_dashboard_advanced/static/description/assets/misc/support.png new file mode 100644 index 000000000..4f18b8b82 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/misc/support.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/misc/whatsapp.png b/purchase_dashboard_advanced/static/description/assets/misc/whatsapp.png new file mode 100644 index 000000000..d513a5356 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/misc/whatsapp.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/modules/1.png b/purchase_dashboard_advanced/static/description/assets/modules/1.png new file mode 100644 index 000000000..d0f3dfb74 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/modules/1.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/modules/2.jpg b/purchase_dashboard_advanced/static/description/assets/modules/2.jpg new file mode 100644 index 000000000..803618b9f Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/modules/2.jpg differ diff --git a/purchase_dashboard_advanced/static/description/assets/modules/3.png b/purchase_dashboard_advanced/static/description/assets/modules/3.png new file mode 100644 index 000000000..b1cb1b5d1 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/modules/3.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/modules/4.png b/purchase_dashboard_advanced/static/description/assets/modules/4.png new file mode 100644 index 000000000..55070c974 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/modules/4.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/modules/5.png b/purchase_dashboard_advanced/static/description/assets/modules/5.png new file mode 100644 index 000000000..5d23539cd Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/modules/5.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/modules/6.png b/purchase_dashboard_advanced/static/description/assets/modules/6.png new file mode 100644 index 000000000..234c34c01 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/modules/6.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/screenshots/1.png b/purchase_dashboard_advanced/static/description/assets/screenshots/1.png new file mode 100644 index 000000000..6fc6366f7 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/screenshots/1.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/screenshots/2.png b/purchase_dashboard_advanced/static/description/assets/screenshots/2.png new file mode 100644 index 000000000..6dbda7021 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/screenshots/2.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/screenshots/dashboard_community.png b/purchase_dashboard_advanced/static/description/assets/screenshots/dashboard_community.png new file mode 100644 index 000000000..f0277c97d Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/screenshots/dashboard_community.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/screenshots/dashboard_enterprise.png b/purchase_dashboard_advanced/static/description/assets/screenshots/dashboard_enterprise.png new file mode 100644 index 000000000..ddf9b446f Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/screenshots/dashboard_enterprise.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/screenshots/dashboard_tiles.png b/purchase_dashboard_advanced/static/description/assets/screenshots/dashboard_tiles.png new file mode 100644 index 000000000..a21384600 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/screenshots/dashboard_tiles.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/screenshots/gif.zip b/purchase_dashboard_advanced/static/description/assets/screenshots/gif.zip new file mode 100644 index 000000000..61d596183 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/screenshots/gif.zip differ diff --git a/purchase_dashboard_advanced/static/description/assets/screenshots/gif/1.png b/purchase_dashboard_advanced/static/description/assets/screenshots/gif/1.png new file mode 100644 index 000000000..a2109f3fa Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/screenshots/gif/1.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/screenshots/gif/2.png b/purchase_dashboard_advanced/static/description/assets/screenshots/gif/2.png new file mode 100644 index 000000000..a0e589dd1 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/screenshots/gif/2.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/screenshots/gif/3.png b/purchase_dashboard_advanced/static/description/assets/screenshots/gif/3.png new file mode 100644 index 000000000..6dbda7021 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/screenshots/gif/3.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/screenshots/gif/4.png b/purchase_dashboard_advanced/static/description/assets/screenshots/gif/4.png new file mode 100644 index 000000000..31d58b74a Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/screenshots/gif/4.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/screenshots/gif/5.png b/purchase_dashboard_advanced/static/description/assets/screenshots/gif/5.png new file mode 100644 index 000000000..1b0ee5c61 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/screenshots/gif/5.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/screenshots/gif/6.png b/purchase_dashboard_advanced/static/description/assets/screenshots/gif/6.png new file mode 100644 index 000000000..050fb4a00 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/screenshots/gif/6.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/screenshots/hero.gif b/purchase_dashboard_advanced/static/description/assets/screenshots/hero.gif new file mode 100644 index 000000000..733f621d6 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/screenshots/hero.gif differ diff --git a/purchase_dashboard_advanced/static/description/assets/screenshots/pending_arrivals.png b/purchase_dashboard_advanced/static/description/assets/screenshots/pending_arrivals.png new file mode 100644 index 000000000..4c74d9e05 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/screenshots/pending_arrivals.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/screenshots/product_category_analysis.png b/purchase_dashboard_advanced/static/description/assets/screenshots/product_category_analysis.png new file mode 100644 index 000000000..1b0ee5c61 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/screenshots/product_category_analysis.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/screenshots/purchase_vendor_analysis.png b/purchase_dashboard_advanced/static/description/assets/screenshots/purchase_vendor_analysis.png new file mode 100644 index 000000000..050fb4a00 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/screenshots/purchase_vendor_analysis.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/screenshots/purchases_by_month.png b/purchase_dashboard_advanced/static/description/assets/screenshots/purchases_by_month.png new file mode 100644 index 000000000..31d58b74a Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/screenshots/purchases_by_month.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/screenshots/tiles.png b/purchase_dashboard_advanced/static/description/assets/screenshots/tiles.png new file mode 100644 index 000000000..a0e589dd1 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/screenshots/tiles.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/screenshots/top_charts.png b/purchase_dashboard_advanced/static/description/assets/screenshots/top_charts.png new file mode 100644 index 000000000..a2109f3fa Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/screenshots/top_charts.png differ diff --git a/purchase_dashboard_advanced/static/description/assets/screenshots/upcoming_arrivals.png b/purchase_dashboard_advanced/static/description/assets/screenshots/upcoming_arrivals.png new file mode 100644 index 000000000..d028aa3f1 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/assets/screenshots/upcoming_arrivals.png differ diff --git a/purchase_dashboard_advanced/static/description/banner.png b/purchase_dashboard_advanced/static/description/banner.png new file mode 100644 index 000000000..f15502972 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/banner.png differ diff --git a/purchase_dashboard_advanced/static/description/icon.png b/purchase_dashboard_advanced/static/description/icon.png new file mode 100644 index 000000000..b27b817d8 Binary files /dev/null and b/purchase_dashboard_advanced/static/description/icon.png differ diff --git a/purchase_dashboard_advanced/static/description/index.html b/purchase_dashboard_advanced/static/description/index.html new file mode 100644 index 000000000..d5636840b --- /dev/null +++ b/purchase_dashboard_advanced/static/description/index.html @@ -0,0 +1,610 @@ +
+ +
+ +
+
+ Community +
+
+ Enterprise +
+
+
+ + +

Purchase Dashboard

+

Detailed Dashboard View For Purchase

+ + + +
+ + +
+
+ +
+

Explore This + Module

+
+ + + + +
+
+ +
+

Overview +

+
+
+
+ A Dashboard for keeping track and evaluate various aspects of spending on purchases , We can track Monthly , yearly , top products , priority products and upcoming details of purchase. +
+
+ + + +
+
+ +
+

Features +

+
+
+
+
+ + Detailed view for purchases + +
+
+ + Responsive views +
+
+ + Different types of graphs + +
+
+ + Different types of tables for analysing the records +
+ +
+
+ + + + +
+
+

+ Screenshots +

+
+
+

+ Dashboard View for the Purchase Module

+

+ The Dashboard is available in the Purchase module with tiles and the Related graphs. +

+ + +
+ +
+

+ The Tiles display a list of the Purchase orders,Total amount, Priority orders and Vendors based on Today,This Week, This Month and This Year + +

+

+ +

+ +
+
+

+ Top Charts

+

+ This is the pie graph for showing the Top Products, Top Vendors, Top Purchase Representatives +

+ +
+ +
+

+ Purchases By Month

+

+ This bar graph shows the purchases made in each month. +

+ +
+ +
+

+ Purchase Vendor Analysis

+

+ This is a line graph containing multiple attributes on it. This will show the purchases and its states based on the vendors. +

+ +
+
+

+ Product Category Analysis

+

+ This is a line graph used to plot the product category analysis. It will demonstrate the quantity of products based on the category selected. +

+ +
+ +
+

+ Pending Arrivals

+

+ There are pending purchase orders with partial deliveries, where some products have been delivered, but the rest are still awaiting delivery. +

+ +
+
+

+ Upcoming Arrivals

+

+ This is the table of contents describing the purchase order that is yet to arrive. +

+ +
+ + + + +
+
+

Suggested Products

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

Our Services +

+
+ +
+
+
+
+ +
+
+ Odoo + Customization
+
+ +
+
+ +
+
+ Odoo + Implementation
+
+ +
+
+ +
+
+ Odoo + Support
+
+ + +
+
+ +
+
+ Hire + Odoo + Developer
+
+ +
+
+ +
+
+ Odoo + Integration
+
+ +
+
+ +
+
+ Odoo + Migration
+
+ + +
+
+ +
+
+ Odoo + Consultancy
+
+ +
+
+ +
+
+ Odoo + Implementation
+
+ +
+
+ +
+
+ Odoo + Licensing Consultancy
+
+
+ +
+ + + + + +
+
+ +
+

Our + Industries +

+
+ +
+
+
+
+ +
+ Trading +
+

+ Easily procure + and + sell your products

+
+
+ +
+
+ +
+ POS +
+

+ Easy + configuration + and convivial experience

+
+
+ +
+
+ +
+ Education +
+

+ A platform for + educational management

+
+
+ +
+
+ +
+ Manufacturing +
+

+ Plan, track and + schedule your operations

+
+
+ +
+
+ +
+ E-commerce & Website +
+

+ Mobile + friendly, + awe-inspiring product pages

+
+
+ +
+
+ +
+ Service Management +
+

+ Keep track of + services and invoice

+
+
+ +
+
+ +
+ Restaurant +
+

+ Run your bar or + restaurant methodically

+
+
+ +
+
+ +
+ Hotel Management +
+

+ An + all-inclusive + hotel management application

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

Support +

+
+
+
+
+
+
+ +
+
+

Need Help?

+

Got questions or need help? Get in touch.

+ +

+ odoo@cybrosys.com

+
+
+
+
+
+
+
+ +
+
+

WhatsApp

+

Say hi to us on WhatsApp!

+ +

+91 86068 + 27707

+
+
+
+
+
+
+
+ +
+
+
+ +
diff --git a/purchase_dashboard_advanced/static/src/css/style.css b/purchase_dashboard_advanced/static/src/css/style.css new file mode 100644 index 000000000..163d6c606 --- /dev/null +++ b/purchase_dashboard_advanced/static/src/css/style.css @@ -0,0 +1,349 @@ +.oh_dashboards{ + padding-top :15px; + background-color: #f8faff !important; +} + +.oh-card h4 { + font-size: 1.1rem; +} + +/* Widget One +---------------------------*/ +.stat-content { + display: inline-block; + width: 66%; +} +.stat-icon{ + display: inline-block; +} + +.stat-widget-one .stat-icon { + vertical-align: top; + margin: auto; + width: 100%; + color: #01c490; +} + +.stat-widget-one .stat-icon i { + font-size: 30px; + font-weight: 900; + display: inline-block; + color: #01c490;} + +.stat-widget-one .stat-text { + font-size: 14px; + color: #868e96; + font-weight: bold; +} + +.stat-widget-one .stat-digit { + font-size: 24px; + color: #02448b; } + +.stat-count { + font-size: 20px; + text-align: center; + color: #00438b;} + +.stat-title { + font-size: 17px; + text-align: center; + color: #00438b; } + +.mb-0{ + font-size: 20px; + position: relative; + text-align: center; +} +.mb-0 .dash-title { + font-size: 20px; + text-align: center; + color: rgba(255, 255, 255, 0.81); +} + +.oh-card { + + padding-top: 0px; + padding: 0px; + margin-bottom: 1.5rem; + border-radius: 0px; + box-shadow: none; + background: none; + transition: transform 0.2s ease, box-shadow 0.2s ease; + will-change: transform, box-shadow; + +} +.oh-card:hover { + + transform: translateY(-2px) translateZ(0) !important; + box-shadow: 0 10px 10px 0 rgba(62, 57, 107, 0.12), 0 0 0 transparent !important; + +} +.oh-data { + + margin-top: 4.5%; + +} +.oh-data .stat-icon { + + width: 30%; + height: 85px; + text-align: center; + background: #ff8762; + color: #fff; + width: 32%; + padding-top: 2%; + font-size: xxx-large; + +} +.oh-data .oh-card { + + transition: transform 0.2s ease, box-shadow 0.2s ease; + will-change: transform, box-shadow; + box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62,57,107,0.06); + +} +.stat-widget-one .stat-text { + font-size: 14px; + color: #ff8762; + margin-top: 2.3rem; + margin-left: 1rem; +} +.stat-widget-one .stat-digit { + font-size: 26px; + color:#993232; + margin-left: 1rem; + margin-top: -1px; + font-family: initial +} + +.stat-widget-one .stat-icon i { + + font-size: 25px; + font-weight: 900; + display: inline-block; + color: #fff; + +} +.stat-widget-one { + + background-color: white; + text-align: left; + +} +.stat-widget-one { + width: 100%; +} +.oh-data .stat-icon { + + width: 30%; + height: 85px; + text-align: center; + padding-top: 2%; + +} + +h4 .stat-count { + font-size: 17px; + text-align: center; + color: #000 !important; + margin-top: 0px; + width: 100%; + float: left; + margin: 0; +} + +.stat-head { + text-align: left !important; + font-weight: 300; + font-size: 15px; + margin-bottom: 25px; + margin-left: 24px; + width: 100%; +} +.oh-card-body { + display: flex; + justify-content: space-between; + align-items: center; +} + +.o_action_manager{ + overflow-y: scroll !important; + max-width:100%; + } + +.stat_count{ + margin-top: -89px; + margin-left: 35px; + font-size: 33px; +} + + +.stat-head { + text-align: left !important; + font-weight: 300; + font-size: 18px; + margin-bottom: 25px; + margin-left: 24px; + width: 100%; + margin-top: 57px; + color: black; +} + +.top_chart{ + height: fit-content; +} +.row.main-section { + margin-right: 0px; !important; +} + +.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%; +} +#container { + height: 400px; +} +/*vendor analysis*/ +#vendor_select { + position: absolute; + top: 1px; + right: 63px; +} + +#vendor_selection { + position: absolute; + top: 33px; + background-color: #0d5820; +} + +/*category analysis*/ +#product_categ_select { + position: absolute; + top: 1px; + right: 63px; + +} + +#product_categ_selection { + position: absolute; + top: 33px; + background-color: #00000099; +} + +/*table*/ +.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;} + +.chart-container h2 { + font-weight: 700; + font-size: 1.690rem; +} + +.hr_notification { + background: #f6f7fa; + transition: transform 0.2s ease, box-shadow 0.2s ease; + will-change: transform, box-shadow; + box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62,57,107,0.06); + height: 316px; + overflow-y: auto; + margin-bottom: 15px; +} +.hr_notification .media { + border-bottom: 1px solid #e6e6e6; + padding-bottom: 6px; + margin-bottom: 10px; +} +hr_notification .text-color.display-6 { + margin: 0px 0 3px; + color: #2d2d2d; +} +.hr_notification p { + margin: 0 0 1px; + color: #666; + font-size: 10px; +} +.chart_head { + font-size: 17px; + text-align: center; + padding: 12px 0; + color: #fff; + font-weight: 300; + background: #5ebade; + margin-bottom: 9px; +} +.hr_notification_head { + font-size: 17px; + text-align: center; + padding: 12px 0; + color: #fff; + font-weight: 300; + background: #5ebade; + margin-bottom: 9px; +} +@media (max-width: 767.98px) { + .oh-card{ + width: 100% !important; + } + .dashboard_main_section .form-control{ + width: 85% !important; + margin: 15px auto; + } + .sale_details{ + position: relative; + top: 0px !important; + right: 0px !important; + } + .selling_product_graph_view{ + margin-top: 5rem; + } + .hr_notification{ + min-width: 90% !important; + } +} +.hr_notification{ + min-width: 425.683px; + min-height: 316px; + max-width: 100%; +} +.media-body{ + + background: #466b8d; + float: left; + margin: 0; + width: 100% + +} diff --git a/purchase_dashboard_advanced/static/src/js/dashboard.js b/purchase_dashboard_advanced/static/src/js/dashboard.js new file mode 100644 index 000000000..dcddf93f3 --- /dev/null +++ b/purchase_dashboard_advanced/static/src/js/dashboard.js @@ -0,0 +1,734 @@ +odoo.define('purchase_dashboard_advanced.PurchaseDashboard', function (require) { + 'use strict'; + var AbstractAction = require('web.AbstractAction'); + var core = require('web.core'); + var _t = core._t; + var QWeb = core.qweb; + var ajax = require('web.ajax'); + var rpc = require('web.rpc'); + + var PurchaseDashboard = AbstractAction.extend({ + template: 'PurchaseDashboard', + events: { + 'click .purchase_order_all': 'purchase_order_all', + 'click .po_priority_orders': 'po_priority_orders', + 'change #select_mode': 'onchange_select_mode', + 'change #select_chart': 'onchange_select_chart', + 'change #product_categ_selection': 'onchange_product_categ', + 'change #vendor_selection': 'onchange_vendor_selection', + }, + init: function () { + /** + * Initializes an object with a list of dashboard template names. + * + * @returns {undefined} + */ + this._super.apply(this, arguments); + this.dashboard_templates = ['PurchaseMain', 'Top']; + }, + + start: function() { + /** + * Initializes the PurchaseDashboard and renders dashboards and graphs. + * + * @function + * @memberof PurchaseDashboard + * @returns {Promise} A Promise that resolves when rendering is complete. + */ + var self = this; + this.set("title", 'PurchaseDashboard'); + return this._super().then(function() { + self.render_dashboards(); + self.render_graphs(); + }); + }, + + willStart: function() { + /** + * Executes a series of asynchronous operations and returns a Promise that resolves when all operations are complete. + * + * @returns {Promise} A Promise that resolves when all asynchronous operations are complete. + */ + var self = this; + return $.when(ajax.loadLibs(this), this._super()).then(function() { + return self.fetch_data(); + }); + }, + + render_graphs: function(){ + /** + * Renders the graphs for the PurchaseDashboard. + * + * @function + * @memberof PurchaseDashboard + * @returns {void} + */ + var self = this; + self.render_top_product(); + self.render_line_chart(); + self.render_product_categ_analysis(); + self.render_fusion_chart(); + }, + + render_dashboards: function() { + /** + * Renders the dashboards for the PurchaseDashboard. + * + * @function + * @memberof PurchaseDashboard + * @returns {void} + */ + var self = this; + _.each(this.dashboard_templates, function(template) { + self.$el.find('.o_purchase_dashboard').append(QWeb.render(template, {widget: self})); + }); + }, + + purchase_order_all: function(e) { + /** + * Handles the click event of the "Purchase Order All" button, opening a list view of purchase orders. + * + * @function + * @memberof PurchaseDashboard + * @param {MouseEvent} e - The click event. + * @returns {void} + */ + var self = this; + e.stopPropagation(); + e.preventDefault(); + if(this.purchase_orders) { + var options = { + on_reverse_breadcrumb: self.on_reverse_breadcrumb, + }; + self.do_action({ + name: _t("Purchase Order"), + type: 'ir.actions.act_window', + res_model: 'purchase.order', + view_mode: 'tree,form', + views: [[false, 'list'],[false, 'form']], + domain: [['state','in', ['purchase', 'done']]], + target: 'current' + }, options) + } + }, + + render_line_chart: function(e) { + var self=this + /** + * Renders a line chart of purchase orders by month. + * + * @function + * @memberof PurchaseDashboard + * @param {MouseEvent} e - The click event (optional). + * @returns {void} + */ + rpc.query({ + model: "purchase.order", + method: 'get_orders_by_month', + }).then(function (arrays) { + var ctx = self.el.querySelector("#canvas"); + var month = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] + var count = arrays.count; + new Chart(ctx, { + type: 'bar', + data: { + labels: month, + datasets: [{ + label: 'Count', + data: count, + backgroundColor: '#ac3973', + borderColor: '#ac3973', + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'bar', + fill: false + }] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + responsive: true, + maintainAspectRatio: false, + } + }); + }); + }, + + render_product_categ_analysis: function(e) { + /** + Render the product category analysis chart based on the purchase order lines. + @function + @name render_product_categ_analysis + @memberof PurchaseDashboardWidget + @param {Event} e - The event object. + @returns {void} + */ + var self = this + rpc.query({ + model: "purchase.order.line", + method: 'product_categ_analysis', + }).then(function (result) { + var ctx = self.$el.find("#product_categ_purchases"); + var count = result[0].count + var category_name = result[1].category_name + var category_id = result[1].category_id + var count = 0; + Object.entries(result[1].category_name).forEach(([key, value]) => { + if(count == 0){ + self.$el.find('#product_categ_selection').append('') + count++; + }else{ + self.$el.find('#product_categ_selection').append('') + count++; + } + }); + self.$el.find('#product_categ_table').hide(); + var option = self.$el.find( "#product_categ_selection" ).val(); + rpc.query({ + model: "purchase.order.line", + method: "product_categ_data", + args: [option] + }).then(function(result) { + var ctx = self.$el.find("#product_categ_purchases"); + var name = result.name + var count = result.count; + 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, + } + }); + }); + }); + }, + + po_priority_orders: function(e) { + /** + Renders priority purchase orders based on the priority field value. + @param {Event} e - The click event. + */ + var self = this; + e.stopPropagation(); + e.preventDefault(); + if(this.priority_orders) { + var options = { + on_reverse_breadcrumb: self.on_reverse_breadcrumb, + }; + self.do_action({ + name: _t("Priority Order"), + type: 'ir.actions.act_window', + res_model: 'purchase.order', + view_mode: 'tree,form', + views: [[false, 'list'],[false, 'form']], + domain: [['priority','=', 1]], + target: 'current' + }, options) + } + }, + + onchange_select_mode: function(e) { + /** + Handles onchange event of select mode dropdown and fetches data from server accordingly + @param {Event} e - Event object + @returns {void} + */ + var option = e.target.value + var self = this + rpc.query({ + model: 'purchase.order', + method: 'get_select_mode_data', + args: [option] + }).then(function (result) { + self.$el.find('#purchase_order').empty() + self.$el.find('#amount').empty() + self.$el.find('#priority').empty() + self.$el.find('#partner').empty() + self.$el.find('#purchase_orders').empty() + self.$el.find('#purchase_amount').empty() + self.$el.find('#priority_orders').empty() + self.$el.find('#vendors').empty() + self.$el.find('#purchase_orders').append(result['purchase_orders']) + self.$el.find('#purchase_amount').append(result['purchase_amount']) + self.$el.find('#priority_orders').append(result['priority_orders']) + self.$el.find('#vendors').append(result['vendors']) + }); + }, + + fetch_data: function() { + /** + Fetches purchase data and assigns it to the corresponding properties of the current object. + @returns {Promise} A Promise that resolves with the fetched data. + */ + var self = this + var fetchMonthlyData = this._rpc({ + model: 'purchase.order', + method: "get_monthly_data", + args: ['this_month'] + }) + .then(function (result) { + self.purchase_orders = result['purchase_orders'] + self.purchase_amount = result['purchase_amount'] + self.priority_orders = result['priority_orders'] + self.vendors = result['vendors'] + }); + var fetchPendingPurchaseData = self._rpc({ + model: 'purchase.order', + method: 'get_pending_purchase_data' + }).then(function (res) { + var order = Object.values(res['order']) + var vendor = Object.values(res['vendor']) + var amount = Object.values(res['amount']) + var date = Object.values(res['date']) + var state = Object.values(res['state']) + self.data = res['data'] + }); + var test = this + var fetchUpcomingPurchaseData = self._rpc({ + model: 'purchase.order', + method: 'get_upcoming_purchase_data' + }).then((res) => { + var order = Object.values(res['order']) + var vendor = Object.values(res['vendor']) + var amount = Object.values(res['amount']) + var date = Object.values(res['date']) + var state = Object.values(res['state']) + self.upcoming_data = res['data'] + }); + return $.when(fetchMonthlyData, fetchPendingPurchaseData, fetchUpcomingPurchaseData) + }, + + onchange_select_chart: function (e) { + /** + Function to handle the onchange event of select chart + @param {Event} e - The event object + */ + var option = e.target.value + var self = this + var ctx = self.$el.find(".top_pie_chart"); + var background_color = []; + rpc.query({ + model: "purchase.order", + method: 'get_top_chart_data', + args: [option] + }).then(function (arrays) { + arrays[0].forEach((div) => { + var randomColor = '#' + Math.floor(Math.random() * 16777215).toString(16); + background_color.push(randomColor) + }); + var randomColor= background_color + var data = { + labels : arrays[1], + datasets: [{ + label: "", + data: arrays[0], + backgroundColor:randomColor, + borderColor:randomColor, + borderWidth: 1 + },] + }; + //options + var options = { + responsive: true, + title: false, + legend: { + display: true, + position: "right", + labels: { + fontColor: "#333", + fontSize: 16 + } + }, + scales: { + yAxes: [{ + gridLines: { + color: "rgba(0, 0, 0, 0)", + display: false, + }, + ticks: { + min: 0, + display: false, + } + }] + } + }; + if (window.myCharts_top_priority != undefined) + window.myCharts_top_priority.destroy(); + window.myCharts_top_priority = new Chart(ctx, { + type: "doughnut", + data: data, + options: options + }); + }); + }, + + onchange_product_categ: function (events) { + /** + Function to handle the change in product category and display the data related to the product category. + @param {Event} events - The event object. + */ + var option = events.target.value; + var self = this + rpc.query({ + model: "purchase.order.line", + method: "product_categ_data", + args: [option] + }).then(function(result) { + var ctx = self.$el.find("#product_categ_purchases"); + var name = result.name + var count = result.count; + var index = 0; + self.$el.find('#product_categ_table td').remove(); + Object.entries(result.count).forEach(([key, value]) => { + self.$el.find('#product_categ_table').append(''+name[index]+''+value+'') + index++; + }); + self.$el.find('#product_categ_table').hide(); + new Chart(ctx, { + type: 'line', + data: { + labels: name, + datasets: [{ + label: 'Quantity', + 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, + } + }); + }); + }, + + render_top_product: function() { + /** + Render top products chart. + @function + @name render_top_product + @memberof module:purchases_dashboard + @returns {void} + */ + var self = this + var ctx = self.$el.find(".top_pie_chart"); + var background_color = []; + rpc.query({ + model: "purchase.order", + method: 'get_top_chart_data', + args: ['top_product'] + }).then(function (arrays) { + arrays[0].forEach((div) => { + var randomColor = '#' + Math.floor(Math.random() * 16777215).toString(16); + background_color.push(randomColor) + }); + var randomColor= background_color + var data = { + labels : arrays[1], + datasets: [{ + label: "", + data: arrays[0], + backgroundColor:randomColor, + borderColor:randomColor, + borderWidth: 1 + },] + }; + var options = { + responsive: true, + title: false, + legend: { + display: true, + position: "right", + labels: { + fontColor: "#333", + fontSize: 16 + } + }, + scales: { + yAxes: [{ + gridLines: { + color: "rgba(0, 0, 0, 0)", + display: false, + }, + ticks: { + min: 0, + display: false, + } + }] + } + }; + window.myCharts_top_priority = new Chart(ctx, { + type: "doughnut", + data: data, + options: options + }); + }); + }, + + render_fusion_chart: function(e) { + /** + Renders a Fusion chart by making a RPC call to retrieve purchase vendor data + @function + @param {Object} e - Event object + @returns {void} + */ + var self = this + rpc.query({ + model: "purchase.order", + method: 'purchase_vendors', + }).then(function (result) { + var ctx = self.$el.find("#purchase_vendors"); + var partner_id = result.partner_id; + var partner_name = result.partner_name; + var count = 0; + Object.entries(result.partner_name).forEach(([key, value]) => { + if(count == 0){ + self.$el.find('#vendor_selection').append('') + count++; + }else{ + self.$el.find('#vendor_selection').append('') + count++; + } + }); + var option = self.$el.find( "#vendor_selection" ).val(); + rpc.query({ + model: "purchase.order", + method: 'purchase_vendor_details', + args: [option] + }).then(function (result) { + self.$el.find("#purchase_vendors").empty(); + var ctx = self.$el.find("#purchase_vendors"); + if (result) { + self.$el.find('#purchase_vendors').append('
') + var ctx = self.$("#partner_graph"); + var name = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] + var sum = result.purchase_amount + var po_count = result.po_count + var draft_total = result.draft_amount + var draft_count = result.draft_count + var approve_amount = result.approve_amount + var approve_count = result.approve_count + var cancel_amount = result.cancel_amount + var cancel_count = result.cancel_count + var index = 0; + if (window.myChart_year != undefined) + window.myChart_year.destroy(); + window.myChart_year = new Chart(ctx, { + type: 'line', + data: { + labels: name, + datasets: [ + { + label: 'Purchase Order Total', + data: sum, + backgroundColor: '#0000ff', + borderColor: '#0000ff', + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'line', + fill: false + }, + { + label: 'Draft Order Total', + data: draft_total, + backgroundColor: '#71d927', + borderColor: '#71d927', + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'line', + fill: false + }, + { + label: 'To Approve', + data: approve_amount, + backgroundColor: '#ff0066', + borderColor: '#ff0066', + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'line', + fill: false + }, + { + label: 'Cancelled Orders', + data: cancel_amount, + backgroundColor: '#ffff1a', + borderColor: '#ffff1a', + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'line', + fill: false + }, + ] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + responsive: true, + maintainAspectRatio: false, + } + }); + } + }); + }); + }, + + onchange_vendor_selection: function(events) { + /** + Function to handle the change event of vendor selection dropdown. + @param {Event} events - The change event object + */ + var option = events.target.value; + var self = this + rpc.query({ + model: "purchase.order", + method: 'purchase_vendor_details', + args: [option] + }).then(function(result) { + self.$("#purchase_vendors").empty(); + var ctx = self.$el.find("#purchase_vendors"); + if (result) { + self.$el.find('#purchase_vendors').append('
') + var ctx = self.$el.find("#partner_graph"); + var name = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] + var sum = result.purchase_amount + var po_count = result.po_count + var draft_total = result.draft_amount + var draft_count = result.draft_count + var approve_amount = result.approve_amount + var approve_count = result.approve_count + var cancel_amount = result.cancel_amount + var cancel_count = result.cancel_count + var index = 0; + + if (window.myChart_year != undefined) + window.myChart_year.destroy(); window.myChart_year = new Chart(ctx, { + type: 'line', + data: { + labels: name, + datasets: [ + { + label: 'Purchase Order Total', + data: sum, + backgroundColor: '#0000ff', + borderColor: '#0000ff', + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'line', + fill: false + }, + { + label: 'Draft Order Total', + data: draft_total, + backgroundColor: '#71d927', + borderColor: '#71d927', + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'line', + fill: false + }, + { + label: 'To Approve', + data: approve_amount, + backgroundColor: '#ff0066', + borderColor: '#ff0066', + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'line', + fill: false + }, + { + label: 'Cancelled Orders', + data: cancel_amount, + backgroundColor: '#ffff1a', + borderColor: '#ffff1a', + barPercentage: 0.5, + barThickness: 6, + maxBarThickness: 8, + minBarLength: 0, + borderWidth: 1, + type: 'line', + fill: false + }, + ] + }, + options: { + scales: { + y: { + beginAtZero: true + }, + }, + responsive: true, + maintainAspectRatio: false, + } + }); + } + }); + }, + }); + core.action_registry.add('purchase_dashboard', PurchaseDashboard); + return PurchaseDashboard; +}); diff --git a/purchase_dashboard_advanced/static/src/xml/purchase_dashboard_templates.xml b/purchase_dashboard_advanced/static/src/xml/purchase_dashboard_templates.xml new file mode 100644 index 000000000..10a09e2b2 --- /dev/null +++ b/purchase_dashboard_advanced/static/src/xml/purchase_dashboard_templates.xml @@ -0,0 +1,309 @@ + + + diff --git a/purchase_dashboard_advanced/views/purchase_dashboard_menus.xml b/purchase_dashboard_advanced/views/purchase_dashboard_menus.xml new file mode 100644 index 000000000..e18cef889 --- /dev/null +++ b/purchase_dashboard_advanced/views/purchase_dashboard_menus.xml @@ -0,0 +1,13 @@ + + + + + Purchase + purchase_dashboard + + + +