diff --git a/crm_dashboard/README.rst b/crm_dashboard/README.rst new file mode 100755 index 000000000..3eb5d42c0 --- /dev/null +++ b/crm_dashboard/README.rst @@ -0,0 +1,40 @@ +CRM Dashboard +================== +* CRM Dashboard module for Odoo 16. + +Installation +============ + - www.odoo.com/documentation/16.0/setup/install.html + - Install our custom addon + +License +------- +General Public License, Version 3 (LGPL v3). +(https://www.odoo.com/documentation/user/16.0/legal/licenses/licenses.html) + +Company +------- +* 'Cybrosys Techno Solutions '__ + +Credits +------- +* 'Cybrosys Techno Solutions '__ + +Contacts +-------- +* Mail Contact : odoo@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 +========== +This module is maintained by Cybrosys Technologies. + +For support and more information, please visit https://www.cybrosys.com + +Further information +=================== +HTML Description: ``__ + diff --git a/crm_dashboard/__init__.py b/crm_dashboard/__init__.py new file mode 100644 index 000000000..26bd4be6e --- /dev/null +++ b/crm_dashboard/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2021-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/crm_dashboard/__manifest__.py b/crm_dashboard/__manifest__.py new file mode 100644 index 000000000..eab65f001 --- /dev/null +++ b/crm_dashboard/__manifest__.py @@ -0,0 +1,62 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2021-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': "CRM Dashboard", + 'description': """CRM Dashboard""", + 'summary': """CRM dashboard module brings a multipurpose graphical dashboard""" + """ for CRM module and making the relationship management better and easier""", + 'category': 'Sales', + 'version': '16.0.1.0.0', + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'website': "https://www.cybrosys.com", + 'depends': ['base', 'crm', 'sale_management'], + 'data': [ + 'views/dashboard_view.xml', + ], + 'assets': { + 'web.assets_backend': [ + 'crm_dashboard/static/src/css/dashboard.css', + 'crm_dashboard/static/src/css/style.scss', + 'crm_dashboard/static/src/css/material-gauge.css', + 'crm_dashboard/static/src/js/dashboard_view.js', + 'crm_dashboard/static/src/js/custom.js', + 'crm_dashboard/static/src/js/lib/highcharts.js', + 'crm_dashboard/static/src/js/lib/Chart.bundle.js', + 'crm_dashboard/static/src/js/lib/funnel.js', + 'crm_dashboard/static/src/js/lib/d3.min.js', + 'crm_dashboard/static/src/js/lib/material-gauge.js', + 'crm_dashboard/static/src/js/lib/columnHeatmap.min.js', + 'crm_dashboard/static/src/js/lib/columnHeatmap.js', + 'crm_dashboard/static/src/xml/dashboard_view.xml', + + ], + }, + 'images': [ + 'static/description/banner.png', + ], + 'license': 'LGPL-3', + 'installable': True, + 'application': True, + 'auto_install': False, +} diff --git a/crm_dashboard/doc/RELEASE_NOTES.md b/crm_dashboard/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..f264483e8 --- /dev/null +++ b/crm_dashboard/doc/RELEASE_NOTES.md @@ -0,0 +1,6 @@ +## Module + +#### 30.07.2022 +#### Version 16.0.1.0.0 +#### ADD +- Initial commit for CRM Dashboard Module diff --git a/crm_dashboard/models/__init__.py b/crm_dashboard/models/__init__.py new file mode 100644 index 000000000..ef192e226 --- /dev/null +++ b/crm_dashboard/models/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-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 crm_dashboard diff --git a/crm_dashboard/models/crm_dashboard.py b/crm_dashboard/models/crm_dashboard.py new file mode 100644 index 000000000..a49900553 --- /dev/null +++ b/crm_dashboard/models/crm_dashboard.py @@ -0,0 +1,1455 @@ +""""CRM Dashboard""" +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-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 datetime +import calendar + +from odoo import models, fields, api +from odoo.tools import date_utils +from odoo.http import request + +from dateutil.relativedelta import relativedelta +from datetime import datetime + + +class CRMSalesTeam(models.Model): + _inherit = 'crm.team' + + crm_lead_state_id = fields.Many2one("crm.stage", string="CRM Lead", + store=True) + + +class ResUser(models.Model): + _inherit = 'res.users' + + sales = fields.Float(string="Target") + + +class SalesOrder(models.Model): + _inherit = 'sale.order' + + def action_confirm(self): + """Supering the Confirm Button for Changing CRM Stage""" + res = super(SalesOrder, self).action_confirm() + self.opportunity_id.stage_id = self.team_id.crm_lead_state_id + return res + + +class CRMLead(models.Model): + _inherit = 'crm.lead' + + crm_manager_id = fields.Many2one("res.users", string="CRM Manager", + store=True) + monthly_goal = fields.Float(string="Monthly Goal") + achievement_amount = fields.Float(string="Monthly Achievement") + + @api.model + def _get_currency(self): + currency_array = [self.env.user.company_id.currency_id.symbol, + self.env.user.company_id.currency_id.position] + return currency_array + + @api.model + def check_user_group(self): + """Checking user group""" + user = self.env.user + if user.has_group('sales_team.group_sale_manager'): + return True + else: + return False + + @api.model + def get_lead_stage_data(self): + """funnel chart""" + stage_ids = self.env["crm.stage"].search([]) + crm_list = [] + for stage in stage_ids: + leads = self.search_count([("stage_id", "=", stage.id)]) + crm_list.append((stage.name, int(leads))) + return crm_list + + @api.model + def get_lead_month_pie(self): + """pie chart""" + month_count = [] + month_value = [] + leads = self.env['crm.lead'].search([]) + for rec in leads: + month = rec.create_date.month + if month not in month_value: + month_value.append(month) + month_count.append(month) + + month_val = [] + for index in range(len(month_value)): + value = month_count.count(month_value[index]) + month_name = calendar.month_name[month_value[index]] + month_val.append({'label': month_name, 'value': value}) + + name = [] + for record in month_val: + name.append(record.get('label')) + + count = [] + for record in month_val: + count.append(record.get('value')) + + month = [count, name] + return month + + @api.model + def get_the_sales_activity(self): + """Sales Activity Pie""" + self._cr.execute('''select mail_activity_type.name,COUNT(*) from mail_activity + inner join mail_activity_type on mail_activity.activity_type_id = mail_activity_type.id + where mail_activity.res_model = 'crm.lead' GROUP BY mail_activity_type.name''') + data = self._cr.dictfetchall() + + name = [] + for record in data: + name.append(record.get('name')) + + count = [] + for record in data: + count.append(record.get('count')) + + final = [count, name] + return final + + @api.model + def get_the_annual_target(self): + """Annual Target: Year To Date Graph""" + session_user_id = self.env.uid + + self._cr.execute('''SELECT res_users.id,res_users.sales,res_users.sale_team_id, + (SELECT crm_team.invoiced_target FROM crm_team WHERE crm_team.id = res_users.sale_team_id) + FROM res_users WHERE res_users.sales is not null and res_users.id=%s + AND res_users.sale_team_id is not null;''' % session_user_id) + data2 = self._cr.dictfetchall() + + sales = [] + inv_target = [] + team_id = 0 + for rec in data2: + sales.append(rec['sales']) + inv_target.append(rec['invoiced_target']) + if inv_target == [None]: + inv_target = [0] + team_id = rec['sale_team_id'] + target_annual = (sum(sales) + sum(inv_target)) + + if self.env.user.has_group('sales_team.group_sale_manager'): + self._cr.execute('''SELECT res_users.id,res_users.sales,res_users.sale_team_id, + (SELECT crm_team.invoiced_target FROM crm_team WHERE + crm_team.id = res_users.sale_team_id) FROM res_users WHERE res_users.id = %s + AND res_users.sales is not null;''' % session_user_id) + data3 = self._cr.dictfetchall() + + sales = [] + inv_target = [] + for rec in data3: + sales.append(rec['sales']) + inv_target.append(rec['invoiced_target']) + if inv_target == [None]: + inv_target = [0] + ytd_target = (sum(sales) + sum(inv_target)) + + self._cr.execute('''select sum(expected_revenue) from crm_lead where stage_id=4 + and team_id=%s AND Extract(Year FROM date_closed)=Extract(Year FROM DATE(NOW( + )))''' % team_id) + achieved_won_data = self._cr.dictfetchall() + achieved_won = [item['sum'] for item in achieved_won_data] + + else: + self._cr.execute('''SELECT res_users.id,res_users.sales FROM res_users + WHERE res_users.id = %s AND res_users.sales is not null;''' % session_user_id) + data4 = self._cr.dictfetchall() + + sales = [] + for rec in data4: + sales.append(rec['sales']) + ytd_target = (sum(sales)) + + self._cr.execute('''select sum(expected_revenue) from crm_lead where stage_id=4 + and user_id=%s AND Extract(Year FROM date_closed)=Extract(Year FROM DATE(NOW( + )))''' % session_user_id) + achieved_won_data = self._cr.dictfetchall() + achieved_won = [item['sum'] for item in achieved_won_data] + + won = achieved_won[0] + if won is None: + won = 0 + value = [target_annual, ytd_target, won] + name = ["Annual Target", "YtD target", "Won"] + final = [value, name] + + return final + + @api.model + def get_the_campaign_pie(self): + """Leads Group By Campaign Pie""" + self._cr.execute('''select campaign_id, COUNT(*), + (SELECT name FROM utm_campaign WHERE utm_campaign.id = crm_lead.campaign_id) + FROM crm_lead WHERE campaign_id is not null GROUP BY campaign_id''') + data = self._cr.dictfetchall() + + name = [] + for record in data: + name.append(record.get('name')) + + count = [] + for record in data: + count.append(record.get('count')) + + final = [count, name] + return final + + @api.model + def get_the_source_pie(self): + """Leads Group By Source Pie""" + self._cr.execute('''select source_id,COUNT(*),(SELECT name FROM utm_source + WHERE utm_source.id = crm_lead.source_id) from crm_lead + WHERE source_id is not null GROUP BY source_id''') + data = self._cr.dictfetchall() + + name = [] + for record in data: + name.append(record.get('name')) + + count = [] + for record in data: + count.append(record.get('count')) + + final = [count, name] + return final + + @api.model + def get_the_medium_pie(self): + """Leads Group By Medium Pie""" + self._cr.execute('''select medium_id,COUNT(*),(SELECT name FROM utm_medium + WHERE utm_medium.id = crm_lead.medium_id) from crm_lead + WHERE medium_id is not null GROUP BY medium_id ''') + data = self._cr.dictfetchall() + + name = [] + for record in data: + name.append(record.get('name')) + + count = [] + for record in data: + count.append(record.get('count')) + + final = [count, name] + return final + + @api.model + def revenue_count_pie(self): + """Total expected revenue and count Pie""" + session_user_id = self.env.uid + self._cr.execute('''select sum(expected_revenue) as revenue from crm_lead + where user_id=%s and type='opportunity' and active=true''' % session_user_id) + total_expected_revenue_data = self._cr.dictfetchall() + total_expected_revenue = [item['revenue'] for item in + total_expected_revenue_data] + total_expected_revenue = total_expected_revenue[0] + if total_expected_revenue is None: + total_expected_revenue = 0 + + self._cr.execute('''select sum(expected_revenue) as revenue from crm_lead + where user_id=%s and type='opportunity' and stage_id=4''' % session_user_id) + total_won_rev_data = self._cr.dictfetchall() + total_won_rev = [item['revenue'] for item in total_won_rev_data] + total_won_rev = total_won_rev[0] + if total_won_rev is None: + total_won_rev = 0 + + self._cr.execute('''select sum(expected_revenue) as revenue from crm_lead + where user_id=%s and type='opportunity' and probability=0 and active='false' + ''' % session_user_id) + total_lost_rev_data = self._cr.dictfetchall() + total_lost_rev = [item['revenue'] for item in total_lost_rev_data] + total_lost_rev = total_lost_rev[0] + if total_lost_rev is None: + total_lost_rev = 0 + + exp_revenue_without_won = total_expected_revenue - total_won_rev + revenue_pie_count = [exp_revenue_without_won, total_won_rev, + total_lost_rev] + revenue_pie_title = ['Expected without Won', 'Won', 'Lost'] + revenue_data = [revenue_pie_count, revenue_pie_title] + + return revenue_data + + @api.model + def get_upcoming_events(self): + """Upcoming Activities Table""" + today = fields.date.today() + session_user_id = self.env.uid + self._cr.execute('''select mail_activity.activity_type_id,mail_activity.date_deadline, + mail_activity.summary,mail_activity.res_name,(SELECT mail_activity_type.name + FROM mail_activity_type WHERE mail_activity_type.id = mail_activity.activity_type_id), + mail_activity.user_id FROM mail_activity WHERE res_model = 'crm.lead' AND + mail_activity.date_deadline >= '%s' and user_id = %s GROUP BY mail_activity.activity_type_id, + mail_activity.date_deadline,mail_activity.summary,mail_activity.res_name,mail_activity.user_id + order by mail_activity.date_deadline asc''' % (today, session_user_id)) + data = self._cr.fetchall() + + events = [] + for record in data: + user_id = record[5] + user_id_obj = self.env['res.users'].browse(user_id) + record_list = list(record) + record_list[5] = user_id_obj.name + events.append(record_list) + return {'event': events, + 'cur_lang': self.env.context.get('lang')} + + @api.model + def get_top_deals(self): + """Top 10 Deals Table""" + self._cr.execute('''SELECT crm_lead.user_id,crm_lead.id,crm_lead.expected_revenue, + crm_lead.name,crm_lead.company_id, (SELECT crm_team.name FROM crm_team + WHERE crm_lead.team_id = crm_team.id) from crm_lead where crm_lead.expected_revenue + is not null and crm_lead.type = 'opportunity' GROUP BY crm_lead.user_id, + crm_lead.id,crm_lead.expected_revenue,crm_lead.name,crm_lead.company_id + order by crm_lead.expected_revenue DESC limit 10''') + data1 = self._cr.fetchall() + + deals = [] + num = 0 + for rec in data1: + company_id = rec[4] + user_id = rec[0] + company_id_obj = self.env['res.company'].browse(company_id) + user_id_obj = self.env['res.users'].browse(user_id) + currency = company_id_obj.currency_id.symbol + rec_list = list(rec) + rec_list[0] = user_id_obj.name + num += 1 + rec_list.append(currency) + rec_list.append(num) + deals.append(rec_list) + + return {'deals': deals} + + @api.model + def get_monthly_goal(self): + """Monthly Goal Gauge""" + uid = request.session.uid + leads = self.env['crm.lead'].search([('date_deadline', '!=', False), + ('user_id', '=', uid), + ('type', '=', 'opportunity')]) + leads_won = self.env['crm.lead'].search([('date_closed', '!=', False), + ('stage_id', '=', 4), + ('user_id', '=', uid), + ('type', '=', 'opportunity')]) + currency_symbol = self.env.company.currency_id.symbol + + goals = [] + achievement = 0 + for won in leads_won.filtered( + lambda a: a.date_closed.month == fields.date.today().month): + if won.date_closed.year == fields.date.today().year: + achievement += won.expected_revenue + + total = 0 + for rec in leads.filtered( + lambda t: t.date_deadline.month == fields.date.today().month): + if rec.date_deadline.year == fields.date.today().year: + total += rec.expected_revenue + + self.monthly_goal = total + self.achievement_amount = achievement + + percent = 0 + if total > 0: + percent = (achievement * 100 / total) / 100 + + goals.append(achievement) + goals.append(total) + goals.append(currency_symbol) + goals.append(percent) + + return {'goals': goals} + + @api.model + def get_top_sp_revenue(self): + """Top 10 Salesperson revenue Table""" + user = self.env.user + + self._cr.execute('''SELECT user_id,id,expected_revenue,name,company_id + from crm_lead where expected_revenue is not null AND user_id = %s + GROUP BY user_id,id order by expected_revenue DESC limit 10''' % user.id) + data1 = self._cr.fetchall() + + top_revenue = [] + for rec in data1: + company_id = rec[4] + user_id = rec[0] + company_id_obj = self.env['res.company'].browse(company_id) + user_id_obj = self.env['res.users'].browse(user_id) + currency = company_id_obj.currency_id.symbol + rec_list = list(rec) + rec_list[0] = user_id_obj.name + rec_list.append(currency) + top_revenue.append(rec_list) + + return {'top_revenue': top_revenue} + + @api.model + def get_country_revenue(self): + """Top 10 Country Wise Revenue - Heat Map""" + company_id = self.env.company.id + self._cr.execute('''select country_id, sum(expected_revenue) from crm_lead + where expected_revenue is not null AND country_id is not null + group by country_id order by sum(expected_revenue) desc limit 10''') + data1 = self._cr.fetchall() + + country_revenue = [] + for rec in data1: + country_id = rec[0] + company_id_obj = self.env['res.company'].browse(company_id) + country_id_obj = self.env['res.country'].browse(country_id) + currency = company_id_obj.currency_id.symbol + rec_list = list(rec) + rec_list[0] = country_id_obj.name + rec_list.append(currency) + country_revenue.append(rec_list) + + return {'country_revenue': country_revenue} + + @api.model + def get_country_count(self): + """Top 10 Country Wise Count - Heat Map""" + self._cr.execute('''select country_id,count(*) from crm_lead where country_id is not null + group by country_id order by count(*) desc limit 10''') + data1 = self._cr.fetchall() + + country_count = [] + for rec in data1: + country_id = rec[0] + country_id_obj = self.env['res.country'].browse(country_id) + rec_list = list(rec) + rec_list[0] = country_id_obj.name + country_count.append(rec_list) + + return {'country_count': country_count} + + @api.model + def get_total_lost_crm(self, option): + """Lost Opportunity or Lead Graph""" + month_dict = {} + for i in range(int(option) - 1, -1, -1): + last_month = datetime.now() - relativedelta(months=i) + text = format(last_month, '%B') + month_dict[text] = 0 + + if option == '1': + day_dict = {} + last_day = date_utils.end_of(fields.Date.today(), + "month").strftime("%d") + + for i in range(1, int(last_day), 1): + day_dict[i] = 0 + + self._cr.execute('''select create_date::date,count(id) from crm_lead + where probability=0 and active=false and create_date between (now() - interval '1 month') and now() + group by create_date order by create_date;''') + data = self._cr.dictfetchall() + + for rec in data: + day_dict[int(rec['create_date'].strftime("%d"))] = rec['count'] + + test = {'month': list(day_dict.keys()), + 'count': list(day_dict.values())} + else: + month_string = str(int(option)) + ' Months' + self._cr.execute('''select extract(month from create_date),count(id) + from crm_lead where probability=0 and active=false and + create_date between (now() - interval '%s') and now() + group by extract(month from create_date) order by extract( + month from create_date);''' % month_string) + data = self._cr.dictfetchall() + + for rec in data: + datetime_object = datetime.strptime(str(int(rec['date_part'])), + "%m") + month_name = datetime_object.strftime("%B") + month_dict[month_name] = rec['count'] + + test = {'month': list(month_dict.keys()), + 'count': list(month_dict.values())} + + return test + + # @api.model + # def get_lost_reason_count(self): + # """Top 5 Lost Reason and Count""" + # self._cr.execute('''select lost_reason_id,count(lost_reason_id) as counts + # from crm_lead where probability=0 and active=false and lost_reason_id is not null + # group by lost_reason_id order by counts desc limit 5''') + # data1 = self._cr.fetchall() + # + # reason_count = [] + # for rec in data1: + # reason_id = rec[0] + # reason_id_obj = self.env['crm.lost.reason'].browse(reason_id) + # rec_list = list(rec) + # rec_list[0] = reason_id_obj.name + # reason_count.append(rec_list) + # + # return {'reason_count': reason_count} + + @api.model + def get_ratio_based_country(self): + """Top 5 Won vs Lost Ratio based on Country""" + self._cr.execute('''select (select name from res_country where id=country_id), + count(country_id) from crm_lead where probability=100 and active=true + group by country_id order by count(country_id) desc''') + data_won = self._cr.fetchall() + + self._cr.execute('''select (select name from res_country where id=country_id), + count(country_id) from crm_lead where probability=0 and active=false + group by country_id order by count(country_id) desc''') + data_lost = self._cr.fetchall() + + won = [] + for rec in data_won: + won_list = list(rec) + won.append(won_list) + + for lose in data_lost: + lose_list = list(lose) + + if lose_list[0] == won_list[0]: + won_list.append(lose_list[1]) + + country_wise_ratio = [] + for data in won: + if len(data) != 3: + del data + else: + if data[2] == 0: + ratio = 0 + else: + ratio = round(data[1] / data[2], 2) + data.append(str(ratio)) + country_wise_ratio.append(data) + + country_wise_ratio = sorted(country_wise_ratio, key=lambda x: x[3], + reverse=True) + country_wise_ratio = country_wise_ratio[:5] + + return {'country_wise_ratio': country_wise_ratio} + + @api.model + def get_ratio_based_sp(self): + """Top 5 Won vs Lost Ratio based on Sales Person""" + self._cr.execute('''select user_id,count(user_id) from crm_lead where + probability=100 and active=true group by user_id order by count(user_id) desc''') + data_won = self._cr.fetchall() + + self._cr.execute('''select user_id,count(user_id) from crm_lead where probability=0 + and active=false group by user_id order by count(user_id) desc''') + data_lost = self._cr.fetchall() + + won = [] + for rec in data_won: + won_list = list(rec) + user_id = rec[0] + user_id_obj = self.env['res.users'].browse(user_id) + won_list[0] = user_id_obj.name + won.append(won_list) + + for lose in data_lost: + lose_list = list(lose) + user_id = lose[0] + user_id_obj = self.env['res.users'].browse(user_id) + lose_list[0] = user_id_obj.name + + if lose_list[0] == won_list[0]: + won_list.append(lose_list[1]) + + salesperson_wise_ratio = [] + for data in won: + if len(data) != 3: + del data + else: + if data[2] == 0: + ratio = 0 + else: + ratio = round(data[1] / data[2], 2) + data.append(str(ratio)) + salesperson_wise_ratio.append(data) + + salesperson_wise_ratio = sorted(salesperson_wise_ratio, + key=lambda x: x[3], reverse=True) + salesperson_wise_ratio = salesperson_wise_ratio[:5] + + return {'salesperson_wise_ratio': salesperson_wise_ratio} + + @api.model + def get_ratio_based_sales_team(self): + """Top 5 Won vs Lost Ratio based on Sales Team""" + self._cr.execute('''select (SELECT name FROM crm_team WHERE crm_team.id = team_id), + count(user_id) from crm_lead where probability=100 and active=true + group by team_id order by count(team_id) desc''') + data_won = self._cr.fetchall() + + self._cr.execute('''select (SELECT name FROM crm_team WHERE crm_team.id = team_id), + count(user_id) from crm_lead where probability=0 and active=false + group by team_id order by count(team_id) desc''') + data_lost = self._cr.fetchall() + + won = [] + for rec in data_won: + won_list = list(rec) + won.append(won_list) + + for lose in data_lost: + lose_list = list(lose) + + if lose_list[0] == won_list[0]: + won_list.append(lose_list[1]) + + sales_team_wise_ratio = [] + for data in won: + if len(data) != 3: + del data + else: + if data[2] == 0: + ratio = 0 + else: + ratio = round(data[1] / data[2], 2) + data.append(str(ratio)) + sales_team_wise_ratio.append(data) + + sales_team_wise_ratio = sorted(sales_team_wise_ratio, + key=lambda x: x[3], reverse=True) + sales_team_wise_ratio = sales_team_wise_ratio[:5] + + return {'sales_team_wise_ratio': sales_team_wise_ratio} + + @api.model + def get_lost_lead_by_reason_pie(self): + """Lost Leads by Lost Reason Pie""" + self._cr.execute('''select lost_reason_id, count(*), (SELECT name FROM crm_lost_reason + WHERE id = lost_reason_id) from crm_lead where probability=0 and active=false and + type='lead' group by lost_reason_id''') + data1 = self._cr.dictfetchall() + + name = [] + for rec in data1: + if rec["name"] is None: + rec["name"] = "Undefined" + name.append(rec.get('name')) + + count = [] + for rec in data1: + count.append(rec.get('count')) + + lost_leads = [count, name] + return lost_leads + + @api.model + def get_lost_lead_by_stage_pie(self): + """Lost Leads by Stage Pie""" + self._cr.execute('''select stage_id, count(*),(SELECT name FROM crm_stage + WHERE id = stage_id) from crm_lead where probability=0 and active=false + and type='lead' group by stage_id''') + data1 = self._cr.dictfetchall() + + name = [] + for rec in data1: + name.append(rec.get('name')) + + count = [] + for rec in data1: + count.append(rec.get('count')) + + lost_leads_stage = [count, name] + return lost_leads_stage + + @api.model + def get_recent_activities(self): + """Recent Activities Table""" + today = fields.date.today() + recent_week = today - relativedelta(days=7) + self._cr.execute('''select mail_activity.activity_type_id,mail_activity.date_deadline, + mail_activity.summary,mail_activity.res_name,(SELECT mail_activity_type.name + FROM mail_activity_type WHERE mail_activity_type.id = mail_activity.activity_type_id), + mail_activity.user_id FROM mail_activity WHERE res_model = 'crm.lead' AND + mail_activity.date_deadline between '%s' and '%s' GROUP BY mail_activity.activity_type_id, + mail_activity.date_deadline,mail_activity.summary,mail_activity.res_name,mail_activity.user_id + order by mail_activity.date_deadline desc''' % (recent_week, today)) + data = self._cr.fetchall() + activities = [] + for record in data: + user_id = record[5] + user_id_obj = self.env['res.users'].browse(user_id) + record_list = list(record) + record_list[5] = user_id_obj.name + activities.append(record_list) + + return {'activities': activities} + + @api.model + def get_count_unassigned(self): + """Unassigned Leads Count Card""" + count_unassigned = self.env['crm.lead'].search_count( + [('user_id', '=', False), ('type', '=', 'lead')]) + + return {'count_unassigned': count_unassigned} + + @api.model + def get_top_sp_by_invoice(self): + """Top 10 Sales Person by Invoice Table""" + self._cr.execute('''select user_id,sum(amount_total) as total + from sale_order where invoice_status='invoiced' + group by user_id order by total desc limit 10''') + data1 = self._cr.fetchall() + + sales_person_invoice = [] + num = 0 + for rec in data1: + user_id = rec[0] + user_id_obj = self.env['res.users'].browse(user_id) + currency = user_id_obj.company_id.currency_id.symbol + rec_list = list(rec) + rec_list[0] = user_id_obj.name + num += 1 + rec_list.append(currency) + rec_list.append(num) + sales_person_invoice.append(rec_list) + + return {'sales_person_invoice': sales_person_invoice} + + @api.model + def lead_details_user(self): + """Cards Count and Details based on User""" + session_user_id = self.env.uid + month_count = [] + month_value = [] + leads = self.env['crm.lead'].search([]) + for rec in leads: + month = rec.create_date.month + if month not in month_value: + month_value.append(month) + month_count.append(month) + + value = [] + for index in range(len(month_value)): + value = month_count.count(month_value[index]) + + self._cr.execute('''SELECT res_users.id,res_users.sales,res_users.sale_team_id, + (SELECT crm_team.invoiced_target FROM crm_team WHERE crm_team.id = res_users.sale_team_id) + FROM res_users WHERE res_users.sales is not null and res_users.id=%s + AND res_users.sale_team_id is not null;''' % session_user_id) + data2 = self._cr.dictfetchall() + + sales = [] + inv_target = [] + team_id = 0 + for rec in data2: + sales.append(rec['sales']) + inv_target.append(rec['invoiced_target']) + if inv_target == [None]: + inv_target = [0] + team_id = rec['sale_team_id'] + target_annual = (sum(sales) + sum(inv_target)) + + if self.env.user.has_group('sales_team.group_sale_manager'): + self._cr.execute('''SELECT res_users.id,res_users.sales,res_users.sale_team_id, + (SELECT crm_team.invoiced_target FROM crm_team WHERE + crm_team.id = res_users.sale_team_id) FROM res_users WHERE res_users.id = %s + AND res_users.sales is not null;''' % session_user_id) + data3 = self._cr.dictfetchall() + + sales = [] + inv_target = [] + for rec in data3: + sales.append(rec['sales']) + inv_target.append(rec['invoiced_target']) + if inv_target == [None]: + inv_target = [0] + ytd_target = (sum(sales) + sum(inv_target)) + + self._cr.execute('''select sum(expected_revenue) from crm_lead where stage_id=4 + and team_id=%s AND Extract(Year FROM date_closed)=Extract(Year FROM DATE(NOW( + )))''' % team_id) + achieved_won_data = self._cr.dictfetchall() + achieved_won = [item['sum'] for item in achieved_won_data] + + else: + self._cr.execute('''SELECT res_users.id,res_users.sales FROM res_users + WHERE res_users.id = %s AND res_users.sales is not null;''' % session_user_id) + data4 = self._cr.dictfetchall() + + sales = [] + for rec in data4: + sales.append(rec['sales']) + ytd_target = (sum(sales)) + + self._cr.execute('''select sum(expected_revenue) from crm_lead where stage_id=4 + and user_id=%s AND Extract(Year FROM date_closed)=Extract(Year FROM DATE(NOW( + )))''' % session_user_id) + achieved_won_data = self._cr.dictfetchall() + achieved_won = [item['sum'] for item in achieved_won_data] + + won = achieved_won[0] + if won is None: + won = 0 + difference = target_annual - won + + self._cr.execute('''select COUNT(id) from crm_lead WHERE crm_lead.user_id = '%s' + AND Extract(MONTH FROM crm_lead.date_deadline) = Extract( MONTH FROM DATE(NOW())) + AND Extract(Year FROM crm_lead.date_deadline) = Extract(Year FROM DATE(NOW())) + ''' % session_user_id) + record = self._cr.dictfetchall() + rec_ids = [item['count'] for item in record] + crm_lead_value = rec_ids[0] + + self._cr.execute('''select COUNT(id) from crm_lead WHERE crm_lead.user_id = %s + AND crm_lead.type = 'opportunity' AND Extract(MONTH FROM crm_lead.date_deadline + ) = Extract(MONTH FROM DATE(NOW())) AND Extract(Year FROM crm_lead.date_deadline + ) = Extract(Year FROM DATE(NOW( )))''' % session_user_id) + opportunity_data = self._cr.dictfetchall() + opportunity_data_value = [item['count'] for item in opportunity_data] + opportunity_value = opportunity_data_value[0] + + self._cr.execute('''select SUM(crm_lead.expected_revenue) from crm_lead WHERE + crm_lead.user_id = %s and type='opportunity' and active='true' AND Extract(MONTH + FROM crm_lead.date_deadline) = Extract(MONTH FROM DATE(NOW())) AND Extract(Year + FROM crm_lead.date_deadline) = Extract(Year FROM DATE(NOW()))''' % session_user_id) + exp_revenue_data = self._cr.dictfetchall() + exp_revenue_data_value = [item['sum'] for item in exp_revenue_data] + exp_revenue_value = exp_revenue_data_value[0] + if exp_revenue_value is None: + exp_revenue_value = 0 + + self._cr.execute('''select SUM(crm_lead.expected_revenue) from crm_lead WHERE + crm_lead.user_id = %s and type='opportunity' and active='true' and stage_id=4 + AND Extract(MONTH FROM crm_lead.date_closed) = Extract(MONTH FROM DATE(NOW())) + AND Extract(Year FROM crm_lead.date_closed) = Extract(Year FROM DATE(NOW())) + ''' % session_user_id) + revenue_data = self._cr.dictfetchall() + revenue_data_value = [item['sum'] for item in revenue_data] + revenue_value = revenue_data_value[0] + if revenue_value is None: + revenue_value = 0 + + ratio_value = [] + if revenue_value == 0: + ratio_value = 0 + if revenue_value > 0: + self._cr.execute('''select case when b.count_two = 0 then 0 else ( + CAST(a.count_one as float) / CAST(b.count_two as float))end as final_count + from (select COUNT(id) as count_one from crm_lead WHERE + crm_lead.user_id = '%s' AND crm_lead.active = True AND crm_lead.probability = 100 + AND Extract(MONTH FROM crm_lead.date_deadline) = Extract(MONTH FROM DATE(NOW())) + AND Extract(Year FROM crm_lead.date_open) = Extract(Year FROM DATE(NOW())))a, + (select COUNT(id) as count_two from crm_lead WHERE crm_lead.user_id = '%s' AND + crm_lead.active = False AND crm_lead.probability = 0 AND Extract(MONTH FROM + crm_lead.date_deadline) = Extract(MONTH FROM DATE(NOW())) AND Extract(Year + FROM crm_lead.date_deadline) = Extract(Year FROM DATE(NOW())))b + ''' % (session_user_id, session_user_id)) + ratio_data_value = [row[0] for row in self._cr.fetchall()] + ratio_value = str(ratio_data_value)[1:-1] + + self._cr.execute('''SELECT active,count(active) FROM crm_lead where type='opportunity' + and active = true and probability = 100 and user_id=%s AND Extract(MONTH FROM date_closed + ) = Extract(MONTH FROM DATE(NOW())) AND Extract(Year FROM date_closed) = Extract( + Year FROM DATE(NOW())) or type='opportunity' and active = false and probability = 0 + and user_id=%s AND Extract(MONTH FROM date_deadline) = Extract(MONTH FROM DATE(NOW())) + AND Extract(Year FROM date_deadline) = Extract(Year FROM DATE(NOW())) GROUP BY active + ''' % (session_user_id, session_user_id)) + record_opportunity = dict(self._cr.fetchall()) + opportunity_ratio_value = 0.0 + if record_opportunity == {}: + opportunity_ratio_value = 0.0 + else: + total_opportunity_won = record_opportunity.get(False) + total_opportunity_lost = record_opportunity.get(True) + if total_opportunity_won is None: + total_opportunity_won = 0 + if total_opportunity_lost is None: + total_opportunity_lost = 0 + opportunity_ratio_value = 0.0 + if total_opportunity_lost > 0: + opportunity_ratio_value = round( + total_opportunity_won / total_opportunity_lost, 2) + + avg = 0 + if crm_lead_value == 1: + self._cr.execute('''SELECT id, date_conversion, create_date + FROM crm_lead WHERE date_conversion IS NOT NULL;''') + data = self._cr.dictfetchall() + for rec in data: + date_close = rec['date_conversion'] + date_create = rec['create_date'] + avg = (date_close - date_create).seconds + if crm_lead_value > 1: + self._cr.execute('''SELECT id, date_conversion, create_date + FROM crm_lead WHERE date_conversion IS NOT NULL;''') + data1 = self._cr.dictfetchall() + for rec in data1: + date_close = rec['date_conversion'] + date_create = rec['create_date'] + avg = (date_close - date_create).seconds + + avg_time = 0 if crm_lead_value == 0 else round(avg / crm_lead_value) + + data = { + 'record': crm_lead_value, + 'record_op': opportunity_value, + 'record_rev_exp': exp_revenue_value, + 'record_rev': revenue_value, + 'record_ratio': ratio_value, + 'opportunity_ratio_value': str(opportunity_ratio_value), + 'avg_time': avg_time, + 'count': value, + 'target': target_annual, + 'ytd_target': ytd_target, + 'difference': difference, + 'won': won, + } + return data + + @api.model + def crm_year(self): + """Year CRM Dropdown Filter""" + session_user_id = self.env.uid + print(session_user_id) + + self._cr.execute('''select COUNT(id) from crm_lead WHERE crm_lead.user_id = '%s' + AND Extract(Year FROM crm_lead.date_deadline) = Extract(Year FROM DATE(NOW())) + ''' % session_user_id) + record = self._cr.dictfetchall() + rec_ids = [item['count'] for item in record] + crm_lead_value = rec_ids[0] + + self._cr.execute('''select COUNT(id) from crm_lead WHERE crm_lead.user_id = %s + AND crm_lead.type = 'opportunity' AND Extract(Year FROM crm_lead.date_deadline + ) = Extract(Year FROM DATE(NOW()))''' % session_user_id) + opportunity_data = self._cr.dictfetchall() + opportunity_data_value = [item['count'] for item in opportunity_data] + opportunity_value = opportunity_data_value[0] + + self._cr.execute('''select SUM(crm_lead.expected_revenue) from crm_lead + WHERE crm_lead.user_id = %s and type='opportunity' and active='true' AND + Extract(Year FROM crm_lead.date_deadline) = Extract(Year FROM DATE(NOW())) + ''' % session_user_id) + exp_revenue_data = self._cr.dictfetchall() + exp_revenue_data_value = [item['sum'] for item in exp_revenue_data] + exp_revenue_value = exp_revenue_data_value[0] + if exp_revenue_value is None: + exp_revenue_value = 0 + + self._cr.execute('''select SUM(crm_lead.expected_revenue) from crm_lead + WHERE crm_lead.user_id = %s and type='opportunity' and active='true' and + stage_id=4 AND Extract(Year FROM crm_lead.date_closed) = Extract(Year + FROM DATE(NOW()))''' % session_user_id) + revenue_data = self._cr.dictfetchall() + revenue_data_value = [item['sum'] for item in revenue_data] + revenue_value = revenue_data_value[0] + print('revenue_value', revenue_value) + + if revenue_value is None: + revenue_value = 0 + + ratio_value = [] + if revenue_value == 0: + ratio_value = 0 + if revenue_value > 0: + self._cr.execute('''select case when b.count_two = 0 then 0 else ( + CAST(a.count_one as float) / CAST(b.count_two as float))end as final_count from ( + select COUNT(id) as count_one from crm_lead WHERE crm_lead.user_id = '%s' AND + crm_lead.active = True AND crm_lead.probability = 100 AND Extract(Year FROM + crm_lead.date_deadline) = Extract(Year FROM DATE(NOW())))a, + (select COUNT(id) as count_two from crm_lead WHERE crm_lead.user_id = '%s' AND + crm_lead.active = False AND crm_lead.probability = 0 AND Extract(Year FROM + crm_lead.date_deadline) = Extract(Year FROM DATE(NOW())))b + ''' % (session_user_id, session_user_id)) + ratio_value = [row[0] for row in self._cr.fetchall()] + print(ratio_value, 'ratio_value1') + ratio_value = str(ratio_value)[1:-1] + print(ratio_value, 'ratio_value2') + + self._cr.execute('''SELECT active,count(active) FROM crm_lead + where type='opportunity' and active = true and probability = 100 and user_id=%s + AND Extract(Year FROM date_closed) = Extract(Year FROM DATE(NOW())) + or type='opportunity' and active = false and probability = 0 and user_id=%s + AND Extract(Year FROM date_deadline) = Extract(Year FROM DATE(NOW())) + GROUP BY active''' % (session_user_id, session_user_id)) + record_opportunity = dict(self._cr.fetchall()) + opportunity_ratio_value = 0.0 + if record_opportunity == {}: + opportunity_ratio_value = 0.0 + else: + total_opportunity_won = record_opportunity.get(False) + total_opportunity_lost = record_opportunity.get(True) + if total_opportunity_won is None: + total_opportunity_won = 0 + if total_opportunity_lost is None: + total_opportunity_lost = 0 + opportunity_ratio_value = 0.0 + if total_opportunity_lost > 0: + opportunity_ratio_value = round( + total_opportunity_won / total_opportunity_lost, 2) + + avg = 0 + if crm_lead_value == 1: + self._cr.execute('''SELECT id, date_conversion, create_date + FROM crm_lead WHERE date_conversion IS NOT NULL;''') + data = self._cr.dictfetchall() + for rec in data: + date_close = rec['date_conversion'] + date_create = rec['create_date'] + avg = (date_close - date_create).seconds + if crm_lead_value > 1: + self._cr.execute('''SELECT id, date_conversion, create_date + FROM crm_lead WHERE date_conversion IS NOT NULL;''') + data1 = self._cr.dictfetchall() + for rec in data1: + date_close = rec['date_conversion'] + date_create = rec['create_date'] + avg = (date_close - date_create).seconds + + if crm_lead_value == 0: + record_avg_time = 0 + else: + record_avg_time = round(avg / crm_lead_value) + + data_year = { + 'record': crm_lead_value, + 'record_op': opportunity_value, + 'record_rev_exp': exp_revenue_value, + 'record_rev': revenue_value, + 'record_ratio': ratio_value, + 'opportunity_ratio_value': str(opportunity_ratio_value), + 'avg_time': record_avg_time, + } + return data_year + + @api.model + def crm_quarter(self): + """Quarter CRM Dropdown Filter""" + session_user_id = self.env.uid + + self._cr.execute('''select COUNT(id) from crm_lead WHERE crm_lead.user_id = '%s' + AND Extract(QUARTER FROM crm_lead.date_deadline) = Extract(QUARTER FROM DATE(NOW())) + AND Extract(Year FROM crm_lead.date_deadline) = Extract(Year FROM DATE(NOW())) + ''' % session_user_id) + record = self._cr.dictfetchall() + rec_ids = [item['count'] for item in record] + crm_lead_value = rec_ids[0] + + self._cr.execute('''select COUNT(id) from crm_lead WHERE crm_lead.user_id = %s + AND crm_lead.type = 'opportunity' AND Extract(QUARTER FROM crm_lead.date_deadline + ) = Extract(QUARTER FROM DATE(NOW())) AND Extract(Year FROM crm_lead.date_deadline + ) = Extract(Year FROM DATE(NOW( )))''' % session_user_id) + opportunity_data = self._cr.dictfetchall() + opportunity_data_value = [item['count'] for item in opportunity_data] + opportunity_value = opportunity_data_value[0] + + self._cr.execute('''select SUM(crm_lead.expected_revenue) from crm_lead WHERE + crm_lead.user_id = %s and type='opportunity' and active='true' AND Extract( + QUARTER FROM crm_lead.date_deadline) = Extract(QUARTER FROM DATE(NOW())) AND + Extract(Year FROM crm_lead.date_deadline) = Extract(Year FROM DATE(NOW())) + ''' % session_user_id) + exp_revenue_data = self._cr.dictfetchall() + exp_revenue_data_value = [item['sum'] for item in exp_revenue_data] + exp_revenue_value = exp_revenue_data_value[0] + if exp_revenue_value is None: + exp_revenue_value = 0 + + self._cr.execute('''select SUM(crm_lead.expected_revenue) from crm_lead WHERE + crm_lead.user_id = %s and type='opportunity' and active='true' and stage_id=4 + AND Extract(QUARTER FROM crm_lead.date_closed) = Extract(QUARTER FROM + DATE(NOW())) AND Extract(Year FROM crm_lead.date_closed) = Extract(Year + FROM DATE(NOW()))''' % session_user_id) + revenue_data = self._cr.dictfetchall() + revenue_data_value = [item['sum'] for item in revenue_data] + revenue_value = revenue_data_value[0] + if revenue_value is None: + revenue_value = 0 + + ratio_value = [] + if revenue_value == 0: + ratio_value = 0 + if revenue_value > 0: + self._cr.execute('''select case when b.count_two = 0 then 0 else ( + CAST(a.count_one as float) / CAST(b.count_two as float))end as final_count + from (select COUNT(id) as count_one from crm_lead + WHERE crm_lead.user_id = '%s' AND crm_lead.active = True AND + crm_lead.probability = 100 AND Extract(QUARTER FROM crm_lead.date_deadline + ) = Extract(QUARTER FROM DATE(NOW())) AND Extract(Year FROM crm_lead.date_open + ) = Extract(Year FROM DATE(NOW())))a, + (select COUNT(id) as count_two from crm_lead WHERE crm_lead.user_id = '%s' + AND crm_lead.active = False AND crm_lead.probability = 0 AND Extract( + QUARTER FROM crm_lead.date_deadline) = Extract(QUARTER FROM DATE(NOW())) + AND Extract(Year FROM crm_lead.date_deadline) = Extract(Year FROM DATE(NOW( + ))))b''' % (session_user_id, session_user_id)) + ratio_value = [row[0] for row in self._cr.fetchall()] + ratio_value = str(ratio_value)[1:-1] + + self._cr.execute('''SELECT active,count(active) FROM crm_lead + where type='opportunity' and active = true and probability = 100 and user_id=%s + AND Extract(QUARTER FROM date_closed) = Extract(QUARTER FROM DATE(NOW())) + AND Extract(Year FROM date_closed) = Extract(Year FROM DATE(NOW())) + or type='opportunity' and active = false and probability = 0 and user_id=%s + AND Extract(QUARTER FROM date_deadline) = Extract(QUARTER FROM DATE(NOW())) + AND Extract(Year FROM date_deadline) = Extract(Year FROM DATE(NOW())) + GROUP BY active''' % (session_user_id, session_user_id)) + record_opportunity = dict(self._cr.fetchall()) + opportunity_ratio_value = 0.0 + if record_opportunity == {}: + opportunity_ratio_value = 0.0 + else: + total_opportunity_won = record_opportunity.get(False) + total_opportunity_lost = record_opportunity.get(True) + if total_opportunity_won is None: + total_opportunity_won = 0 + if total_opportunity_lost is None: + total_opportunity_lost = 0 + opportunity_ratio_value = 0.0 + if total_opportunity_lost > 0: + opportunity_ratio_value = round( + total_opportunity_won / total_opportunity_lost, 2) + + avg = 0 + if crm_lead_value == 1: + self._cr.execute('''SELECT id, date_conversion, create_date + FROM crm_lead WHERE date_conversion IS NOT NULL;''') + data = self._cr.dictfetchall() + for rec in data: + date_close = rec['date_conversion'] + date_create = rec['create_date'] + avg = (date_close - date_create).seconds + if crm_lead_value > 1: + self._cr.execute('''SELECT id, date_conversion, create_date + FROM crm_lead WHERE date_conversion IS NOT NULL;''') + data1 = self._cr.dictfetchall() + for rec in data1: + date_close = rec['date_conversion'] + date_create = rec['create_date'] + avg = (date_close - date_create).seconds + + if crm_lead_value == 0: + record_avg_time = 0 + else: + record_avg_time = round(avg / crm_lead_value) + + data_quarter = { + 'record': crm_lead_value, + 'record_op': opportunity_value, + 'record_rev_exp': exp_revenue_value, + 'record_rev': revenue_value, + 'record_ratio': ratio_value, + 'opportunity_ratio_value': str(opportunity_ratio_value), + 'avg_time': record_avg_time, + } + return data_quarter + + @api.model + def crm_month(self): + """Month CRM Dropdown Filter""" + session_user_id = self.env.uid + + self._cr.execute('''select COUNT(id) from crm_lead WHERE crm_lead.user_id = '%s' + AND Extract(MONTH FROM crm_lead.date_deadline) = Extract(MONTH FROM DATE(NOW())) + AND Extract(Year FROM crm_lead.date_deadline) = Extract(Year FROM DATE(NOW())) + ''' % session_user_id) + record = self._cr.dictfetchall() + rec_ids = [item['count'] for item in record] + crm_lead_value = rec_ids[0] + + self._cr.execute('''select COUNT(id) from crm_lead WHERE crm_lead.user_id = %s + AND crm_lead.type = 'opportunity' AND Extract(MONTH FROM crm_lead.date_deadline + ) = Extract(MONTH FROM DATE(NOW())) AND Extract(Year FROM crm_lead.date_deadline + ) = Extract(Year FROM DATE(NOW( )))''' % session_user_id) + opportunity_data = self._cr.dictfetchall() + opportunity_data_value = [item['count'] for item in opportunity_data] + opportunity_value = opportunity_data_value[0] + + self._cr.execute('''select SUM(crm_lead.expected_revenue) from crm_lead WHERE + crm_lead.user_id = %s and type='opportunity' and active='true' AND Extract( + MONTH FROM crm_lead.date_deadline) = Extract(MONTH FROM DATE(NOW())) AND + Extract(Year FROM crm_lead.date_deadline) = Extract(Year FROM DATE(NOW())) + ''' % session_user_id) + exp_revenue_data = self._cr.dictfetchall() + exp_revenue_data_value = [item['sum'] for item in exp_revenue_data] + exp_revenue_value = exp_revenue_data_value[0] + if exp_revenue_value is None: + exp_revenue_value = 0 + + self._cr.execute('''select SUM(crm_lead.expected_revenue) from crm_lead WHERE + crm_lead.user_id = %s and type='opportunity' and active='true' and stage_id=4 + AND Extract(MONTH FROM crm_lead.date_closed) = Extract(MONTH FROM DATE(NOW())) + AND Extract(Year FROM crm_lead.date_closed) = Extract(Year FROM DATE(NOW())) + ''' % session_user_id) + revenue_data = self._cr.dictfetchall() + revenue_data_value = [item['sum'] for item in revenue_data] + revenue_value = revenue_data_value[0] + if revenue_value is None: + revenue_value = 0 + + ratio_value = [] + if revenue_value == 0: + ratio_value = 0 + if revenue_value > 0: + self._cr.execute('''select case when b.count_two = 0 then 0 else ( + CAST(a.count_one as float) / CAST(b.count_two as float))end as final_count + from (select COUNT(id) as count_one from crm_lead + WHERE crm_lead.user_id = '%s' AND crm_lead.active = True AND + crm_lead.probability = 100 AND Extract(MONTH FROM crm_lead.date_deadline + ) = Extract(MONTH FROM DATE(NOW())) AND Extract(Year FROM crm_lead.date_open + ) = Extract(Year FROM DATE(NOW())))a, + (select COUNT(id) as count_two from crm_lead WHERE crm_lead.user_id = '%s' + AND crm_lead.active = False AND crm_lead.probability = 0 AND Extract( + MONTH FROM crm_lead.date_deadline) = Extract(MONTH FROM DATE(NOW())) AND + Extract(Year FROM crm_lead.date_deadline) = Extract(Year FROM DATE(NOW())))b + ''' % (session_user_id, session_user_id)) + ratio_value = [row[0] for row in self._cr.fetchall()] + ratio_value = str(ratio_value)[1:-1] + + self._cr.execute('''SELECT active,count(active) FROM crm_lead + where type='opportunity' and active = true and probability = 100 and user_id=%s + AND Extract(MONTH FROM date_closed) = Extract(MONTH FROM DATE(NOW())) + AND Extract(Year FROM date_closed) = Extract(Year FROM DATE(NOW())) + or type='opportunity' and active = false and probability = 0 and user_id=%s + AND Extract(MONTH FROM date_deadline) = Extract(MONTH FROM DATE(NOW())) + AND Extract(Year FROM date_deadline) = Extract(Year FROM DATE(NOW())) + GROUP BY active''' % (session_user_id, session_user_id)) + record_opportunity = dict(self._cr.fetchall()) + opportunity_ratio_value = 0.0 + if record_opportunity == {}: + opportunity_ratio_value = 0.0 + else: + total_opportunity_won = record_opportunity.get(False) + total_opportunity_lost = record_opportunity.get(True) + if total_opportunity_won is None: + total_opportunity_won = 0 + if total_opportunity_lost is None: + total_opportunity_lost = 0 + opportunity_ratio_value = 0.0 + if total_opportunity_lost > 0: + opportunity_ratio_value = round( + total_opportunity_won / total_opportunity_lost, 2) + + avg = 0 + if crm_lead_value == 1: + self._cr.execute('''SELECT id, date_conversion, create_date + FROM crm_lead WHERE date_conversion IS NOT NULL;''') + data = self._cr.dictfetchall() + for rec in data: + date_close = rec['date_conversion'] + date_create = rec['create_date'] + avg = (date_close - date_create).seconds + if crm_lead_value > 1: + self._cr.execute('''SELECT id, date_conversion, create_date + FROM crm_lead WHERE date_conversion IS NOT NULL;''') + data1 = self._cr.dictfetchall() + for rec in data1: + date_close = rec['date_conversion'] + date_create = rec['create_date'] + avg = (date_close - date_create).seconds + + record_avg_time = 0 if crm_lead_value == 0 else round( + avg / crm_lead_value) + + data_month = { + 'record': crm_lead_value, + 'record_op': opportunity_value, + 'record_rev_exp': exp_revenue_value, + 'record_rev': revenue_value, + 'record_ratio': ratio_value, + 'opportunity_ratio_value': str(opportunity_ratio_value), + 'avg_time': record_avg_time, + } + return data_month + + @api.model + def crm_week(self): + """Week CRM Dropdown Filter""" + session_user_id = self.env.uid + + self._cr.execute('''select COUNT(id) from crm_lead WHERE crm_lead.user_id = '%s' + AND Extract(MONTH FROM crm_lead.date_deadline) = Extract(MONTH FROM DATE(NOW())) + AND Extract(Week FROM crm_lead.date_deadline) = Extract(Week FROM DATE(NOW())) AND + Extract(Year FROM crm_lead.date_deadline) = Extract(Year FROM DATE(NOW())) + ''' % session_user_id) + record = self._cr.dictfetchall() + rec_ids = [item['count'] for item in record] + crm_lead_value = rec_ids[0] + + self._cr.execute('''select COUNT(id) from crm_lead WHERE crm_lead.user_id = %s + AND crm_lead.type = 'opportunity' AND Extract(MONTH FROM crm_lead.date_deadline + ) = Extract(MONTH FROM DATE(NOW())) AND Extract(Week FROM crm_lead.date_deadline + ) = Extract(Week FROM DATE(NOW())) AND Extract(Year FROM crm_lead.date_deadline + ) = Extract(Year FROM DATE(NOW()))''' % session_user_id) + opportunity_data = self._cr.dictfetchall() + opportunity_data_value = [item['count'] for item in opportunity_data] + opportunity_value = opportunity_data_value[0] + + self._cr.execute('''select SUM(crm_lead.expected_revenue) from crm_lead WHERE + crm_lead.user_id = %s and type='opportunity' and active='true' AND Extract( + MONTH FROM crm_lead.date_deadline) = Extract(MONTH FROM DATE(NOW())) AND + Extract(Week FROM crm_lead.date_deadline) = Extract(Week FROM DATE(NOW())) + AND Extract(Year FROM crm_lead.date_deadline) = Extract(Year FROM DATE(NOW())) + ''' % session_user_id) + exp_revenue_data = self._cr.dictfetchall() + exp_revenue_data_value = [item['sum'] for item in exp_revenue_data] + exp_revenue_value = exp_revenue_data_value[0] + if exp_revenue_value is None: + exp_revenue_value = 0 + + self._cr.execute('''select SUM(crm_lead.expected_revenue) from crm_lead WHERE + crm_lead.user_id = %s and type='opportunity' and active='true' and stage_id=4 + AND Extract(MONTH FROM crm_lead.date_closed) = Extract(MONTH FROM DATE(NOW())) + AND Extract(Week FROM crm_lead.date_closed) = Extract(Week FROM DATE(NOW())) + AND Extract(Year FROM crm_lead.date_closed) = Extract(Year FROM DATE(NOW())) + ''' % session_user_id) + revenue_data = self._cr.dictfetchall() + revenue_data_value = [item['sum'] for item in revenue_data] + revenue_value = revenue_data_value[0] + if revenue_value is None: + revenue_value = 0 + + ratio_value = [] + if revenue_value == 0: + ratio_value = 0 + if revenue_value > 0: + self._cr.execute('''select case when b.count_two = 0 then 0 else ( + CAST(a.count_one as float) / CAST(b.count_two as float))end as final_count + from (select COUNT(id) as count_one from crm_lead + WHERE crm_lead.user_id = '%s' AND crm_lead.active = True AND + crm_lead.probability = 100 AND Extract(MONTH FROM crm_lead.date_deadline + ) = Extract(MONTH FROM DATE(NOW())) AND Extract(Week FROM crm_lead.date_deadline + ) = Extract(Week FROM DATE(NOW())) AND Extract(Year FROM crm_lead.date_open + ) = Extract(Year FROM DATE(NOW())))a, + (select COUNT(id) as count_two from crm_lead WHERE crm_lead.user_id = '%s' + AND crm_lead.active = False AND crm_lead.probability = 0 AND Extract(MONTH + FROM crm_lead.date_deadline) = Extract(MONTH FROM DATE(NOW())) AND Extract(Week + FROM crm_lead.date_deadline) = Extract(Week FROM DATE(NOW())) AND Extract(Year FROM + crm_lead.date_deadline) = Extract(Year FROM DATE(NOW())))b + ''' % (session_user_id, session_user_id)) + ratio_value = [row[0] for row in self._cr.fetchall()] + ratio_value = str(ratio_value)[1:-1] + + self._cr.execute('''SELECT active,count(active) FROM crm_lead + where type='opportunity' and active = true and probability = 100 and user_id=%s + AND Extract(MONTH FROM crm_lead.date_closed) = Extract(MONTH FROM DATE(NOW())) + AND Extract(Week FROM crm_lead.date_closed) = Extract(Week FROM DATE(NOW())) + AND Extract(Year FROM crm_lead.date_closed) = Extract(Year FROM DATE(NOW())) + or type='opportunity' and active = false and probability = 0 and user_id=%s + AND Extract(MONTH FROM crm_lead.date_deadline) = Extract(MONTH FROM DATE(NOW())) + AND Extract(Week FROM crm_lead.date_deadline) = Extract(Week FROM DATE(NOW())) + AND Extract(Year FROM crm_lead.date_deadline) = Extract(Year FROM DATE(NOW())) + GROUP BY active''' % (session_user_id, session_user_id)) + record_opportunity = dict(self._cr.fetchall()) + opportunity_ratio_value = 0.0 + if record_opportunity == {}: + opportunity_ratio_value = 0.0 + else: + total_opportunity_won = record_opportunity.get(False) + total_opportunity_lost = record_opportunity.get(True) + if total_opportunity_won is None: + total_opportunity_won = 0 + if total_opportunity_lost is None: + total_opportunity_lost = 0 + opportunity_ratio_value = 0.0 + if total_opportunity_lost > 0: + opportunity_ratio_value = round( + total_opportunity_won / total_opportunity_lost, 2) + + avg = 0 + if crm_lead_value == 1: + self._cr.execute('''SELECT id, date_conversion, create_date + FROM crm_lead WHERE date_conversion IS NOT NULL;''') + data = self._cr.dictfetchall() + for rec in data: + date_close = rec['date_conversion'] + date_create = rec['create_date'] + avg = (date_close - date_create).seconds + if crm_lead_value > 1: + self._cr.execute('''SELECT id, date_conversion, create_date + FROM crm_lead WHERE date_conversion IS NOT NULL;''') + data1 = self._cr.dictfetchall() + for rec in data1: + date_close = rec['date_conversion'] + date_create = rec['create_date'] + avg = (date_close - date_create).seconds + + if crm_lead_value == 0: + record_avg_time = 0 + else: + record_avg_time = round(avg / crm_lead_value) + + data_week = { + 'record': crm_lead_value, + 'record_op': opportunity_value, + 'record_rev_exp': exp_revenue_value, + 'record_rev': revenue_value, + 'record_ratio': ratio_value, + 'opportunity_ratio_value': str(opportunity_ratio_value), + 'avg_time': record_avg_time, + } + return data_week + + +class CampaignSmartButton(models.Model): + _inherit = 'utm.campaign' + + total_ratio = fields.Float(compute='_compute_ratio') + + def get_ratio(self): + """Onclick of Smart Button""" + self.ensure_one() + + return { + 'type': 'ir.actions.act_window', + 'name': 'Win Loss Ratio', + 'view_mode': 'kanban', + 'res_model': 'crm.lead', + 'domain': [['user_id', '=', self.env.uid], "|", + "&", ["active", "=", True], ["probability", '=', 100], + "&", ["active", "=", False], ["probability", '=', 0] + ], + 'context': "{'create': False,'records_draggable': False}" + } + + def _compute_ratio(self): + print('the Win Loss Ratio') + """Compute the Win Loss Ratio""" + total_won = self.env['crm.lead'].search_count( + [('active', '=', True), ('probability', '=', 100), + ('user_id', '=', self.env.uid)]) + total_lose = self.env['crm.lead'].search_count( + [('active', '=', False), ('probability', '=', 0), + ('user_id', '=', self.env.uid)]) + + if total_lose == 0: + ratio = 0 + else: + ratio = round(total_won / total_lose, 2) + self.total_ratio = ratio diff --git a/crm_dashboard/static/description/assets/icons/check.png b/crm_dashboard/static/description/assets/icons/check.png new file mode 100644 index 000000000..c8e85f51d Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/check.png differ diff --git a/crm_dashboard/static/description/assets/icons/chevron.png b/crm_dashboard/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..2089293d6 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/chevron.png differ diff --git a/crm_dashboard/static/description/assets/icons/cogs.png b/crm_dashboard/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/cogs.png differ diff --git a/crm_dashboard/static/description/assets/icons/consultation.png b/crm_dashboard/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/consultation.png differ diff --git a/crm_dashboard/static/description/assets/icons/ecom-black.png b/crm_dashboard/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/ecom-black.png differ diff --git a/crm_dashboard/static/description/assets/icons/education-black.png b/crm_dashboard/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/education-black.png differ diff --git a/crm_dashboard/static/description/assets/icons/hotel-black.png b/crm_dashboard/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/hotel-black.png differ diff --git a/crm_dashboard/static/description/assets/icons/license.png b/crm_dashboard/static/description/assets/icons/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/license.png differ diff --git a/crm_dashboard/static/description/assets/icons/lifebuoy.png b/crm_dashboard/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/lifebuoy.png differ diff --git a/crm_dashboard/static/description/assets/icons/manufacturing-black.png b/crm_dashboard/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/manufacturing-black.png differ diff --git a/crm_dashboard/static/description/assets/icons/pos-black.png b/crm_dashboard/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/pos-black.png differ diff --git a/crm_dashboard/static/description/assets/icons/puzzle.png b/crm_dashboard/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/puzzle.png differ diff --git a/crm_dashboard/static/description/assets/icons/restaurant-black.png b/crm_dashboard/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/restaurant-black.png differ diff --git a/crm_dashboard/static/description/assets/icons/service-black.png b/crm_dashboard/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/service-black.png differ diff --git a/crm_dashboard/static/description/assets/icons/trading-black.png b/crm_dashboard/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/trading-black.png differ diff --git a/crm_dashboard/static/description/assets/icons/training.png b/crm_dashboard/static/description/assets/icons/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/training.png differ diff --git a/crm_dashboard/static/description/assets/icons/update.png b/crm_dashboard/static/description/assets/icons/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/update.png differ diff --git a/crm_dashboard/static/description/assets/icons/user.png b/crm_dashboard/static/description/assets/icons/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/user.png differ diff --git a/crm_dashboard/static/description/assets/icons/wrench.png b/crm_dashboard/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/crm_dashboard/static/description/assets/icons/wrench.png differ diff --git a/crm_dashboard/static/description/assets/misc/categories.png b/crm_dashboard/static/description/assets/misc/categories.png new file mode 100644 index 000000000..bedf1e0b1 Binary files /dev/null and b/crm_dashboard/static/description/assets/misc/categories.png differ diff --git a/crm_dashboard/static/description/assets/misc/check-box.png b/crm_dashboard/static/description/assets/misc/check-box.png new file mode 100644 index 000000000..42caf24b9 Binary files /dev/null and b/crm_dashboard/static/description/assets/misc/check-box.png differ diff --git a/crm_dashboard/static/description/assets/misc/compass.png b/crm_dashboard/static/description/assets/misc/compass.png new file mode 100644 index 000000000..d5fed8faa Binary files /dev/null and b/crm_dashboard/static/description/assets/misc/compass.png differ diff --git a/crm_dashboard/static/description/assets/misc/corporate.png b/crm_dashboard/static/description/assets/misc/corporate.png new file mode 100644 index 000000000..2eb13edbf Binary files /dev/null and b/crm_dashboard/static/description/assets/misc/corporate.png differ diff --git a/crm_dashboard/static/description/assets/misc/customer-support.png b/crm_dashboard/static/description/assets/misc/customer-support.png new file mode 100644 index 000000000..79efc72ed Binary files /dev/null and b/crm_dashboard/static/description/assets/misc/customer-support.png differ diff --git a/crm_dashboard/static/description/assets/misc/cybrosys-logo.png b/crm_dashboard/static/description/assets/misc/cybrosys-logo.png new file mode 100644 index 000000000..cc3cc0ccf Binary files /dev/null and b/crm_dashboard/static/description/assets/misc/cybrosys-logo.png differ diff --git a/crm_dashboard/static/description/assets/misc/features.png b/crm_dashboard/static/description/assets/misc/features.png new file mode 100644 index 000000000..b41769f77 Binary files /dev/null and b/crm_dashboard/static/description/assets/misc/features.png differ diff --git a/crm_dashboard/static/description/assets/misc/logo.png b/crm_dashboard/static/description/assets/misc/logo.png new file mode 100644 index 000000000..478462d3e Binary files /dev/null and b/crm_dashboard/static/description/assets/misc/logo.png differ diff --git a/crm_dashboard/static/description/assets/misc/pictures.png b/crm_dashboard/static/description/assets/misc/pictures.png new file mode 100644 index 000000000..56d255fe9 Binary files /dev/null and b/crm_dashboard/static/description/assets/misc/pictures.png differ diff --git a/crm_dashboard/static/description/assets/misc/pie-chart.png b/crm_dashboard/static/description/assets/misc/pie-chart.png new file mode 100644 index 000000000..426e05244 Binary files /dev/null and b/crm_dashboard/static/description/assets/misc/pie-chart.png differ diff --git a/crm_dashboard/static/description/assets/misc/right-arrow.png b/crm_dashboard/static/description/assets/misc/right-arrow.png new file mode 100644 index 000000000..730984a06 Binary files /dev/null and b/crm_dashboard/static/description/assets/misc/right-arrow.png differ diff --git a/crm_dashboard/static/description/assets/misc/star.png b/crm_dashboard/static/description/assets/misc/star.png new file mode 100644 index 000000000..2eb9ab29f Binary files /dev/null and b/crm_dashboard/static/description/assets/misc/star.png differ diff --git a/crm_dashboard/static/description/assets/misc/support.png b/crm_dashboard/static/description/assets/misc/support.png new file mode 100644 index 000000000..4f18b8b82 Binary files /dev/null and b/crm_dashboard/static/description/assets/misc/support.png differ diff --git a/crm_dashboard/static/description/assets/misc/whatsapp.png b/crm_dashboard/static/description/assets/misc/whatsapp.png new file mode 100644 index 000000000..d513a5356 Binary files /dev/null and b/crm_dashboard/static/description/assets/misc/whatsapp.png differ diff --git a/crm_dashboard/static/description/assets/modules/1.png b/crm_dashboard/static/description/assets/modules/1.png new file mode 100644 index 000000000..5238bdeab Binary files /dev/null and b/crm_dashboard/static/description/assets/modules/1.png differ diff --git a/crm_dashboard/static/description/assets/modules/2.png b/crm_dashboard/static/description/assets/modules/2.png new file mode 100644 index 000000000..1ae7cfe3b Binary files /dev/null and b/crm_dashboard/static/description/assets/modules/2.png differ diff --git a/crm_dashboard/static/description/assets/modules/3.png b/crm_dashboard/static/description/assets/modules/3.png new file mode 100644 index 000000000..3c3ff1afb Binary files /dev/null and b/crm_dashboard/static/description/assets/modules/3.png differ diff --git a/crm_dashboard/static/description/assets/modules/4.png b/crm_dashboard/static/description/assets/modules/4.png new file mode 100644 index 000000000..3fae4631e Binary files /dev/null and b/crm_dashboard/static/description/assets/modules/4.png differ diff --git a/crm_dashboard/static/description/assets/modules/5.gif b/crm_dashboard/static/description/assets/modules/5.gif new file mode 100644 index 000000000..2a5f8e659 Binary files /dev/null and b/crm_dashboard/static/description/assets/modules/5.gif differ diff --git a/crm_dashboard/static/description/assets/modules/6.png b/crm_dashboard/static/description/assets/modules/6.png new file mode 100644 index 000000000..7f2815273 Binary files /dev/null and b/crm_dashboard/static/description/assets/modules/6.png differ diff --git a/crm_dashboard/static/description/assets/screenshots/1.png b/crm_dashboard/static/description/assets/screenshots/1.png new file mode 100644 index 000000000..14ac5ab80 Binary files /dev/null and b/crm_dashboard/static/description/assets/screenshots/1.png differ diff --git a/crm_dashboard/static/description/assets/screenshots/2.png b/crm_dashboard/static/description/assets/screenshots/2.png new file mode 100644 index 000000000..ed1b65a9b Binary files /dev/null and b/crm_dashboard/static/description/assets/screenshots/2.png differ diff --git a/crm_dashboard/static/description/assets/screenshots/3.png b/crm_dashboard/static/description/assets/screenshots/3.png new file mode 100644 index 000000000..ce996c1c4 Binary files /dev/null and b/crm_dashboard/static/description/assets/screenshots/3.png differ diff --git a/crm_dashboard/static/description/assets/screenshots/4.png b/crm_dashboard/static/description/assets/screenshots/4.png new file mode 100644 index 000000000..ee7d8c295 Binary files /dev/null and b/crm_dashboard/static/description/assets/screenshots/4.png differ diff --git a/crm_dashboard/static/description/assets/screenshots/5.png b/crm_dashboard/static/description/assets/screenshots/5.png new file mode 100644 index 000000000..8e2ec9297 Binary files /dev/null and b/crm_dashboard/static/description/assets/screenshots/5.png differ diff --git a/crm_dashboard/static/description/assets/screenshots/6.png b/crm_dashboard/static/description/assets/screenshots/6.png new file mode 100644 index 000000000..2aacae247 Binary files /dev/null and b/crm_dashboard/static/description/assets/screenshots/6.png differ diff --git a/crm_dashboard/static/description/assets/screenshots/7.png b/crm_dashboard/static/description/assets/screenshots/7.png new file mode 100644 index 000000000..2f852bb75 Binary files /dev/null and b/crm_dashboard/static/description/assets/screenshots/7.png differ diff --git a/crm_dashboard/static/description/assets/screenshots/8.png b/crm_dashboard/static/description/assets/screenshots/8.png new file mode 100644 index 000000000..e4dd7b3b8 Binary files /dev/null and b/crm_dashboard/static/description/assets/screenshots/8.png differ diff --git a/crm_dashboard/static/description/assets/screenshots/9.png b/crm_dashboard/static/description/assets/screenshots/9.png new file mode 100644 index 000000000..35dfc0155 Binary files /dev/null and b/crm_dashboard/static/description/assets/screenshots/9.png differ diff --git a/crm_dashboard/static/description/assets/screenshots/hero.gif b/crm_dashboard/static/description/assets/screenshots/hero.gif new file mode 100644 index 000000000..5d8e7c397 Binary files /dev/null and b/crm_dashboard/static/description/assets/screenshots/hero.gif differ diff --git a/crm_dashboard/static/description/banner.png b/crm_dashboard/static/description/banner.png new file mode 100644 index 000000000..25ed3e0b6 Binary files /dev/null and b/crm_dashboard/static/description/banner.png differ diff --git a/crm_dashboard/static/description/icon.png b/crm_dashboard/static/description/icon.png new file mode 100644 index 000000000..664c5b353 Binary files /dev/null and b/crm_dashboard/static/description/icon.png differ diff --git a/crm_dashboard/static/description/index.html b/crm_dashboard/static/description/index.html new file mode 100644 index 000000000..92b430099 --- /dev/null +++ b/crm_dashboard/static/description/index.html @@ -0,0 +1,648 @@ +
+ +
+ +
+
+ Community +
+
+ Enterprise +
+
+ Odoo.sh +
+
+
+ + + +

CRM Dashboard

+

Detailed Dashboard View for CRM.

+ + + +
+ + +
+
+ +
+

Explore This + Module

+
+ + + + +
+
+ +
+

Overview +

+
+
+
+ The CRM Dashboard module helps you to see the Overview of the CRM module + and its functioning. The Odoo CRM module will provide a complete + over of the entire functional aspects of the Customer Relationship Management + operations which are conducted with Odoo CRM. Moreover, you will attain a clear + insight into the Leads, Opportunities, Expected, and Total Revenue. + The Dashboard can be viewed in two different formats one for the Admin and + another for the User. In the case of the Admin, the CRM Dashboard will provide + a complete insight on the operations of the CRM providing a complete insight + into the operations. Whereas in the case of the user they will only obtain + certain of the details which they have been providing authorization. + The user authorization differs based on their job role. For example, + a Sales person will not have the same dashboard as that of a Sales Manager. +
+ Furthermore, we can view the different types of reports in the form of graphs + according to the values and operations of CRM providing the viewer with complete + insight into the real-time operations of the CRM operations of the company. +
+
+ + + +
+
+ +
+

Features +

+
+
+
+
+ + Dedicated Views for Users and Admins. +
+
+ + The users will have different authorization based on + the employment level. +
+
+ + Activity monitoring. +
+ +
+ + Insight on Upcoming and Recent activities. +
+ +
+ + Year to Date bar graphTarget Field in User Settings. +
+ +
+ + Opportunity Lost reason management. +
+ +
+ + Top deals and Monthly revenue goals. +
+ +
+ + Clickable Dashboard Cards. +
+ +
+
+ + + +
+
+ +
+

Screenshots +

+
+
+
+ +
+

Clickable Dashboard Cards

+

You can click on the respective Cards which will direct the users to the respective information + and aspects of the CRM operations with Odoo. Moreover, these Clickable Cards will act as a + navigation + icon within the CRM dashboard for the easiness of operations. Furthermore, these Clickable Cards + will + ensure that the configuration and the operations of the CRM dashboard are the way you need them.

+ +
+ +
+

Target, Lead and Activity analysis

+

A dedicated Funnel Chart provides you with complete insight into the Leads which are in operation. + The leads will be depicted as New, Qualified, Proposition, and Won. Moreover, the Year date target + will provide an insight into the goals which are achieved. The Donut graph based on the monthly + Lead operation will provide a clear picture of the monthly Lead operations. Additionally, the + Activity Donut graph will describe the activity analysis on the leads.

+ +
+ +
+

Set up Individual user targets

+

With the CRM Dashboard configuration, you will be able to set the individual target amount for + the Leads to be acquired by a user for a period of time, which can be set as Date, Month or Year. + The Targets can be set under the Settings tab > User Settings > Below the access right tab.

+ +
+ +
+

A dedicated Listing of Top Deals and the Monthly Goal Gauge motivates users

+

The Top Deals on the products and services will be listed out in a dedicated menu which helps + the users and the Salesperson to deal with the Leads and Opportunities with respect to it. + Moreover, this will be a useful tool in promoting the various deals instantly to the Leads + and the Opportunities.
+ The Monthly Goal Gauges that are available will serve as a motivation booster for the Sales + team as well as the users to pursue on more leads to achieve the target. Additionally, + the Lead Groping analysis with the help of the graph in the form of Donut providing analysis + on Lead Groups by Medium, Campaign, and Source will be helpful for the business.

+ +
+ +
+

Upcoming Activities and Total Revenue

+

Activity management is vital for CRM operations and the CRM Dashboard will provide a dedicated + tab defining the upcoming activities. These tabs will be different for each user based on their + operations in the company. Moreover, the Admin will have a separate view of their own activities + having clearer insight into the operations.
+ Furthermore, the Total Revenue of the respective Salesperson will be depicted in the form of + a graph providing the complete insight into the Revenue from the Leads which are being generated.

+ +
+ +
+

An informative Heat Map

+

In the CRM Dashboard, you will obtain an informative heat map on the aspects of the Revenue + obtained based on the CRM operations. Here the Top Salesperson, as well as Top Country Revenues, + will be depicted with a color-coordinated Heat map providing clear insight on the financial + values of revenue which is being generated. Moreover, a detailed tab will provide the information + on the country-vise count on the opportunities which are being attained. The Country-wise count + is also depicted on a heat map.

+ +
+ +
+

Lost Analysis, Recent Activities, and Top Salesperson.

+

You will get an insight on the lost opportunities and Leads from the Lost Analysis Graph providing + a clearer insight based on year or month. The Recent Activities description tab will provide + a complete insight on the Activities which have been scheduled and conducted recently in regard to + the Customer Relationship management operations on the pursuing of Leads and Opportunities.

+ +
+ +
+

Dashboard View of the User

+

As mentioned earlier there are dedicated views for the Admin as well as the User who has access + to the CRM Dashboard. The Following screenshot depicts the User view of the CRM Dashboard. + Here the information relating to the respective user and their operations will be only depicted + and the ones which the respective User has authorization to can be modified..

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

Related + 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

+
+
+
+
+
+
+
+ +
+
+
+ \ No newline at end of file diff --git a/crm_dashboard/static/src/css/dashboard.css b/crm_dashboard/static/src/css/dashboard.css new file mode 100644 index 000000000..335e5831e --- /dev/null +++ b/crm_dashboard/static/src/css/dashboard.css @@ -0,0 +1,34 @@ +p, span, a, ul, li, button { + font-size: inherit; + font-weight: inherit; + line-height: inherit; +} + +strong { + font-weight: 600; +} + +h1, h2, h3, h4, h5, h6 { + line-height: 1.5em; + font-weight: 300; +} + +strong { + font-weight: 400; +} + +.sub_title { + font-size: 14px; +} + +.sub_title div span { + font-weight: 600; +} + +.chart #canvas_graph { + height: 400px !important; +} + +.highcharts-background { + fill: none; +} \ No newline at end of file diff --git a/crm_dashboard/static/src/css/material-gauge.css b/crm_dashboard/static/src/css/material-gauge.css new file mode 100644 index 000000000..7f553df9a --- /dev/null +++ b/crm_dashboard/static/src/css/material-gauge.css @@ -0,0 +1,194 @@ +/* + * #### Gauge Component + * + * The standard markup for the component is: + * + *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * No + * + * Yes + *
+ *
+ */ + +/* + * First define all of the relevant rules that aren't dependent + * on the size of the gauge. We want to collect the size-depenent + * rules in one place to make it easier to adjust the size. + */ + +.gauge { + position: relative; +} + +.gauge__container { + margin: 0; + padding: 0; + position: absolute; + left: 50%; + overflow: hidden; + text-align: center; + -webkit-transform: translateX(-50%); + -moz-transform: translateX(-50%); + -ms-transform: translateX(-50%); + -o-transform: translateX(-50%); + transform: translateX(-50%); +} + +.gauge__background { + z-index: 0; + position: absolute; + background-color: #d8f0de; + top: 0; + border-radius: 300px 300px 0 0; +} + +.gauge__data { + z-index: 1; + position: absolute; + background-color: #00c29d; + margin-left: auto; + margin-right: auto; + border-radius: 300px 300px 0 0; + -webkit-transform-origin: center bottom; + -moz-transform-origin: center bottom; + -ms-transform-origin: center bottom; + -o-transform-origin: center bottom; + transform-origin: center bottom; +} + +.gauge__center { + z-index: 2; + position: absolute; + background-color: #f9f9f9; + margin-right: auto; + border-radius: 300px 300px 0 0; +} + +.gauge__marker { + z-index: 3; + background-color: #fff; + position: absolute; + width: 1px; +} + +.gauge__needle { + z-index: 4; + background-color: #21242c; + height: 3px; + position: absolute; + -webkit-transform-origin: left center; + -moz-transform-origin: left center; + -ms-transform-origin: left center; + -o-transform-origin: left center; + transform-origin: left center; +} + +.gauge__labels { + display: table; + margin: 0 auto; + position: relative; +} + +.gauge__label--low { + display: table-cell; + text-align: center; + color: #00c29d; +} + +.gauge__label--spacer { + display: table-cell; +} + +.gauge__label--high { + display: table-cell; + text-align: center; + color: #979f99; +} + +/* + * Now define the rules that depend on the size of + * the gauge. We start with sizing for a small mobile + * device. + */ + +.gauge { height: calc(120px + 3em); } +.gauge__container { width: 240px; height: 120px; } +.gauge__marker { height: 120px; left: 119.5px; } +.gauge__background { width: 240px; height: 120px; } +.gauge__center { width: 144px; height: 72px; top: 48px; margin-left: 48px; } +.gauge__data { width: 240px; height: 120px; } +.gauge__needle { left: 120px; top: 117px; width: 120px; } +.gauge__labels { top: 120px; width: 240px; } +.gauge__label--low { width: 48px; } +.gauge__label--spacer { width: 144px; } +.gauge__label--high { width: 48px; } + +/* + * Increase the gauge size slightly on larger viewports. + */ + + @media only screen and (min-width: 400px) { + .gauge { height: calc(150px + 3em); } + .gauge__container { width: 300px; height: 150px; } + .gauge__marker { height: 150px; left: 149.5px; } + .gauge__background { width: 300px; height: 150px; } + .gauge__center { width: 180px; height: 90px; top: 60px; margin-left: 60px; } + .gauge__data { width: 300px; height: 150px; } + .gauge__needle { left: 150px; top: 147px; width: 150px; } + .gauge__labels { top: 160px; width: 300px; font-size: 20px;} + .gauge__label--low { width: 60px; } + .gauge__label--spacer { width: 180px; } + .gauge__label--high { width: 60px; } +} + +/* + * As an option, the `gauge--liveupdate` class can be added + * to the main gauge element. When this class is present, + * we add a transition that animates any changes to the gauge + * value. Currently, the app does not use this option because + * all the inputs that can change gauge values are present + * on tab panels that are different from the gauge itself. + * Therefore, users won't be able to see any gauge changes + * when they make input changes. The code is available, though, + * should this change. + */ + +.gauge--liveupdate .gauge__data, +.gauge--liveupdate .gauge__needle { + -webkit-transition: all 1s ease-in-out; + -moz-transition: all 1s ease-in-out; + -ms-transition: all 1s ease-in-out; + -o-transition: all 1s ease-in-out; + transition: all 1s ease-in-out; +} + +/* + * For a given gauge value, x, ranging from 0.0 to 1.0, set + * the `transform: rotate()` property according to the + * following equation: `-0.5 + 0.5x turns` The default + * properties below represent an x value of 0. + */ + +.gauge__data { + -webkit-transform: rotate(-.50turn); + -moz-transform: rotate(-.50turn); + -ms-transform: rotate(-.50turn); + -o-transform: rotate(-.50turn); + transform: rotate(-.50turn); +} +.gauge__needle { + -webkit-transform: rotate(-.50turn); + -moz-transform: rotate(-.50turn); + -ms-transform: rotate(-.50turn); + -o-transform: rotate(-.50turn); + transform: rotate(-.50turn); +} diff --git a/crm_dashboard/static/src/css/style.scss b/crm_dashboard/static/src/css/style.scss new file mode 100644 index 000000000..b189646c4 --- /dev/null +++ b/crm_dashboard/static/src/css/style.scss @@ -0,0 +1,237 @@ +: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: 1rem; + 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: 1.7rem; + background-color: var(--mauve-light); + color: var(--mauve); + height: 50px; + width: 50px; + border-radius: 50%; + 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 */ +thead { + background-color: #e9ecf0; + border-bottom: none; +} + +.table thead th { + border-bottom: none; +} + +.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; +} + +.crm_scroll_table .count-container { + height: 45px; + width: 130px; + border-radius: 50px; + margin-right: 10px; +} + +.crm_scroll_table .item-content ul > li { + font-size: 1.1rem; +} \ No newline at end of file diff --git a/crm_dashboard/static/src/js/custom.js b/crm_dashboard/static/src/js/custom.js new file mode 100644 index 000000000..8dc84ba88 --- /dev/null +++ b/crm_dashboard/static/src/js/custom.js @@ -0,0 +1,41 @@ +odoo.define('crm_dashboard.custom', function (require) { + 'use strict'; + + var rpc = require('web.rpc'); + var manager = false; + rpc.query({ + model: "crm.lead", + method: "check_user_group", + }) + .then(function (res) { + manager = res; + }); + + $(document).on("mouseenter", ".dashboard_main_section", function(event){ + if (manager) { + var percentage_crm = $('#percentage_crm').val(); + var gauge = new Gauge(document.getElementById("gauge")); + gauge.value(percentage_crm); + $('#country_revenue_table').columnHeatmap({ + columns: [1], + inverse:true, + }); + $('#country_count_table').columnHeatmap({ + columns: [1], + inverse:true, + }); + $('#salesperson_revenue_table').columnHeatmap({ + columns: [1], + inverse:true, + }); + } + }); +// $(document).on("click", "#view_lost_dashboard", function(event){ +// $(".dashboard_main_section").css({'display':'none'}); +// $("#dashboard_sub_section").css({'display':'block'}); +// }); +// function BreadcrumbSubDash(){ +// $(".dashboard_main_section").css({'display':'block'}); +// $("#dashboard_sub_section").css({'display':'none'}); +// }; +}); \ No newline at end of file diff --git a/crm_dashboard/static/src/js/dashboard_view.js b/crm_dashboard/static/src/js/dashboard_view.js new file mode 100644 index 000000000..57e37a96c --- /dev/null +++ b/crm_dashboard/static/src/js/dashboard_view.js @@ -0,0 +1,1656 @@ +odoo.define('crm_dashboard.CRMDashboard', function (require) { + 'use strict'; + + var AbstractAction = require('web.AbstractAction'); + var ajax = require('web.ajax'); + var core = require('web.core'); + var rpc = require('web.rpc'); + var web_client = require('web.web_client'); + var session = require('web.session'); + var _t = core._t; + var QWeb = core.qweb; + var self = this; + var currency; + var DashBoard = AbstractAction.extend({ + contentTemplate: 'CRMdashboard', + events: { + 'click .my_lead': 'my_lead', + 'click .opportunity': 'opportunity', + 'click .unassigned_leads': 'unassigned_leads', + 'click .exp_revenue': 'exp_revenue', + 'click .revenue_card': 'revenue_card', + 'change #income_expense_values': function(e) { + e.stopPropagation(); + var $target = $(e.target); + var value = $target.val(); + if (value=="this_year"){ + this.onclick_this_year($target.val()); + }else if (value=="this_quarter"){ + this.onclick_this_quarter($target.val()); + }else if (value=="this_month"){ + this.onclick_this_month($target.val()); + }else if (value=="this_week"){ + this.onclick_this_week($target.val()); + } + }, + 'change #total_loosed_crm': function(e) { + e.stopPropagation(); + var $target = $(e.target); + var value = $target.val(); + if (value=="lost_last_12months"){ + this.onclick_lost_last_12months($target.val()); + }else if (value=="lost_last_6months"){ + this.onclick_lost_last_6months($target.val()); + }else if (value=="lost_last_month"){ + this.onclick_lost_last_month($target.val()); + } + }, +// 'change #total_loosed_crm_sub': function(e) { +// e.stopPropagation(); +// var $target = $(e.target); +// var value = $target.val(); +// if (value=="sub_lost_last_12months"){ +// this.onclick_sub_lost_last_12months($target.val()); +// }else if (value=="sub_lost_last_6months"){ +// this.onclick_sub_lost_last_6months($target.val()); +// }else if (value=="sub_lost_last_month"){ +// this.onclick_sub_lost_last_month($target.val()); +// } +// }, + }, + + init: function(parent, context) { + this._super(parent, context); + this.upcoming_events = []; + this.current_lang=[]; +// this.dashboards_templates = ['LoginUser','Managercrm','Admincrm', 'SubDashboard']; + this.dashboards_templates = ['LoginUser','Managercrm','Admincrm']; + this.login_employee = []; + }, + + willStart: function(){ + var self = this; + this.login_employee = {}; + return this._super() + .then(function() { + + var def0 = self._rpc({ + model: 'crm.lead', + method: 'check_user_group' + }).then(function(result) { + if (result == true){ + self.is_manager = true; + } + else{ + self.is_manager = false; + } + }); + + var def1 = self._rpc({ + model: "crm.lead", + method: "get_upcoming_events", + }) + .then(function (res) { + self.upcoming_events = res['event']; + self.current_lang = res['cur_lang']; + }); + + var def2 = self._rpc({ + model: "crm.lead", + method: "get_top_deals", + }) + .then(function (res) { + self.top_deals = res['deals']; + }); + + var def3 = self._rpc({ + model: "crm.lead", + method: "get_monthly_goal", + }) + .then(function (res) { + self.monthly_goals = res['goals']; + }); + + var def4 = self._rpc({ + model: "crm.lead", + method: "get_top_sp_revenue", + }) + .then(function (res) { + self.top_sp_revenue = res['top_revenue']; + }); + + var def5 = self._rpc({ + model: "crm.lead", + method: "get_country_revenue", + }) + .then(function (res) { + self.top_country_revenue = res['country_revenue']; + }); + + var def6 = self._rpc({ + model: "crm.lead", + method: "get_country_count", + }) + .then(function (res) { + self.top_country_count = res['country_count']; + }); + +// var def7 = self._rpc({ +// model: "crm.lead", +// method: "get_lost_reason_count", +// }) +// .then(function (res) { +// self.top_reason_count = res['reason_count']; +// }); + + var def8 = self._rpc({ + model: "crm.lead", + method: "get_ratio_based_country", + }) + .then(function (res) { + self.top_country_wise_ratio = res['country_wise_ratio']; + }); + + var def9 = self._rpc({ + model: "crm.lead", + method: "get_ratio_based_sp", + }) + .then(function (res) { + self.top_salesperson_wise_ratio = res['salesperson_wise_ratio']; + }); + + var def10 = self._rpc({ + model: "crm.lead", + method: "get_ratio_based_sales_team", + }) + .then(function (res) { + self.top_sales_team_wise_ratio = res['sales_team_wise_ratio']; + }); + + var def11 = self._rpc({ + model: "crm.lead", + method: "get_recent_activities", + }) + .then(function (res) { + self.recent_activities = res['activities']; + }); + + var def12 = self._rpc({ + model: "crm.lead", + method: "get_count_unassigned", + }) + .then(function (res) { + self.get_count_unassigned = res['count_unassigned']; + }); + + var def13 = self._rpc({ + model: "crm.lead", + method: "get_top_sp_by_invoice", + }) + .then(function (res) { + self.top_sp_by_invoice = res['sales_person_invoice']; + }); + +// return $.when(def0, def1, def2, def3, def4, def5, def6, def7, def8, def9, def10, def11, def12, def13); + return $.when(def0, def1, def2, def3, def4, def5, def6, def8, def9, def10, def11, def12, def13); + }); + }, + + onclick_this_year: function (ev) { + var self = this; + rpc.query({ + model: 'crm.lead', + method: 'crm_year', + args: [], + }) + .then(function (result) { + $('#leads_this_quarter').hide(); + $('#opp_this_quarter').hide(); + $('#exp_rev_this_quarter').hide(); + $('#rev_this_quarter').hide(); + $('#ratio_this_quarter').hide(); + $('#avg_time_this_quarter').hide(); + $('#total_revenue_this_quarter').hide(); + $('#leads_this_month').hide(); + $('#opp_this_month').hide(); + $('#exp_rev_this_month').hide(); + $('#rev_this_month').hide(); + $('#ratio_this_month').hide(); + $('#avg_time_this_month').hide(); + $('#total_revenue_this_month').hide(); + $('#leads_this_week').hide(); + $('#opp_this_week').hide(); + $('#exp_rev_this_week').hide(); + $('#rev_this_week').hide(); + $('#ratio_this_week').hide(); + $('#avg_time_this_week').hide(); + $('#total_revenue_this_week').hide(); + + $('#leads_this_year').show(); + $('#opp_this_year').show(); + $('#exp_rev_this_year').show(); + $('#rev_this_year').show(); + $('#ratio_this_year').show(); + $('#avg_time_this_year').show(); + $('#total_revenue_this_year').show(); + + $('#leads_this_year').empty(); + $('#opp_this_year').empty(); + $('#exp_rev_this_year').empty(); + $('#rev_this_year').empty(); + $('#ratio_this_year').empty(); + $('#avg_time_this_year').empty(); + $('#total_revenue_this_year').empty(); + + $('#leads_this_year').append('' + result.record + ''); + $('#opp_this_year').append('' + result.record_op + ''); + $('#exp_rev_this_year').append('' + self.monthly_goals[2] + ' ' + result.record_rev_exp + ''); + $('#rev_this_year').append('' + self.monthly_goals[2] + ' ' + result.record_rev + ''); + $('#ratio_this_year').append('' + result.record_ratio + ''); + $('#avg_time_this_year').append('' + result.avg_time + ' sec' + ''); + $('#total_revenue_this_year').append('' + result.opportunity_ratio_value + ''); + }) + }, + + onclick_this_quarter: function (ev) { + var self = this; + rpc.query({ + model: 'crm.lead', + method: 'crm_quarter', + args: [], + }) + .then(function (result) { + $('#leads_this_year').hide(); + $('#opp_this_year').hide(); + $('#exp_rev_this_year').hide(); + $('#rev_this_year').hide(); + $('#ratio_this_year').hide(); + $('#avg_time_this_year').hide(); + $('#total_revenue_this_year').hide(); + $('#leads_this_month').hide(); + $('#opp_this_month').hide(); + $('#exp_rev_this_month').hide(); + $('#rev_this_month').hide(); + $('#ratio_this_month').hide(); + $('#avg_time_this_month').hide(); + $('#total_revenue_this_month').hide(); + $('#leads_this_week').hide(); + $('#opp_this_week').hide(); + $('#exp_rev_this_week').hide(); + $('#rev_this_week').hide(); + $('#ratio_this_week').hide(); + $('#avg_time_this_week').hide(); + $('#total_revenue_this_week').hide(); + + $('#leads_this_quarter').show(); + $('#opp_this_quarter').show(); + $('#exp_rev_this_quarter').show(); + $('#rev_this_quarter').show(); + $('#ratio_this_quarter').show(); + $('#avg_time_this_quarter').show(); + $('#total_revenue_this_quarter').show(); + + $('#leads_this_quarter').empty(); + $('#opp_this_quarter').empty(); + $('#exp_rev_this_quarter').empty(); + $('#rev_this_quarter').empty(); + $('#ratio_this_quarter').empty(); + $('#avg_time_this_quarter').empty(); + $('#total_revenue_this_quarter').empty(); + + $('#leads_this_quarter').append('' + result.record + ''); + $('#opp_this_quarter').append('' + result.record_op + ''); + $('#exp_rev_this_quarter').append('' + self.monthly_goals[2] + ' ' + result.record_rev_exp + ''); + $('#rev_this_quarter').append('' + self.monthly_goals[2] + ' ' + result.record_rev + ''); + $('#ratio_this_quarter').append('' + result.record_ratio + ''); + $('#avg_time_this_quarter').append('' + result.avg_time + ' sec' + ''); + $('#total_revenue_this_quarter').append('' + result.opportunity_ratio_value + ''); + }) + }, + + onclick_this_month: function (ev) { + var self = this; + rpc.query({ + model: 'crm.lead', + method: 'crm_month', + args: [], + }) + .then(function (result) { + $('#leads_this_year').hide(); + $('#opp_this_year').hide(); + $('#exp_rev_this_year').hide(); + $('#rev_this_year').hide(); + $('#ratio_this_year').hide(); + $('#avg_time_this_year').hide(); + $('#total_revenue_this_year').hide(); + $('#leads_this_quarter').hide(); + $('#opp_this_quarter').hide(); + $('#exp_rev_this_quarter').hide(); + $('#rev_this_quarter').hide(); + $('#ratio_this_quarter').hide(); + $('#avg_time_this_quarter').hide(); + $('#total_revenue_this_quarter').hide(); + $('#leads_this_week').hide(); + $('#opp_this_week').hide(); + $('#exp_rev_this_week').hide(); + $('#rev_this_week').hide(); + $('#ratio_this_week').hide(); + $('#avg_time_this_week').hide(); + $('#total_revenue_this_week').hide(); + + $('#leads_this_month').show(); + $('#opp_this_month').show(); + $('#exp_rev_this_month').show(); + $('#rev_this_month').show(); + $('#ratio_this_month').show(); + $('#avg_time_this_month').show(); + $('#total_revenue_this_month').show(); + + $('#leads_this_month').empty(); + $('#opp_this_month').empty(); + $('#exp_rev_this_month').empty(); + $('#rev_this_month').empty(); + $('#ratio_this_month').empty(); + $('#avg_time_this_month').empty(); + $('#total_revenue_this_month').empty(); + + $('#leads_this_month').append('' + result.record + ''); + $('#opp_this_month').append('' + result.record_op + ''); + $('#exp_rev_this_month').append('' + self.monthly_goals[2] + ' ' + result.record_rev_exp + ''); + $('#rev_this_month').append('' + self.monthly_goals[2] + ' ' + result.record_rev + ''); + $('#ratio_this_month').append('' + result.record_ratio + ''); + $('#avg_time_this_month').append('' + result.avg_time + ' sec' + ''); + $('#total_revenue_this_month').append('' + result.opportunity_ratio_value + ''); + }) + }, + + onclick_this_week: function (ev) { + var self = this; + rpc.query({ + model: 'crm.lead', + method: 'crm_week', + args: [], + }) + .then(function (result) { + $('#leads_this_year').hide(); + $('#opp_this_year').hide(); + $('#exp_rev_this_year').hide(); + $('#rev_this_year').hide(); + $('#ratio_this_year').hide(); + $('#avg_time_this_year').hide(); + $('#total_revenue_this_year').hide(); + $('#leads_this_quarter').hide(); + $('#opp_this_quarter').hide(); + $('#exp_rev_this_quarter').hide(); + $('#rev_this_quarter').hide(); + $('#ratio_this_quarter').hide(); + $('#avg_time_this_quarter').hide(); + $('#total_revenue_this_quarter').hide(); + $('#leads_this_month').hide(); + $('#opp_this_month').hide(); + $('#exp_rev_this_month').hide(); + $('#rev_this_month').hide(); + $('#ratio_this_month').hide(); + $('#avg_time_this_month').hide(); + $('#total_revenue_this_month').hide(); + + $('#leads_this_week').show(); + $('#opp_this_week').show(); + $('#exp_rev_this_week').show(); + $('#rev_this_week').show(); + $('#ratio_this_week').show(); + $('#avg_time_this_week').show(); + $('#total_revenue_this_week').show(); + + $('#leads_this_week').empty(); + $('#opp_this_week').empty(); + $('#exp_rev_this_week').empty(); + $('#rev_this_week').empty(); + $('#ratio_this_week').empty(); + $('#avg_time_this_week').empty(); + $('#total_revenue_this_week').empty(); + + $('#leads_this_week').append('' + result.record + ''); + $('#opp_this_week').append('' + result.record_op + ''); + $('#exp_rev_this_week').append('' + self.monthly_goals[2] + ' ' + result.record_rev_exp + ''); + $('#rev_this_week').append('' + self.monthly_goals[2] + ' ' + result.record_rev + ''); + $('#ratio_this_week').append('' + result.record_ratio + ''); + $('#avg_time_this_week').append('' + result.avg_time + ' sec' + ''); + $('#total_revenue_this_week').append('' + result.opportunity_ratio_value + ''); + }) + }, + + renderElement: function (ev) { + var self = this; + $.when(this._super()) + .then(function (ev) { + rpc.query({ + model: "crm.lead", + method: "lead_details_user", + args: [], + }) + .then(function (result) { + $('#leads_this_month').append('' + result.record + ''); + $('#opp_this_month').append('' + result.record_op + ''); + $('#exp_rev_this_month').append('' + self.monthly_goals[2] + ' ' + result.record_rev_exp + ''); + $('#rev_this_month').append('' + self.monthly_goals[2] + ' ' + result.record_rev + ''); + $('#ratio_this_month').append('' + result.record_ratio + ''); + $('#avg_time_this_month').append('' + result.avg_time + ' sec' + ''); + $('#total_revenue_this_month').append('' + result.opportunity_ratio_value + ''); + $('#target').append('' + result.target +''); + $('#ytd_target').append('' + result.ytd_target +''); + $('#difference').append('' + result.difference +''); + $('#won').append('' + result.won +''); + }) + }); + }, + + //lead + my_lead: function(e) { + var self = this; + e.stopPropagation(); + e.preventDefault(); + var options = { + on_reverse_breadcrumb: this.on_reverse_breadcrumb, + }; + this.do_action({ + name: _t("My Leads"), + type: 'ir.actions.act_window', + res_model: 'crm.lead', + view_mode: 'tree,form,calendar', + views: [[false, 'list'],[false, 'form']], + domain: [['user_id', '=', session.uid]], + target: 'current', + }, options) + }, + + //opportunity + opportunity: function(e) { + var self = this; + e.stopPropagation(); + e.preventDefault(); + var options = { + on_reverse_breadcrumb: this.on_reverse_breadcrumb, + }; + this.do_action({ + name: _t("Opportunity"), + type: 'ir.actions.act_window', + res_model: 'crm.lead', + view_mode: 'tree,form,calendar', + views: [[false, 'list'],[false, 'form']], + domain: [['user_id', '=', session.uid], ['type','=', 'opportunity']], + target: 'current', + }, options) + }, + + //expected_revenue + exp_revenue: function(e) { + var self = this; + e.stopPropagation(); + e.preventDefault(); + var options = { + on_reverse_breadcrumb: this.on_reverse_breadcrumb, + }; + this.do_action({ + name: _t("Expected Revenue"), + type: 'ir.actions.act_window', + res_model: 'crm.lead', + view_mode: 'tree,form,calendar', + views: [[false, 'list'],[false, 'form']], + domain: [['user_id','=', session.uid], ['type','=', 'opportunity'], ['active','=', true]], + target: 'current', + }, options) + }, + + //revenue + revenue_card: function(e) { + var self = this; + e.stopPropagation(); + e.preventDefault(); + var options = { + on_reverse_breadcrumb: this.on_reverse_breadcrumb, + }; + this.do_action({ + name: _t("Revenue"), + type: 'ir.actions.act_window', + res_model: 'crm.lead', + view_mode: 'tree,form,calendar', + views: [[false, 'list'],[false, 'form']], + domain: [['user_id','=', session.uid], ['type','=', 'opportunity'], ['stage_id','=', 4]], + target: 'current', + }, options) + }, + + //unassigned_leads + unassigned_leads: function(e) { + var self = this; + e.stopPropagation(); + e.preventDefault(); + var options = { + on_reverse_breadcrumb: this.on_reverse_breadcrumb, + }; + this.do_action({ + name: _t("Unassigned Leads"), + type: 'ir.actions.act_window', + res_model: 'crm.lead', + view_mode: 'tree,form,calendar', + views: [[false, 'list'],[false, 'form']], + domain: [['user_id','=', false],['type', '=', 'lead']], + context: {'group_by': 'team_id'}, + target: 'current', + }, options) + }, + + start: function() { + var self = this; + this.set("title", 'Dashboard'); + return this._super().then(function() { + self.update_cp(); + self.render_dashboards(); + self.render_graphs(); + self.$el.parent().addClass('oe_background_grey'); + }); + }, + + render_graphs: function(){ + var self = this; + self.render_sales_activity_graph(); + self.render_leads_month_graph(); + self.funnel_chart(); + self.render_annual_chart_graph(); + self.render_campaign_leads_graph(); + self.render_medium_leads_graph(); + self.render_source_leads_graph(); + self.onclick_lost_last_12months(); +// self.onclick_sub_lost_last_12months(); + self.render_lost_leads_graph(); + self.render_lost_leads_by_stage_graph(); + self.render_revenue_count_pie(); + }, + + funnel_chart: function () { + rpc.query({ + model: "crm.lead", + method: "get_lead_stage_data", + }).then(function (callbacks) { + Highcharts.chart("container", { + chart: { + type: "funnel", + }, + title: false, + credits: { + enabled: false + }, + plotOptions: { + series: { + dataLabels: { + enabled: true, + softConnector: true + }, + center: ['45%', '50%'], + neckWidth: '40%', + neckHeight: '35%', + width: '90%', + height: '80%' + } + }, + series: [ { + name: "Number Of Leads", + data: callbacks, + }], + }); + }); + }, + + render_lost_leads_graph:function(){ + var self = this; + var ctx = self.$(".lost_leads_graph"); + rpc.query({ + model: "crm.lead", + method: "get_lost_lead_by_reason_pie", + }).then(function (arrays) { + var data = { + labels : arrays[1], + datasets: [{ + label: "", + data: arrays[0], + backgroundColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + borderWidth: 1 + },] + }; + + //options + var options = { + responsive: true, + title: false, + legend: { + display: true, + position: "bottom", + labels: { + fontColor: "#333", + fontSize: 16 + } + }, + scales: { + yAxes: [{ + gridLines: { + color: "rgba(0, 0, 0, 0)", + display: false, + }, + ticks: { + min: 0, + display: false, + } + }] + } + }; + + //create Chart class object + var chart = new Chart(ctx, { + type: "doughnut", + data: data, + options: options + }); + }); + }, + + render_lost_leads_by_stage_graph:function(){ + var self = this + var ctx = self.$(".lost_leads_by_stage_graph"); + rpc.query({ + model: "crm.lead", + method: "get_lost_lead_by_stage_pie", + }).then(function (arrays) { + var data = { + labels : arrays[1], + datasets: [{ + label: "", + data: arrays[0], + backgroundColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + borderWidth: 1 + },] + }; + + //options + var options = { + responsive: true, + title: false, + legend: { + display: true, + position: "bottom", + labels: { + fontColor: "#333", + fontSize: 16 + } + }, + scales: { + yAxes: [{ + gridLines: { + color: "rgba(0, 0, 0, 0)", + display: false, + }, + ticks: { + min: 0, + display: false, + } + }] + } + }; + + //create Chart class object + var chart = new Chart(ctx, { + type: "doughnut", + data: data, + options: options + }); + }); + }, + + render_sales_activity_graph:function(){ + var self = this + var ctx = self.$(".sales_activity"); + rpc.query({ + model: "crm.lead", + method: "get_the_sales_activity", + }).then(function (arrays) { + var data = { + labels : arrays[1], + datasets: [{ + label: "", + data: arrays[0], + backgroundColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + 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, + } + }] + } + }; + + //create Chart class object + var chart = new Chart(ctx, { + type: "doughnut", + data: data, + options: options + }); + }); + }, + + render_leads_month_graph:function(){ + var self = this + var ctx = self.$(".lead_month"); + rpc.query({ + model: "crm.lead", + method: "get_lead_month_pie", + }).then(function (arrays) { + var data = { + labels : arrays[1], + datasets: [{ + label: "", + data: arrays[0], + backgroundColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + 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, + } + }] + } + }; + + //create Chart class object + var chart = new Chart(ctx, { + type: "doughnut", + data: data, + options: options + }); + }); + }, + + render_revenue_count_pie:function(){ + var self = this; + var ctx = self.$(".revenue_count_pie_canvas"); + rpc.query({ + model: "crm.lead", + method: "revenue_count_pie", + }).then(function (arrays) { + var data = { + labels : arrays[1], + datasets: [{ + label: "", + data: arrays[0], + backgroundColor: [ + "#003f5c", + "#ff7c43", + "#f95d6a" + ], + borderColor: [ + "#003f5c", + "#ff7c43", + "#f95d6a" + ], + borderWidth: 1 + },] + }; + + //options + var options = { + responsive: true, + title: false, + legend: { + display: true, + position: "bottom", + labels: { + fontColor: "#333", + fontSize: 16 + } + }, + scales: { + yAxes: [{ + gridLines: { + color: "rgba(0, 0, 0, 0)", + display: false, + }, + ticks: { + min: 0, + display: false, + } + }] + } + }; + + //create Chart class object + var chart = new Chart(ctx, { + type: "doughnut", + data: data, + options: options + }); + }); + }, + + render_annual_chart_graph:function(){ + var self = this + var ctx = self.$(".annual_target"); + rpc.query({ + model: "crm.lead", + method: "get_the_annual_target", + }).then(function (arrays) { + var data = { + labels : arrays[1], + datasets: [{ + label: "", + data: arrays[0], + backgroundColor: [ + "#003f5c", + "#f95d6a", + "#ff7c43", + "#6d5c16" + ], + borderColor: [ + "#003f5c", + "#f95d6a", + "#ff7c43", + "#6d5c16" + ], + borderWidth: 1 + },] + }; + + //options + var options = { + responsive: true, + title: false, + scales: { + yAxes: [{ + ticks: { + min: 0 + } + }] + } + }; + + //create Chart class object + var chart = new Chart(ctx, { + type: "bar", + data: data, + options: { + responsive:true, + maintainAspectRatio: false, + legend: { + display: false //This will do the task + }, + } + }); + }); + }, + + + render_campaign_leads_graph:function(){ + var self = this + var ctx = self.$(".campaign_source"); + rpc.query({ + model: "crm.lead", + method: "get_the_campaign_pie", + }).then(function (arrays) { + var data = { + labels : arrays[1], + datasets: [{ + label: "", + data: arrays[0], + backgroundColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + borderWidth: 1 + },] + }; + + //options + var options = { + responsive: true, + title: false, + legend: { + display: true, + position: "bottom", + labels: { + fontColor: "#333", + fontSize: 14 + } + }, + scales: { + yAxes: [{ + gridLines: { + color: "rgba(0, 0, 0, 0)", + display: false, + }, + ticks: { + min: 0, + display: false, + } + }] + } + }; + + //create Chart class object + var chart = new Chart(ctx, { + type: "doughnut", + data: data, + options: options + }); + }); + }, + + render_source_leads_graph:function(){ + var self = this + var ctx = self.$(".source_lead"); + rpc.query({ + model: "crm.lead", + method: "get_the_source_pie", + }).then(function (arrays) { + var data = { + labels : arrays[1], + datasets: [{ + label: "", + data: arrays[0], + backgroundColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + borderWidth: 1 + },] + }; + + //options + var options = { + responsive: true, + title: false, + legend: { + display: true, + position: "right", + labels: { + fontColor: "#333", + fontSize: 14 + } + }, + scales: { + yAxes: [{ + gridLines: { + color: "rgba(0, 0, 0, 0)", + display: false, + }, + ticks: { + min: 0, + display: false, + } + }] + } + }; + + //create Chart class object + var chart = new Chart(ctx, { + type: "doughnut", + data: data, + options: options + }); + }); + }, + + render_medium_leads_graph:function(){ + var self = this + var ctx = self.$(".medium_leads"); + rpc.query({ + model: "crm.lead", + method: "get_the_medium_pie", + }).then(function (arrays) { + var data = { + labels : arrays[1], + datasets: [{ + label: "", + data: arrays[0], + backgroundColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + borderColor: [ + "#003f5c", + "#2f4b7c", + "#f95d6a", + "#665191", + "#d45087", + "#ff7c43", + "#ffa600", + "#a05195", + "#6d5c16" + ], + borderWidth: 1 + },] + }; + + //options + var options = { + responsive: true, + title: false, + legend: { + display: true, + position: "right", + labels: { + fontColor: "#333", + fontSize: 14 + } + }, + scales: { + yAxes: [{ + gridLines: { + color: "rgba(0, 0, 0, 0)", + display: false, + }, + ticks: { + min: 0, + display: false, + } + }] + } + }; + + //create Chart class object + var chart = new Chart(ctx, { + type: "doughnut", + data: data, + options: options + }); + }); + }, + + onclick_lost_last_12months: function(ev) { + var self = this; + if( self.is_manager == true){ + self.initial_render = true; + rpc.query({ + model: "crm.lead", + method: "get_total_lost_crm", + args: ['12'] + }).then(function(result){ + var ctx = document.getElementById("canvas").getContext('2d'); + // Define the data + var lost_reason = result.month // Add data values to array + var count = result.count; + var myChart = new Chart(ctx, { + type: 'bar', + data: { + labels: lost_reason,//x axis + datasets: [{ + label: 'Count', // Name the series + data: count, // Specify the data values array + backgroundColor: '#66aecf', + borderColor: '#66aecf', + 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 + } + }); + }); + }; + }, + + onclick_lost_last_6months: function(ev) { + var self = this; + self.initial_render = true; + rpc.query({ + model: "crm.lead", + method: "get_total_lost_crm", + args: ['6'] + }).then(function(result){ + var ctx = document.getElementById("canvas").getContext('2d'); + // Define the data + var lost_reason = result.month // Add data values to array + var count = result.count; + var myChart = new Chart(ctx, { + type: 'bar', + data: { + labels: lost_reason,//x axis + datasets: [{ + label: 'Count', // Name the series + data: count, // Specify the data values array + backgroundColor: '#66aecf', + borderColor: '#66aecf', + 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 + } + }); + }); + }, + + onclick_lost_last_month: function(ev) { + var self = this; + self.initial_render = true; + rpc.query({ + model: "crm.lead", + method: "get_total_lost_crm", + args: ['1'] + }).then(function(result){ + var ctx = document.getElementById("canvas").getContext('2d'); + // Define the data + var lost_reason = result.month // Add data values to array + var count = result.count; + var myChart = new Chart(ctx, { + type: 'bar', + data: { + labels: lost_reason,//x axis + datasets: [{ + label: 'Count', // Name the series + data: count, // Specify the data values array + backgroundColor: '#66aecf', + borderColor: '#66aecf', + 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 + } + }); + }); + }, + +// onclick_sub_lost_last_12months: function(ev) { +// var self = this; +// if( self.is_manager == true){ +// self.initial_render = true; +// rpc.query({ +// model: "crm.lead", +// method: "get_total_lost_crm", +// args: ['12'] +// }).then(function(result){ +// var ctx = document.getElementById('canvas_graph').getContext('2d'); +// // Define the data +// var lost_reason = result.month; // Add data values to array +// var count = result.count; +// var myChart = new Chart(ctx, { +// type: 'bar', +// data: { +// labels: lost_reason,//x axis +// datasets: [{ +// label: 'Count', // Name the series +// data: count, // Specify the data values array +// backgroundColor: '#66aecf', +// borderColor: '#66aecf', +// 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 +// } +// }); +// }); +// }; +// }, +// +// onclick_sub_lost_last_6months: function(ev) { +// var self = this; +// self.initial_render = true; +// rpc.query({ +// model: "crm.lead", +// method: "get_total_lost_crm", +// args: ['6'] +// }).then(function(result){ +// var ctx = document.getElementById("canvas_graph").getContext('2d'); +// // Define the data +// var lost_reason = result.month // Add data values to array +// var count = result.count; +// var myChart = new Chart(ctx, { +// type: 'bar', +// data: { +// labels: lost_reason,//x axis +// datasets: [{ +// label: 'Count', // Name the series +// data: count, // Specify the data values array +// backgroundColor: '#66aecf', +// borderColor: '#66aecf', +// 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 +// } +// }); +// }); +// }, +// +// onclick_sub_lost_last_month: function(ev) { +// var self = this; +// self.initial_render = true; +// rpc.query({ +// model: "crm.lead", +// method: "get_total_lost_crm", +// args: ['1'] +// }).then(function(result){ +// var ctx = document.getElementById("canvas_graph").getContext('2d'); +// // Define the data +// var lost_reason = result.month // Add data values to array +// var count = result.count; +// var myChart = new Chart(ctx, { +// type: 'bar', +// data: { +// labels: lost_reason,//x axis +// datasets: [{ +// label: 'Count', // Name the series +// data: count, // Specify the data values array +// backgroundColor: '#66aecf', +// borderColor: '#66aecf', +// 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 +// } +// }); +// }); +// }, + + fetch_data: function() { + var self = this; + + var def0 = self._rpc({ + model: 'crm.lead', + method: 'check_user_group' + }).then(function(result) { + if (result == true){ + self.is_manager = true; + } + else{ + self.is_manager = false; + } + }); + + var def1 = self._rpc({ + model: "crm.lead", + method: "get_upcoming_events", + }) + .then(function (res) { + self.upcoming_events = res['event']; + }); + + var def2 = self._rpc({ + model: "crm.lead", + method: "get_top_deals", + }) + .then(function (res) { + self.top_deals = res['deals']; + }); + + var def3 = self._rpc({ + model: "crm.lead", + method: "get_monthly_goal", + }) + .then(function (res) { + self.monthly_goals = res['goals']; + }); + + var def4 = self._rpc({ + model: "crm.lead", + method: "get_top_sp_revenue", + }) + .then(function (res) { + self.top_sp_revenue = res['top_revenue']; + }); + + var def5 = self._rpc({ + model: "crm.lead", + method: "get_country_revenue", + }) + .then(function (res) { + self.top_country_revenue = res['country_revenue']; + }); + + var def6 = self._rpc({ + model: "crm.lead", + method: "get_country_count", + }) + .then(function (res) { + self.top_country_count = res['country_count']; + }); + +// var def7 = self._rpc({ +// model: "crm.lead", +// method: "get_lost_reason_count", +// }) +// .then(function (res) { +// self.top_reason_count = res['reason_count']; +// }); + + var def8 = self._rpc({ + model: "crm.lead", + method: "get_ratio_based_country", + }) + .then(function (res) { + self.top_country_wise_ratio = res['country_wise_ratio']; + }); + + var def9 = self._rpc({ + model: "crm.lead", + method: "get_ratio_based_sp", + }) + .then(function (res) { + self.top_salesperson_wise_ratio = res['salesperson_wise_ratio']; + }); + + var def10 = self._rpc({ + model: "crm.lead", + method: "get_ratio_based_sales_team", + }) + .then(function (res) { + self.top_sales_team_wise_ratio = res['sales_team_wise_ratio']; + }); + + var def11 = self._rpc({ + model: "crm.lead", + method: "get_recent_activities", + }) + .then(function (res) { + self.recent_activities = res['activities']; + }); + + var def12 = self._rpc({ + model: "crm.lead", + method: "get_count_unassigned", + }) + .then(function (res) { + self.get_count_unassigned = res['count_unassigned']; + }); + + var def13 = self._rpc({ + model: "crm.lead", + method: "get_top_sp_by_invoice", + }) + .then(function (res) { + self.top_sp_by_invoice = res['sales_person_invoice']; + }); + +// return $.when(def0, def1, def2, def3, def4, def5, def6, def7, def8, def9, def10, def11, def12, def13); + return $.when(def0, def1, def2, def3, def4, def5, def6, def8, def9, def10, def11, def12, def13); + }, + + render_dashboards: function() { + var self = this; + if (this.login_employee){ + var templates = [] + if( self.is_manager == true){ +// templates = ['LoginUser', 'Managercrm', 'Admincrm', 'SubDashboard']; + templates = ['LoginUser', 'Managercrm', 'Admincrm']; + } + else{ + templates = ['LoginUser','Managercrm']; + } + _.each(templates, function(template) { + self.$('.o_hr_dashboard').append(QWeb.render(template, {widget: self})); + }); + } + else{ + self.$('.o_hr_dashboard').append(QWeb.render('EmployeeWarning', {widget: self})); + } + }, + + on_reverse_breadcrumb: function() { + var self = this; + web_client.do_push_state({}); + this.update_cp(); + this.fetch_data().then(function() { + self.$('.o_hr_dashboard').reload(); + self.render_dashboards(); + }); + }, + + update_cp: function() { + var self = this; + }, + }); + + core.action_registry.add('crm_dashboard', DashBoard); + return DashBoard; +}); \ No newline at end of file diff --git a/crm_dashboard/static/src/xml/dashboard_view.xml b/crm_dashboard/static/src/xml/dashboard_view.xml new file mode 100644 index 000000000..a62863a35 --- /dev/null +++ b/crm_dashboard/static/src/xml/dashboard_view.xml @@ -0,0 +1,558 @@ + + + +
+
+
+ + +
+
+
+
+
+

CRM Dashboard

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

+ +
+
+
+
+ +

+

My Leads

+
+
+
+ +
+
+
+ +
+
+

+ +
+
+
+
+ +

+

My Opportunities

+
+
+
+ +
+
+
+ +
+
+

+ +
+
+
+
+ +

+

Expected Revenue

+
+
+
+ +
+
+
+ +
+
+

+ +
+
+
+
+ +

+

Revenue

+
+
+
+ +
+
+
+ +
+
+

+ +
+
+
+
+ +

+

Win Ratio

+
+
+
+ +
+
+
+ +
+
+

+ +
+
+
+
+ +

+

Average Closing Time

+
+
+
+ +
+
+
+ +
+
+

+ +
+
+
+
+ +

+

Opportunity Win Loss Ratio

+
+
+
+ +
+
+
+ +
+
+

+ + + +

+

Unassigned Leads Count

+
+
+
+
+ +
+
+
+

Funnel Chart

+
+
+
+
+
+
+
+
+

Year to Date

+
+
+ +
+
+
Annual Target :&nbsp
+
YtD Target :&nbsp
+
Achieved Won :&nbsp
+
Difference :&nbsp
+
+
+
+ +
+
+

Leads by Month

+
+
+ +
+
+
+

CRM Activity

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

Upcoming Activities

+
+
+
+
+ +
+
+ +
+
+
+
    +
  • + + + Activity: + + + + +
  • +
  • + Name: + + + +
  • +
  • Summary: + + + +
  • +
+
+
+
+
+
+
+
+
+
+ +
+
+

Total Revenue by Salesperson

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

Top Deals

+
+
+
+ +
+
+ +
+
+

.

+
+
    +
  • + Sales Person: ,&nbsp + Team: +
  • +
+
+
+
+
+
+
+
+
+ +
+
+

Monthly Goal

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

Leads group by Campaign

+
+
+ +
+
+
+ +
+
+

Leads group by Medium

+
+
+ +
+
+
+

Leads group by Source

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

Top Salesperson Revenue

+
+ + + + + + + + + + + + + + + +
OpportunityRevenue
+
+
+ +
+
+

Top Country Wise Revenue

+
+ + + + + + + + + + + + + + + +
CountryRevenue
+
+
+ +
+
+

Top Country Wise Count

+
+ + + + + + + + + + + + + + + +
CountryCount
+
+
+
+ +
+
+
+

Recent Activities

+
+
+
+
+ +
+
+ +
+
+
+
    +
  • + + + Activity: + + + + +
  • +
  • Name: + + + +
  • +
  • Summary: + + + +
  • +
  • + Sales Rep.: +
  • +
+
+
+
+
+
+
+
+
+
+ +
+
+

Lost Opportunity/Lead Graph

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

Top Sales Person by Invoice

+
+
+
+ +
+
+ +
+
+

&nbsp

+
+
    +
  • + +

  • +
+
+
+
+
+
+
+
+
+
+
+
+ diff --git a/crm_dashboard/static/src/xml/sub_dashboard.xml b/crm_dashboard/static/src/xml/sub_dashboard.xml new file mode 100644 index 000000000..bd0a92b43 --- /dev/null +++ b/crm_dashboard/static/src/xml/sub_dashboard.xml @@ -0,0 +1,150 @@ + + + + + + \ No newline at end of file diff --git a/crm_dashboard/views/dashboard_view.xml b/crm_dashboard/views/dashboard_view.xml new file mode 100644 index 000000000..b80cc5e91 --- /dev/null +++ b/crm_dashboard/views/dashboard_view.xml @@ -0,0 +1,61 @@ + + + + crm.manager.select + crm.lead + + + + + + + + + + sales.team.inherit.view + crm.team + + + + + + + + + + res.users.form.inherit + res.users + + + + + + + + + + + + CRM + crm_dashboard + + + + Campaign Win Lose Smart Button + utm.campaign + + +
+ +
+
+
+ + + +
+
\ No newline at end of file diff --git a/crm_kit/README.rst b/crm_kit/README.rst new file mode 100755 index 000000000..89025232d --- /dev/null +++ b/crm_kit/README.rst @@ -0,0 +1,39 @@ +CRM Kit +======= +* CRM Kit module for Odoo 16. + +Installation +============ + - www.odoo.com/documentation/15.0/setup/install.html + - Install our custom addon + +License +------- +General Public License, Version 3 (LGPL v3). +(https://www.odoo.com/documentation/user/15.0/legal/licenses/licenses.html) + +Company +------- +* 'Cybrosys Techno Solutions '__ + +Credits +------- +* 'Cybrosys Techno Solutions '__ + +Contacts +-------- +* Mail Contact : odoo@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 +========== +This module is maintained by Cybrosys Technologies. + +For support and more information, please visit https://www.cybrosys.com + +Further information +=================== +HTML Description: ``__ diff --git a/crm_kit/__init__.py b/crm_kit/__init__.py new file mode 100644 index 000000000..8909ff398 --- /dev/null +++ b/crm_kit/__init__.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2021-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 +from . import wizard +from . import controllers diff --git a/crm_kit/__manifest__.py b/crm_kit/__manifest__.py new file mode 100644 index 000000000..315cea7bc --- /dev/null +++ b/crm_kit/__manifest__.py @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2021-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": "Odoo15 CRM Kit", + 'description': """Complete CRM Kit for odoo15, CRM, CRM dashboard, crm commission, commission plan, crm features""", + 'summary': """Complete CRM Kit for odoo15""", + "category": 'Sales', + "version": '16.0.1.0.0', + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'website': "https://www.cybrosys.com", + "depends": ['base', 'sale_management', 'crm', 'crm_dashboard'], + "data": [ + 'security/ir.model.access.csv', + 'views/commission.xml', + 'wizard/commission_report.xml', + ], + 'assets': { + 'web.assets_backend': [ + 'crm_kit/static/src/js/action_manager.js', + ], + }, + 'images': [ + 'static/description/banner.png', + ], + 'license': 'LGPL-3', + 'installable': True, + 'application': False, + 'auto_install': False, +} diff --git a/crm_kit/controllers/__init__.py b/crm_kit/controllers/__init__.py new file mode 100644 index 000000000..1178cb52e --- /dev/null +++ b/crm_kit/controllers/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2021-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 main diff --git a/crm_kit/controllers/main.py b/crm_kit/controllers/main.py new file mode 100644 index 000000000..77f04451f --- /dev/null +++ b/crm_kit/controllers/main.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2020-TODAY Cybrosys Technologies() +# Author: Midilaj () +# +# 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 json +from odoo import http +from odoo.http import content_disposition, request +from odoo.tools import html_escape + + +class XLSXReportController(http.Controller): + + @http.route('/xlsx_reports', type='http', auth='user', methods=['POST'], csrf=False) + def get_report_xlsx(self, model, options, output_format, report_name, **kw): + uid = request.session.uid + report_obj = request.env[model].with_user(uid) + options = json.loads(options) + token = 'dummy-because-api-expects-one' + try: + if output_format == 'xlsx': + response = request.make_response( + None, + headers=[ + ('Content-Type', 'application/vnd.ms-excel'), + ('Content-Disposition', content_disposition(report_name + '.xlsx')) + ] + ) + report_obj.get_xlsx_report(options, response) + response.set_cookie('fileToken', token) + return response + except Exception as e: + se = http.serialize_exception(e) + error = { + 'code': 200, + 'message': 'Odoo Server Error', + 'data': se + } + return request.make_response(html_escape(json.dumps(error))) diff --git a/crm_kit/doc/RELEASE_NOTES.md b/crm_kit/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..37cd395d5 --- /dev/null +++ b/crm_kit/doc/RELEASE_NOTES.md @@ -0,0 +1,6 @@ +## Module + +#### 30.09.2022 +#### Version 16.0.1.0.0 +#### ADD +- Initial commit for CRM Kit Module diff --git a/crm_kit/models/__init__.py b/crm_kit/models/__init__.py new file mode 100644 index 000000000..67d5b1c6f --- /dev/null +++ b/crm_kit/models/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2021-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 commission diff --git a/crm_kit/models/commission.py b/crm_kit/models/commission.py new file mode 100644 index 000000000..53c65ca49 --- /dev/null +++ b/crm_kit/models/commission.py @@ -0,0 +1,126 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2021-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 odoo import exceptions +from odoo import fields, models, api, _ + + +class CommissionPlan(models.Model): + _name = 'crm.commission' + _description = 'Commission Plan' + _rec_name = "name" + _inherit = ['mail.thread', 'mail.activity.mixin'] + + name = fields.Char('Name', required=True) + active = fields.Boolean('Active', default=True) + date_from = fields.Date(string="From Date", required=True) + date_to = fields.Date(string="To Date", required=True) + type = fields.Selection( + [('product', 'Product wise'), + ('revenue', 'Revenue wise')], string="Type", + default="product") + team_id = fields.Many2one('crm.team', string='Sales Team') + user_id = fields.Many2one('res.users', string='Salesperson') + product_comm_ids = fields.One2many('commission.product', 'commission_id', + string="Product Wise") + straight_commission_rate = fields.Float(string='Commission rate (%)') + revenue_grd_comm_ids = fields.One2many( + 'commission.graduated', + 'commission_id', + string="Revenue Graduated Wise") + + revenue_type = fields.Selection( + [('straight', 'Straight Commission'), + ('graduated', 'Graduated Commission')], + string="Revenue Type") + + @api.constrains("date_from", "date_to") + def _check_date(self): + for rec in self: + if rec.date_to < rec.date_from: + raise exceptions.ValidationError( + _("The From date cannot be earlier than To date.") + ) + + @api.onchange('type') + def onchange_type(self): + if self.type == 'revenue': + self.product_comm_ids = [(5, 0, 0)] + elif self.type == 'product': + self.revenue_type = False + self.straight_commission_rate = False + self.revenue_grd_comm_ids = [(5, 0, 0)] + + +class CommissionProduct(models.Model): + _name = 'commission.product' + _description = 'Commission Product Wise' + + user_id = fields.Many2one('res.users') + category_id = fields.Many2one('product.category', string='Product Category') + product_id = fields.Many2one('product.product', string='Product', + domain="[('categ_id', '=', category_id)]") + percentage = fields.Float(string='Rate in Percentage (%)') + amount = fields.Monetary('Maximum Commission Amount', default=0.0) + currency_id = fields.Many2one("res.currency", string="Currency", + default=lambda self: + self.env.user.company_id.currency_id.id) + commission_id = fields.Many2one("crm.commission") + + +class CommissionRevenueGraduated(models.Model): + _name = 'commission.graduated' + _description = 'Commission Revenue Graduated Wise' + + graduated_commission_rate = fields.Float(string='Commission rate (%)') + amount_from = fields.Float(string="From Amount") + amount_to = fields.Float(string="To Amount") + commission_id = fields.Many2one("crm.commission") + sequence = fields.Integer(string='Sequence', compute='_compute_sequence', + store=True) + + @api.depends('commission_id') + def _compute_sequence(self): + number = 1 + seq = self.mapped('commission_id') + for rule in seq.revenue_grd_comm_ids: + rule.sequence = number + number += 1 + + @api.constrains("amount_from", "amount_to") + def _check_amounts(self): + for rec in self: + if rec.amount_to < rec.amount_from: + raise exceptions.ValidationError( + _("The From Amount limit cannot be greater than To Amount.") + ) + + +class CrmTeam(models.Model): + _inherit = 'crm.team' + + commission_id = fields.Many2one('crm.commission', string='Commission Plan') + + +class CrmSalespersons(models.Model): + _inherit = 'res.users' + + commission_id = fields.Many2one('crm.commission', string='Commission Plan') diff --git a/crm_kit/security/ir.model.access.csv b/crm_kit/security/ir.model.access.csv new file mode 100644 index 000000000..77920af24 --- /dev/null +++ b/crm_kit/security/ir.model.access.csv @@ -0,0 +1,5 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_commission_plan,crm.commission,model_crm_commission,base.group_user,1,1,1,1 +access_commission_product,commission.product,model_commission_product,base.group_user,1,1,1,1 +access_commission_wizard,commission.wizard,model_commission_wizard,base.group_user,1,1,1,1 +access_commission_graduated,commission.graduated,model_commission_graduated,base.group_user,1,1,1,1 \ No newline at end of file diff --git a/crm_kit/static/description/assets/icons/check.png b/crm_kit/static/description/assets/icons/check.png new file mode 100644 index 000000000..c8e85f51d Binary files /dev/null and b/crm_kit/static/description/assets/icons/check.png differ diff --git a/crm_kit/static/description/assets/icons/chevron.png b/crm_kit/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..2089293d6 Binary files /dev/null and b/crm_kit/static/description/assets/icons/chevron.png differ diff --git a/crm_kit/static/description/assets/icons/cogs.png b/crm_kit/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/crm_kit/static/description/assets/icons/cogs.png differ diff --git a/crm_kit/static/description/assets/icons/consultation.png b/crm_kit/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/crm_kit/static/description/assets/icons/consultation.png differ diff --git a/crm_kit/static/description/assets/icons/ecom-black.png b/crm_kit/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/crm_kit/static/description/assets/icons/ecom-black.png differ diff --git a/crm_kit/static/description/assets/icons/education-black.png b/crm_kit/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/crm_kit/static/description/assets/icons/education-black.png differ diff --git a/crm_kit/static/description/assets/icons/hotel-black.png b/crm_kit/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/crm_kit/static/description/assets/icons/hotel-black.png differ diff --git a/crm_kit/static/description/assets/icons/icon.png b/crm_kit/static/description/assets/icons/icon.png new file mode 100644 index 000000000..61b0eb171 Binary files /dev/null and b/crm_kit/static/description/assets/icons/icon.png differ diff --git a/crm_kit/static/description/assets/icons/license.png b/crm_kit/static/description/assets/icons/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/crm_kit/static/description/assets/icons/license.png differ diff --git a/crm_kit/static/description/assets/icons/lifebuoy.png b/crm_kit/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/crm_kit/static/description/assets/icons/lifebuoy.png differ diff --git a/crm_kit/static/description/assets/icons/logo.png b/crm_kit/static/description/assets/icons/logo.png new file mode 100644 index 000000000..478462d3e Binary files /dev/null and b/crm_kit/static/description/assets/icons/logo.png differ diff --git a/crm_kit/static/description/assets/icons/manufacturing-black.png b/crm_kit/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/crm_kit/static/description/assets/icons/manufacturing-black.png differ diff --git a/crm_kit/static/description/assets/icons/pos-black.png b/crm_kit/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/crm_kit/static/description/assets/icons/pos-black.png differ diff --git a/crm_kit/static/description/assets/icons/puzzle.png b/crm_kit/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/crm_kit/static/description/assets/icons/puzzle.png differ diff --git a/crm_kit/static/description/assets/icons/restaurant-black.png b/crm_kit/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/crm_kit/static/description/assets/icons/restaurant-black.png differ diff --git a/crm_kit/static/description/assets/icons/service-black.png b/crm_kit/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/crm_kit/static/description/assets/icons/service-black.png differ diff --git a/crm_kit/static/description/assets/icons/trading-black.png b/crm_kit/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/crm_kit/static/description/assets/icons/trading-black.png differ diff --git a/crm_kit/static/description/assets/icons/training.png b/crm_kit/static/description/assets/icons/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/crm_kit/static/description/assets/icons/training.png differ diff --git a/crm_kit/static/description/assets/icons/update.png b/crm_kit/static/description/assets/icons/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/crm_kit/static/description/assets/icons/update.png differ diff --git a/crm_kit/static/description/assets/icons/user.png b/crm_kit/static/description/assets/icons/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/crm_kit/static/description/assets/icons/user.png differ diff --git a/crm_kit/static/description/assets/icons/wrench.png b/crm_kit/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/crm_kit/static/description/assets/icons/wrench.png differ diff --git a/crm_kit/static/description/assets/misc/categories.png b/crm_kit/static/description/assets/misc/categories.png new file mode 100644 index 000000000..bedf1e0b1 Binary files /dev/null and b/crm_kit/static/description/assets/misc/categories.png differ diff --git a/crm_kit/static/description/assets/misc/check-box.png b/crm_kit/static/description/assets/misc/check-box.png new file mode 100644 index 000000000..42caf24b9 Binary files /dev/null and b/crm_kit/static/description/assets/misc/check-box.png differ diff --git a/crm_kit/static/description/assets/misc/compass.png b/crm_kit/static/description/assets/misc/compass.png new file mode 100644 index 000000000..d5fed8faa Binary files /dev/null and b/crm_kit/static/description/assets/misc/compass.png differ diff --git a/crm_kit/static/description/assets/misc/corporate.png b/crm_kit/static/description/assets/misc/corporate.png new file mode 100644 index 000000000..2eb13edbf Binary files /dev/null and b/crm_kit/static/description/assets/misc/corporate.png differ diff --git a/crm_kit/static/description/assets/misc/customer-support.png b/crm_kit/static/description/assets/misc/customer-support.png new file mode 100644 index 000000000..79efc72ed Binary files /dev/null and b/crm_kit/static/description/assets/misc/customer-support.png differ diff --git a/crm_kit/static/description/assets/misc/cybrosys-logo.png b/crm_kit/static/description/assets/misc/cybrosys-logo.png new file mode 100644 index 000000000..cc3cc0ccf Binary files /dev/null and b/crm_kit/static/description/assets/misc/cybrosys-logo.png differ diff --git a/crm_kit/static/description/assets/misc/features.png b/crm_kit/static/description/assets/misc/features.png new file mode 100644 index 000000000..b41769f77 Binary files /dev/null and b/crm_kit/static/description/assets/misc/features.png differ diff --git a/crm_kit/static/description/assets/misc/logo.png b/crm_kit/static/description/assets/misc/logo.png new file mode 100644 index 000000000..478462d3e Binary files /dev/null and b/crm_kit/static/description/assets/misc/logo.png differ diff --git a/crm_kit/static/description/assets/misc/pictures.png b/crm_kit/static/description/assets/misc/pictures.png new file mode 100644 index 000000000..56d255fe9 Binary files /dev/null and b/crm_kit/static/description/assets/misc/pictures.png differ diff --git a/crm_kit/static/description/assets/misc/pie-chart.png b/crm_kit/static/description/assets/misc/pie-chart.png new file mode 100644 index 000000000..426e05244 Binary files /dev/null and b/crm_kit/static/description/assets/misc/pie-chart.png differ diff --git a/crm_kit/static/description/assets/misc/right-arrow.png b/crm_kit/static/description/assets/misc/right-arrow.png new file mode 100644 index 000000000..730984a06 Binary files /dev/null and b/crm_kit/static/description/assets/misc/right-arrow.png differ diff --git a/crm_kit/static/description/assets/misc/star.png b/crm_kit/static/description/assets/misc/star.png new file mode 100644 index 000000000..2eb9ab29f Binary files /dev/null and b/crm_kit/static/description/assets/misc/star.png differ diff --git a/crm_kit/static/description/assets/misc/support.png b/crm_kit/static/description/assets/misc/support.png new file mode 100644 index 000000000..4f18b8b82 Binary files /dev/null and b/crm_kit/static/description/assets/misc/support.png differ diff --git a/crm_kit/static/description/assets/misc/whatsapp.png b/crm_kit/static/description/assets/misc/whatsapp.png new file mode 100644 index 000000000..d513a5356 Binary files /dev/null and b/crm_kit/static/description/assets/misc/whatsapp.png differ diff --git a/crm_kit/static/description/assets/modules/1.png b/crm_kit/static/description/assets/modules/1.png new file mode 100644 index 000000000..5238bdeab Binary files /dev/null and b/crm_kit/static/description/assets/modules/1.png differ diff --git a/crm_kit/static/description/assets/modules/2.png b/crm_kit/static/description/assets/modules/2.png new file mode 100644 index 000000000..1ae7cfe3b Binary files /dev/null and b/crm_kit/static/description/assets/modules/2.png differ diff --git a/crm_kit/static/description/assets/modules/3.png b/crm_kit/static/description/assets/modules/3.png new file mode 100644 index 000000000..3c3ff1afb Binary files /dev/null and b/crm_kit/static/description/assets/modules/3.png differ diff --git a/crm_kit/static/description/assets/modules/4.png b/crm_kit/static/description/assets/modules/4.png new file mode 100644 index 000000000..3fae4631e Binary files /dev/null and b/crm_kit/static/description/assets/modules/4.png differ diff --git a/crm_kit/static/description/assets/modules/5.gif b/crm_kit/static/description/assets/modules/5.gif new file mode 100644 index 000000000..2a5f8e659 Binary files /dev/null and b/crm_kit/static/description/assets/modules/5.gif differ diff --git a/crm_kit/static/description/assets/modules/6.png b/crm_kit/static/description/assets/modules/6.png new file mode 100644 index 000000000..7f2815273 Binary files /dev/null and b/crm_kit/static/description/assets/modules/6.png differ diff --git a/crm_kit/static/description/assets/modules/accounting_image.gif b/crm_kit/static/description/assets/modules/accounting_image.gif new file mode 100644 index 000000000..69bf230e7 Binary files /dev/null and b/crm_kit/static/description/assets/modules/accounting_image.gif differ diff --git a/crm_kit/static/description/assets/modules/approval_image.png b/crm_kit/static/description/assets/modules/approval_image.png new file mode 100644 index 000000000..84fe94e80 Binary files /dev/null and b/crm_kit/static/description/assets/modules/approval_image.png differ diff --git a/crm_kit/static/description/assets/modules/budget_image.png b/crm_kit/static/description/assets/modules/budget_image.png new file mode 100644 index 000000000..fe6aa6fe4 Binary files /dev/null and b/crm_kit/static/description/assets/modules/budget_image.png differ diff --git a/crm_kit/static/description/assets/modules/deadline_image.png b/crm_kit/static/description/assets/modules/deadline_image.png new file mode 100644 index 000000000..6bd27b8b5 Binary files /dev/null and b/crm_kit/static/description/assets/modules/deadline_image.png differ diff --git a/crm_kit/static/description/assets/modules/export_image.png b/crm_kit/static/description/assets/modules/export_image.png new file mode 100644 index 000000000..4e4ea0e51 Binary files /dev/null and b/crm_kit/static/description/assets/modules/export_image.png differ diff --git a/crm_kit/static/description/assets/modules/magento_image.png b/crm_kit/static/description/assets/modules/magento_image.png new file mode 100644 index 000000000..39de0820f Binary files /dev/null and b/crm_kit/static/description/assets/modules/magento_image.png differ diff --git a/crm_kit/static/description/assets/modules/pos_image.png b/crm_kit/static/description/assets/modules/pos_image.png new file mode 100644 index 000000000..c5932894b Binary files /dev/null and b/crm_kit/static/description/assets/modules/pos_image.png differ diff --git a/crm_kit/static/description/assets/modules/shopify_image.png b/crm_kit/static/description/assets/modules/shopify_image.png new file mode 100644 index 000000000..c6d92c16d Binary files /dev/null and b/crm_kit/static/description/assets/modules/shopify_image.png differ diff --git a/crm_kit/static/description/assets/screenshots/CRM-Dashboard-user.png b/crm_kit/static/description/assets/screenshots/CRM-Dashboard-user.png new file mode 100644 index 000000000..794115f30 Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/CRM-Dashboard-user.png differ diff --git a/crm_kit/static/description/assets/screenshots/Crm-Commission-Plan-1.png b/crm_kit/static/description/assets/screenshots/Crm-Commission-Plan-1.png new file mode 100644 index 000000000..215a45b39 Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/Crm-Commission-Plan-1.png differ diff --git a/crm_kit/static/description/assets/screenshots/Crm-Commission-Plan-2.png b/crm_kit/static/description/assets/screenshots/Crm-Commission-Plan-2.png new file mode 100644 index 000000000..2d24daaf6 Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/Crm-Commission-Plan-2.png differ diff --git a/crm_kit/static/description/assets/screenshots/Crm-Commission-Plan-3.png b/crm_kit/static/description/assets/screenshots/Crm-Commission-Plan-3.png new file mode 100644 index 000000000..4de984223 Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/Crm-Commission-Plan-3.png differ diff --git a/crm_kit/static/description/assets/screenshots/Crm-Commission-Plan-4.png b/crm_kit/static/description/assets/screenshots/Crm-Commission-Plan-4.png new file mode 100644 index 000000000..76d6b46a6 Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/Crm-Commission-Plan-4.png differ diff --git a/crm_kit/static/description/assets/screenshots/Crm-Commission-Plan-5.png b/crm_kit/static/description/assets/screenshots/Crm-Commission-Plan-5.png new file mode 100644 index 000000000..35253c12e Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/Crm-Commission-Plan-5.png differ diff --git a/crm_kit/static/description/assets/screenshots/Crm-Commission-Plan-6.png b/crm_kit/static/description/assets/screenshots/Crm-Commission-Plan-6.png new file mode 100644 index 000000000..b65fb540e Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/Crm-Commission-Plan-6.png differ diff --git a/crm_kit/static/description/assets/screenshots/Crm-Commission-Plan-7.png b/crm_kit/static/description/assets/screenshots/Crm-Commission-Plan-7.png new file mode 100644 index 000000000..20b5e973a Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/Crm-Commission-Plan-7.png differ diff --git a/crm_kit/static/description/assets/screenshots/dash_screenshot-1.png b/crm_kit/static/description/assets/screenshots/dash_screenshot-1.png new file mode 100644 index 000000000..1d13a5425 Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/dash_screenshot-1.png differ diff --git a/crm_kit/static/description/assets/screenshots/dash_screenshot-2.png b/crm_kit/static/description/assets/screenshots/dash_screenshot-2.png new file mode 100644 index 000000000..5cf05a3c5 Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/dash_screenshot-2.png differ diff --git a/crm_kit/static/description/assets/screenshots/dash_screenshot-22.png b/crm_kit/static/description/assets/screenshots/dash_screenshot-22.png new file mode 100644 index 000000000..ad247eb9d Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/dash_screenshot-22.png differ diff --git a/crm_kit/static/description/assets/screenshots/dash_screenshot-3.png b/crm_kit/static/description/assets/screenshots/dash_screenshot-3.png new file mode 100644 index 000000000..11799ce0a Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/dash_screenshot-3.png differ diff --git a/crm_kit/static/description/assets/screenshots/dash_screenshot-4.png b/crm_kit/static/description/assets/screenshots/dash_screenshot-4.png new file mode 100644 index 000000000..944bdfaf5 Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/dash_screenshot-4.png differ diff --git a/crm_kit/static/description/assets/screenshots/dash_screenshot-5.png b/crm_kit/static/description/assets/screenshots/dash_screenshot-5.png new file mode 100644 index 000000000..d157c91e0 Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/dash_screenshot-5.png differ diff --git a/crm_kit/static/description/assets/screenshots/dash_screenshot-6.png b/crm_kit/static/description/assets/screenshots/dash_screenshot-6.png new file mode 100644 index 000000000..65e5c42cf Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/dash_screenshot-6.png differ diff --git a/crm_kit/static/description/assets/screenshots/hero.gif b/crm_kit/static/description/assets/screenshots/hero.gif new file mode 100644 index 000000000..29dbb19de Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/hero.gif differ diff --git a/crm_kit/static/description/assets/screenshots/hero_kit.gif b/crm_kit/static/description/assets/screenshots/hero_kit.gif new file mode 100644 index 000000000..8286c472c Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/hero_kit.gif differ diff --git a/crm_kit/static/description/assets/screenshots/img2.png b/crm_kit/static/description/assets/screenshots/img2.png new file mode 100644 index 000000000..1da391f7b Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/img2.png differ diff --git a/crm_kit/static/description/assets/screenshots/img3.png b/crm_kit/static/description/assets/screenshots/img3.png new file mode 100644 index 000000000..02e9c70a3 Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/img3.png differ diff --git a/crm_kit/static/description/assets/screenshots/img4.png b/crm_kit/static/description/assets/screenshots/img4.png new file mode 100644 index 000000000..47ed742b8 Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/img4.png differ diff --git a/crm_kit/static/description/assets/screenshots/img5.png b/crm_kit/static/description/assets/screenshots/img5.png new file mode 100644 index 000000000..09e003b85 Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/img5.png differ diff --git a/crm_kit/static/description/assets/screenshots/img6.png b/crm_kit/static/description/assets/screenshots/img6.png new file mode 100644 index 000000000..28dd869bd Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/img6.png differ diff --git a/crm_kit/static/description/assets/screenshots/img7.png b/crm_kit/static/description/assets/screenshots/img7.png new file mode 100644 index 000000000..3a5e34246 Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/img7.png differ diff --git a/crm_kit/static/description/assets/screenshots/img8.png b/crm_kit/static/description/assets/screenshots/img8.png new file mode 100644 index 000000000..d6b002f72 Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/img8.png differ diff --git a/crm_kit/static/description/assets/screenshots/output.gif b/crm_kit/static/description/assets/screenshots/output.gif new file mode 100644 index 000000000..bae45f11a Binary files /dev/null and b/crm_kit/static/description/assets/screenshots/output.gif differ diff --git a/crm_kit/static/description/banner.png b/crm_kit/static/description/banner.png new file mode 100644 index 000000000..8529b823e Binary files /dev/null and b/crm_kit/static/description/banner.png differ diff --git a/crm_kit/static/description/icon.png b/crm_kit/static/description/icon.png new file mode 100644 index 000000000..e19696a9b Binary files /dev/null and b/crm_kit/static/description/icon.png differ diff --git a/crm_kit/static/description/index.html b/crm_kit/static/description/index.html new file mode 100644 index 000000000..827e00c2d --- /dev/null +++ b/crm_kit/static/description/index.html @@ -0,0 +1,796 @@ +
+ +
+ +
+
+ Community +
+
+ Enterprise +
+
+ Odoo.sh +
+
+
+ + + +

CRM Kit

+

Complete CRM Kit for odoo16

+ + + +
+ + +
+
+ +
+

Explore This + Module

+
+ + + + +
+
+ +
+

Overview +

+
+
+
+ Motivating your sales representatives is one of the key factors for successful sales. The + commission-based + plan helps to motivate your Sales Teams and Salespersons to achieve the goals and earnings. + A Commission Plan module is a monetary incentive for motivating Salespeople to meet their Sales + quota + and the CRM Kit has embraced the functionality. In the CRM Kit, we have 2 types of Commission Plans + which are being defined product-wise and revenue-wise further under revenue-wise we have two types: + the straight commission and graduated commission. The CRM Kit also includes the CRM Dashboard which + helps you to see the Overview of the CRM module. Here, you can view all details related to CRM + modules + such as Leads, Opportunities, Expected, and Total Revenue, also we can see the different reports on + the + various CRM activities.
+ The CRM Kit module is the combination of the CRM Dashboard module by Cybrosys Technologies and the + Commission plan module which will provide an intrusive functional environment for the operation of + the + Customer Relationship Management, with tools to manage the Leads and Opportunities, performing + Activities + on them and turning them into the reliable business. Moreover, the Salesperson and the sales team + are + rewarded based on the business Opportunities they bring into the company with a well-structured plan + which + can be crafted in the beginning.
+
+ + + +
+
+ +
+

Features +

+
+
+
+
+ +
+ Craft custom Commission to Salesperson and Sales + Team +
+
+
+ +
+ Draft Commissions based on Revenue and respective + Product +
+
+
+ +
+ Define Commission based on Product Category +
+
+
+ +
+ Informative Commission Plan report +
+
+
+ +
+ Upcoming and Recent Scheduled activity monitoring +
+
+
+ +
+ Year to Date bar graph +
+
+
+ +
+ Target Field in User Settings +
+
+
+ +
+ Opportunity Lost reason management +
+
+
+ +
+ Top deals and Monthly revenue goals +
+
+
+ +
+ Clickable Dashboard Cards. +
+
+
+
+ +
+
+

+ Configuration

+
+

+ For creating new commission plans:
+

    +
  1. + Creating new commissions:
    +

    Initially Create a new commission and Choose a name to distinguish + that typ

    +
  2. +
  3. + Select the type of the Commission:
    +

    Product-based: Commissions are calculated as the percentage of + the price based on the selected product in the form.

    +

    Revenue-based: A certain percentage of revenue is given as + Commission to the Salesperson

    +

    + Straight revenue: Commissions are calculated using a fixed + percentage of the revenue sold. You can fill the percentage in the field "Commission + rate".
    +

    +

    + Graduated revenue: Commissions are calculated as a percentage + of the revenue generated at amount intervals.
    +

    +

    + You can fill in the amount intervals and the percentages in the + "Graduated Revenue Commission" field.
    +

    +
  4. +
+ +

+ For adding Commission in Salesperson & Sales team:
+

+ Go to CRM -> Configuration -> Salesperson or Sales team +
    +
  • Edit the Salesperson or Sales team
  • +
  • Choose a commission type
  • +
  • Save it
  • +
+ +

+ For printing Commission in XLSX report::
+

+ Go to CRM -> Configuration -> Salesperson or Sales team +
    +
  • CRM -> Reporting -> Commission Report
  • +
  • CRM -> Reporting -> Commission Report
  • +
+
+
+ + +
+
+ +
+

Screenshots +

+
+
+
+ +
+

Clickable Dashboard Card

+

The Commission Plan window can be accessed from the Configuration tab of the module and + selected + on + the Commission Plan menu. Here all the Commission Plan details of the operation in respect + to + the + functioning of the Odoo CRM will be depicted.

+ +
+
+

Commission Plan based on Product Category

+

The Commission Plan Creation window can be accessed from the Commission Plan window and while + selecting the Type the Product Wise options can be selected. Further, the Product Categories + with + respect to the respective Product Category based Commission Plan can be defined.

+ +
+
+

Revenue-based Commission Plan: Straight Revenue Commission Plan

+

The second form of Commission Plan in the Odoo CRM Kit where the Sales Revenue and its + percentage + calculation will be provided as Commission to the Salesperson.
+ While Creating a Straight Revenue Commission plan the Commission type can be selected as + Straight + Commission. Further, the commission rate can be defined under the Straight Revenue + Commission + tab.

+ +
+
+

Revenue-based Commission Plan: Graduated Revenue Commission Plan

+

While Creating a Graduated Revenue Commission Plan the Commission type can be selected as + Graduated Commission. Further, the commission rate can be defined under the Graduated + Revenue + Commission tab.

+ +
+
+

Assigning Commission Plan for Salesperson

+

In the CRM Kit under the respective Salesperson description tab, there will be a dedicated + tab + the + Commission Plan where the respective Commission Plan with respect to the operation can be + defined.

+ +
+
+

Assigning Commission Plan for Sales Team

+

In the CRM Kit under the respective sales team description tab, there will be a dedicated tab + the + Commission Plan where the respective Commission Plan with respect to the operation can be + defined.

+ +
+
+

Print the Commission Plan Report in XLSX Format

+

The CRM Kit also holds an advanced operations feature where the Admins, as well as every + User, + can take the Print out of the Commission Plan Reports based on their need and for the period + of + operations that are required. The Reports can be generated in XLSX formats and can be saved + based + on the need. To take the printout of the Commission Plan Report you should go to the + Reporting + tab + of the CRM KIt and further select the Commission Plan menu and select the Required entries + and + Click to Print XLS.

+ +
+
+

Year to Date Chart and Lead Analysis

+

A dedicated insight will be provided with the help of the Funnel Chart on the Leads with + indications + as New, Qualified, Proposition, and Won. The Donut graph based on the monthly Lead operation + will + provide a clear picture of the monthly Lead operations. Additionally, the Activity Donut + graph + will + describe the activity analysis on the leads.

+ +
+
+

Set custom targets for Salesperson

+

For each of the individual Salespersons, you will be able to set dedicated Targets using the + CRM + Kit. + This will ensure that the Salesperson is motivated to keep with the business. The Targets + can be + set + under the Settings tab > User Settings > Below the access right tab.

+ +
+
+

Top deals and Monthly Goal Gauge.

+

The Top Deals listing will help the Salespersons to promote them easily without moving to the + sales + module. Moreover, the Top Deals can be listed out based on the custom ones which are being + defined. + The Monthly Goal Gauge will provide insight on the targets and the achievement rate of each + of + the + Salesperson.

+ +
+
+

Upcoming Activities and Total Revenue

+

Activities and their effective management are the keys for the effective operation of the + Customer + Relationship Management operations of the company. With the CRM Kit, the user will have a + dedicated + Upcoming Activities tab which will provide the complete information in regards to the CRM + operations + of the business. This will ensure that the Salesperson is always planned for the scheduled + Activities + and will not disappoint the clients.
+ The Total Revenue by Salesperson donut chart will provide a complete insight on the Revenue + achieved + or Won, Lost and the Expected Revenue which will be achieved.

+ +
+
+

Dashboard View of the User

+

The Admin, as well as the User who has access to the CRM Kit, can function the various + operations with it and each of the Users and the Admin have a separate CRM Dashboard based + on + the + operational authorization. The Following screenshot depicts the User view of the CRM + Dashboard. + Here the information relating to the respective user and their operations will be only + depicted + and the ones which the respective User has authorization to can be modified.

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

Related + 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

+
+
+
+
+
+
+
+ +
+
+
+ \ No newline at end of file diff --git a/crm_kit/static/src/js/action_manager.js b/crm_kit/static/src/js/action_manager.js new file mode 100644 index 000000000..0e54c8ac8 --- /dev/null +++ b/crm_kit/static/src/js/action_manager.js @@ -0,0 +1,21 @@ +/** @odoo-module */ + +import { registry } from "@web/core/registry"; +import { download } from "@web/core/network/download"; +import framework from 'web.framework'; +import session from 'web.session'; + +registry.category("ir.actions.report handlers").add("xlsx", async (action) => { + if (action.report_type === 'xlsx') { + framework.blockUI(); + var def = $.Deferred(); + session.get_file({ + url: '/xlsx_reports', + data: action.data, + success: def.resolve.bind(def), + error: (error) => this.call('crash_manager', 'rpc_error', error), + complete: framework.unblockUI, + }); + return def; + } +}); diff --git a/crm_kit/views/commission.xml b/crm_kit/views/commission.xml new file mode 100644 index 000000000..d03d06032 --- /dev/null +++ b/crm_kit/views/commission.xml @@ -0,0 +1,128 @@ + + + + team commission plan + crm.team + + + + + + + + + + sales persons commission plan + res.users + + + + + + + + + + crm.commission.tree + crm.commission + + + + + + + + + + crm.commission.form + crm.commission + +
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + +
+
+
+
+ + + CRM Commission Plan + ir.actions.act_window + crm.commission + tree,form + +

+ Create New Commission Plan! +

+
+
+ + + + + Sales Persons + ir.actions.act_window + res.users + [('share','=',False)] + tree,kanban,form + + + +
\ No newline at end of file diff --git a/crm_kit/wizard/__init__.py b/crm_kit/wizard/__init__.py new file mode 100644 index 000000000..2653dce1f --- /dev/null +++ b/crm_kit/wizard/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2021-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 commission_report diff --git a/crm_kit/wizard/commission_report.py b/crm_kit/wizard/commission_report.py new file mode 100644 index 000000000..5a10513fc --- /dev/null +++ b/crm_kit/wizard/commission_report.py @@ -0,0 +1,372 @@ +"""Report Wizard for Commission Plan""" +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2021-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 io +import json +from odoo import models, fields, api +from odoo.tools import date_utils +from odoo.exceptions import ValidationError + +try: + from odoo.tools.misc import xlsxwriter +except ImportError: + import xlsxwriter + + +class CommissionReportWizard(models.TransientModel): + _name = 'commission.wizard' + _description = 'Commission Report Wizard' + + date_from = fields.Date(string="From Date") + date_to = fields.Date(string="To Date") + salesperson_ids = fields.Many2many('res.users', string='Salesperson', + domain="[('share','=',False)]") + sales_team_ids = fields.Many2many('crm.team', string='Sales Team') + date = fields.Date(string='Date', default=fields.Date.context_today) + is_sales_person = fields.Boolean(default=False, string="Is sales person") + is_sales_team = fields.Boolean(default=False, string="Is sales team") + + @api.onchange('salesperson_ids') + def onchange_salesperson_ids(self): + """Function for hide a field base on values""" + self.is_sales_person = True if self.salesperson_ids else False + + @api.onchange('sales_team_ids') + def onchange_sales_team_ids(self): + self.is_sales_team = True if self.sales_team_ids else False + + @api.constrains('sales_team_ids', 'salesperson_ids') + def sales_team_constrains(self): + """Function for showing validation error""" + for rec in self: + if self.sales_team_ids: + if not rec.sales_team_ids.member_ids: + raise ValidationError( + "Selected Sales Team haven't any Salespersons") + if not self.sales_team_ids.member_ids.commission_id and \ + not self.sales_team_ids.commission_id: + raise ValidationError( + "Selected Sales Team haven't any Commission Plan") + elif self.salesperson_ids and not rec.salesperson_ids.commission_id: + raise ValidationError( + "Selected Salesperson haven't any Commission Plan") + + def print_xls_report(self): + """Function for printing xlsx report""" + # sales person's condition starts here # + user_sale_orders = self.env['sale.order'].search([ + ('user_id', 'in', self.salesperson_ids.ids)]) + user_sale_orders_dict = {} + total_list = [] + commission_list = [] + user_commission_name = [] + user_commission_salesperson = [] + user_obj = user_sale_orders.mapped('user_id').sorted(key=lambda d: d.id) + for user in user_obj: + user_sale_orders_dict.update({ + user: user_sale_orders.filtered(lambda l: l.user_id == user) + }) + for user, user_sale_orders in user_sale_orders_dict.items(): + commission_id = user.commission_id + if not commission_id: + continue + filtered_order_lines = user_sale_orders.filtered( + lambda l: self.date_from <= l.date_order.date( + ) <= self.date_to and l.date_order.date() >= commission_id.date_from + ).mapped('order_line') + filtered_order_lines_commission_total = sum( + filtered_order_lines.mapped('price_subtotal')) + + if commission_id.type == 'product': + commission_products = commission_id.product_comm_ids.product_id + prod_commission = filtered_order_lines.filtered( + lambda l: l.product_id in commission_products) + for rule in commission_id.product_comm_ids.filtered( + lambda l: l.product_id in prod_commission.mapped( + 'product_id')): + product_order_line = prod_commission.filtered( + lambda l: l.product_id == rule.product_id) + total_price = sum( + product_order_line.mapped('price_subtotal')) + product_commission = (total_price * rule.percentage) / 100 + total_list.append(total_price) + user_commission_name.append(commission_id.name) + user_commission_salesperson.append(user.name) + commission_list.append(rule.amount) if ( + product_commission > rule.amount) \ + else commission_list.append(product_commission) + + if commission_id.type == 'revenue' and ( + commission_id.revenue_type == 'graduated'): + for rule in commission_id.revenue_grd_comm_ids: + if rule.amount_from <= filtered_order_lines_commission_total < rule.amount_to: + graduated_commission = (filtered_order_lines_commission_total + * rule.graduated_commission_rate) / 100 + commission_list.append(graduated_commission) + user_commission_name.append(commission_id.name) + user_commission_salesperson.append(user.name) + total_list.append(filtered_order_lines_commission_total) + + if commission_id.type == 'revenue' and ( + commission_id.revenue_type == 'straight'): + straight_commission = (filtered_order_lines_commission_total + * commission_id.straight_commission_rate) / 100 + commission_list.append(straight_commission) + user_commission_name.append(commission_id.name) + user_commission_salesperson.append(user.name) + total_list.append(filtered_order_lines_commission_total) + # sales person's condition ends here # + + if not self.sales_team_ids and not self.salesperson_ids: + self.sales_team_ids = self.env['crm.team'].search([]) + + # sales team's condition starts here # + team_wizard_persons = self.sales_team_ids.member_ids + team_sale_orders = self.env['sale.order'].search( + [('user_id', 'in', team_wizard_persons.ids)]) + # print(team_sale_orders) + team_sale_orders_dict = {} + commission_total = [] + commission = [] + commission_name = [] + commission_salesperson = [] + commission_sales_team = [] + team_obj = team_sale_orders.mapped('user_id').sorted(key=lambda d: d.id) + # print(team_obj) + for team_user in team_obj: + team_sale_orders_dict.update({ + team_user: team_sale_orders.filtered( + lambda l: l.user_id == team_user) + }) + # print(team_sale_orders_dict) + for team_user, team_sale_orders in team_sale_orders_dict.items(): + commissions_id = team_user.commission_id if team_user.commission_id \ + else team_user.sale_team_id.commission_id + # print(commissions_id) + if commissions_id: + filtered_order_lines = team_sale_orders.filtered( + lambda l: self.date_from <= l.date_order.date( + ) <= self.date_to and l.date_order.date() >= commissions_id.date_from + ).mapped('order_line') + filtered_order_lines_commission_total = sum( + filtered_order_lines.mapped('price_subtotal')) + if commissions_id.type == 'product': + commission_products = commissions_id.product_comm_ids.product_id + prod_commission = filtered_order_lines.filtered( + lambda l: l.product_id in commission_products) + for rules in commissions_id.product_comm_ids.filtered( + lambda l: l.product_id in prod_commission.mapped( + 'product_id')): + product_order_line = prod_commission.filtered( + lambda l: l.product_id == rules.product_id) + total_price = sum( + product_order_line.mapped('price_subtotal')) + product_commission = (total_price * rules.percentage) / 100 + commission_total.append(total_price) + commission_name.append(commissions_id.name) + commission_salesperson.append(team_user.name) + commission_sales_team.append( + team_user.sale_team_id.name) + commission.append(rules.amount) if ( + product_commission > rules.amount) \ + else commission.append(product_commission) + + if commissions_id.type == 'revenue' and ( + commissions_id.revenue_type == 'graduated'): + for rules in commissions_id.revenue_grd_comm_ids: + if rules.amount_from <= filtered_order_lines_commission_total \ + < rules.amount_to: + graduated_commission = (filtered_order_lines_commission_total + * rules.graduated_commission_rate) / 100 + commission.append(graduated_commission) + commission_name.append(commissions_id.name) + commission_salesperson.append(team_user.name) + commission_sales_team.append( + team_user.sale_team_id.name) + commission_total.append( + filtered_order_lines_commission_total) + + if commissions_id.type == 'revenue' and ( + commissions_id.revenue_type == 'straight'): + straight_commission = (filtered_order_lines_commission_total + * commissions_id.straight_commission_rate) / 100 + commission.append(straight_commission) + commission_name.append(commissions_id.name) + commission_salesperson.append(team_user.name) + commission_sales_team.append(team_user.sale_team_id.name) + commission_total.append( + filtered_order_lines_commission_total) + # sales team's condition ends here # + + data = { + 'model_id': self.id, + 'date': self.date, + 'date_from': self.date_from, + 'date_to': self.date_to, + 'sales_team_ids': self.sales_team_ids.ids, + 'salesperson_ids': self.salesperson_ids.ids, + 'commission_list': commission_list, + 'total_list': total_list, + 'commission': commission, + 'commission_total': commission_total, + 'commission_name': commission_name, + 'commission_salesperson': commission_salesperson, + 'commission_sales_team': commission_sales_team, + 'user_commission_name': user_commission_name, + 'user_commission_salesperson': user_commission_salesperson, + } + return { + 'type': 'ir.actions.report', + 'data': { + 'model': 'commission.wizard', + 'options': json.dumps(data, default=date_utils.json_default), + 'output_format': 'xlsx', + 'report_name': 'Commission Plan xlsx report'}, + 'report_type': 'xlsx' + } + + def get_xlsx_report(self, data, response): + """get_xlsx_report function""" + date = data['date'] + team = data['sales_team_ids'] + user = data['salesperson_ids'] + commission_list = data['commission_list'] + total_list = data['total_list'] + commission = data['commission'] + commission_total = data['commission_total'] + commission_name = data['commission_name'] + commission_salesperson = data['commission_salesperson'] + commission_sales_team = data['commission_sales_team'] + user_commission_name = data['user_commission_name'] + user_commission_salesperson = data['user_commission_salesperson'] + + output = io.BytesIO() + workbook = xlsxwriter.Workbook(output, {'in_memory': True}) + sheet = workbook.add_worksheet() + head = workbook.add_format({'align': 'center', 'bold': True, + 'font_size': '15px', 'valign': 'vcenter'}) + format1 = workbook.add_format({'align': 'left', 'font_size': '12px'}) + format2 = workbook.add_format({'align': 'right', 'font_size': '12x'}) + format3 = workbook.add_format( + {'align': 'right', 'font_size': '12x', 'bold': True}) + heading = workbook.add_format({'align': 'left', 'bold': True, + 'font_size': '12px', + 'valign': 'vcenter'}) + date_format = workbook.add_format( + {'num_format': 'dd/mm/yy', 'align': 'left', 'font_size': '10px'}) + + sheet.merge_range('A2:B2', "Printed Date: " + date, date_format) + sheet.write('A4', 'No.', heading) + sheet.set_column(5, 1, 25) + sheet.set_row(0, 25) + row = 5 + col = 0 + index = 1 + if user: + sheet.merge_range('A1:E1', 'COMMISSION PLAN REPORT', head) + sheet.write('D2', 'Date From: ' + data['date_from'], date_format) + sheet.write('E2', 'Date To: ' + data['date_to'], date_format) + + sheet.write('B4', 'Sale Persons', heading) + sheet.write('C4', 'Commission Plan Name', heading) + sheet.write('D4', 'Total Revenue', heading) + sheet.write('E4', 'Commission Amount', heading) + + for j in user_commission_salesperson: + sheet.write(row, col + 0, index, format2) + sheet.write(row, col + 1, j, format1) + row += 1 + index += 1 + + row = 5 + col = 0 + for j in user_commission_name: + sheet.write(row, col + 2, j, format1) + row += 1 + + row = 5 + col = 0 + for j in total_list: + sheet.write(row, col + 3, round(j, 2), format2) + row += 1 + + row = 5 + col = 0 + for i in commission_list: + sheet.write(row, col + 4, round(i, 2), format2) + row += 1 + + sheet.write(row + 1, col + 2, 'Total', format3) + sheet.write(row + 1, col + 3, round(sum(total_list), 2), format2) + sheet.write(row + 1, col + 4, round(sum(commission_list), 2), + format2) + + elif team: + sheet.merge_range('A1:F1', 'COMMISSION PLAN REPORT', head) + sheet.write('E2', 'Date From: ' + data['date_from'], date_format) + sheet.write('F2', 'Date To: ' + data['date_to'], date_format) + + sheet.write('B4', 'Sales Teams', heading) + sheet.write('C4', 'Sales Person', heading) + sheet.write('D4', 'Commission Plan Name', heading) + sheet.write('E4', 'Total Revenue', heading) + sheet.write('F4', 'Commission Amount', heading) + + for j in commission_sales_team: + sheet.write(row, col + 0, index, format2) + sheet.write(row, col + 1, j, format1) + row += 1 + index += 1 + + row = 5 + col = 0 + for j in commission_salesperson: + sheet.write(row, col + 2, j, format1) + row += 1 + + row = 5 + col = 0 + for j in commission_name: + sheet.write(row, col + 3, j, format1) + row += 1 + + row = 5 + col = 0 + for j in commission_total: + sheet.write(row, col + 4, round(j, 2), format2) + row += 1 + + row = 5 + col = 0 + for i in commission: + sheet.write(row, col + 5, round(i, 2), format2) + row += 1 + + sheet.write(row + 1, col + 3, 'Total:', format3) + sheet.write(row + 1, col + 4, round(sum(commission_total), 2), + format2) + sheet.write(row + 1, col + 5, round(sum(commission), 2), format2) + + workbook.close() + output.seek(0) + response.stream.write(output.read()) + output.close() diff --git a/crm_kit/wizard/commission_report.xml b/crm_kit/wizard/commission_report.xml new file mode 100644 index 000000000..6a6616588 --- /dev/null +++ b/crm_kit/wizard/commission_report.xml @@ -0,0 +1,48 @@ + + + + commission.wizard.form + commission.wizard + form + +
+ + + + + + + + + + + + + + +
+
+
+
+
+ + + Commission Report + commission.wizard + form + + new + + + +
\ No newline at end of file diff --git a/customer_product_qrcode/README.rst b/customer_product_qrcode/README.rst new file mode 100755 index 000000000..07e681067 --- /dev/null +++ b/customer_product_qrcode/README.rst @@ -0,0 +1,46 @@ +Customer and Product QR Code Generator +====================================== + +The Customer and Product QRCode Generator Helps You to Generate Unique +QR Codes to your Products or Customers + +Installation +============ + - www.odoo.com/documentation/16.0/setup/install.html + - Install our custom addon + +License +------- +General Public License, Version 3 (LGPL v3). +(https://www.odoo.com/documentation/user/15.0/legal/licenses/licenses.html) + +Company +------- +* 'Cybrosys Techno Solutions `__ + +Credits +------- +* Developer: +(V14) Sarath Suresh @ Cybrosys +(V15) Midilaj V K @ Cybrosys +(V16) Athira P S @ Cybrosys + + +Contacts +-------- +* Mail Contact : odoo@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 +========== +This module is maintained by Cybrosys Technologies. + +For support and more information, please visit https://www.cybrosys.com + +Further information +=================== +HTML Description: ``__ + diff --git a/customer_product_qrcode/__init__.py b/customer_product_qrcode/__init__.py new file mode 100755 index 000000000..73aefe930 --- /dev/null +++ b/customer_product_qrcode/__init__.py @@ -0,0 +1,32 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2021-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 +from . import report +from odoo import api, SUPERUSER_ID + + +def _set_qr(cr, registry): + env = api.Environment(cr, SUPERUSER_ID, {}) + for record in env['product.product'].search([]): + name = record.name.replace(" ", "") + record.sequence = 'DEF' + name.upper()+str(record.id) + record.generate_qr() diff --git a/customer_product_qrcode/__manifest__.py b/customer_product_qrcode/__manifest__.py new file mode 100755 index 000000000..7c538d769 --- /dev/null +++ b/customer_product_qrcode/__manifest__.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2021-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': 'Customer and Product QR Code Generator', + 'version': '16.0.1.0.0', + 'summary': 'Generate Unique QR Codes for Customers and Products', + 'description': 'QR Code, QR Code Generator, Odoo QR Code Generator, Customer QR Code, Product QR Code, QR, QR Code Odoo', + 'category': 'Extra Tools', + 'author': 'Cybrosys Techno solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'website': 'https://www.cybrosys.com', + 'depends': ['base', 'sale', 'stock'], + 'data': [ + 'report/paperformat.xml', + 'report/report.xml', + 'views/view.xml', + 'report/template.xml', + ], + 'images': ['static/description/banner.png'], + 'installable': True, + 'application': False, + 'auto_install': False, + 'license': 'LGPL-3', + 'post_init_hook': '_set_qr' +} diff --git a/customer_product_qrcode/doc/RELEASE_NOTES.md b/customer_product_qrcode/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..cbd51ab03 --- /dev/null +++ b/customer_product_qrcode/doc/RELEASE_NOTES.md @@ -0,0 +1,6 @@ +## Module + +#### 03.10.2022 +#### Version 16.0.1.0.0 +#### ADD +- Initial commit for customer_product_qrcode \ No newline at end of file diff --git a/customer_product_qrcode/models/__init__.py b/customer_product_qrcode/models/__init__.py new file mode 100755 index 000000000..f2c5a4636 --- /dev/null +++ b/customer_product_qrcode/models/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2021-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/customer_product_qrcode/models/models.py b/customer_product_qrcode/models/models.py new file mode 100755 index 000000000..2b198c7ad --- /dev/null +++ b/customer_product_qrcode/models/models.py @@ -0,0 +1,210 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2021-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 . +# +############################################################################# + +try: + import qrcode +except ImportError: + qrcode = None +try: + import base64 +except ImportError: + base64 = None +from io import BytesIO + +from odoo import models, fields, api, _, SUPERUSER_ID +from odoo.exceptions import UserError + + +class Partners(models.Model): + _inherit = 'res.partner' + + sequence = fields.Char(string="QR Sequence", readonly=True) + qr = fields.Binary(string="QR Code") + + def init(self): + for record in self.env['res.partner'].search( + [('customer_rank', '=', True)]): + print(record,"record") + name = record.name.replace(" ", "") + print(name) + record.sequence = 'DEF' + name.upper() + str(record.id) + + @api.model + def create(self, vals): + prefix = self.env['ir.config_parameter'].sudo().get_param( + 'customer_product_qr.config.customer_prefix') + if not prefix: + raise UserError(_('Set A Customer Prefix In General Settings')) + prefix = str(prefix) + seq = prefix + self.env['ir.sequence'].next_by_code( + 'res.partner') or '/' + vals['sequence'] = seq + return super(Partners, self).create(vals) + + @api.depends('sequence') + def generate_qr(self): + if qrcode and base64: + if not self.sequence: + prefix = self.env['ir.config_parameter'].sudo().get_param( + 'customer_product_qr.config.customer_prefix') + if not prefix: + raise UserError( + _('Set A Customer Prefix In General Settings')) + prefix = str(prefix) + self.sequence = prefix + self.env['ir.sequence'].next_by_code( + 'res.partner') or '/' + qr = qrcode.QRCode( + version=1, + error_correction=qrcode.constants.ERROR_CORRECT_L, + box_size=10, + border=4, + ) + qr.add_data(self.sequence) + qr.make(fit=True) + + img = qr.make_image() + temp = BytesIO() + img.save(temp, format="PNG") + qr_image = base64.b64encode(temp.getvalue()) + # print(qr_image,"qr") + self.write({'qr': qr_image}) + print(qr,"qr") + return self.env.ref( + 'customer_product_qrcode.print_qr').report_action(self, data={ + 'data': self.id, 'type': 'cust'}) + else: + raise UserError( + _('Necessary Requirements To Run This Operation Is Not Satisfied')) + + def get_partner_by_qr(self, **args): + return self.env['res.partner'].search([('sequence', '=', self.id), ], + limit=1).id + + +class Products(models.Model): + _inherit = 'product.product' + + sequence = fields.Char(string="QR Sequence", readonly=True) + qr = fields.Binary(string="QR Code") + + @api.model + def create(self, vals): + prefix = self.env['ir.config_parameter'].sudo().get_param( + 'customer_product_qr.config.product_prefix') + if not prefix: + raise UserError(_('Set A Product Prefix In General Settings')) + prefix = str(prefix) + seq = prefix + self.env['ir.sequence'].next_by_code( + 'product.product') or '/' + vals['sequence'] = seq + qr = qrcode.QRCode( + version=1, + error_correction=qrcode.constants.ERROR_CORRECT_L, + box_size=10, + border=4, + ) + qr.add_data(vals['sequence']) + qr.make(fit=True) + + img = qr.make_image() + temp = BytesIO() + img.save(temp, format="PNG") + qr_image = base64.b64encode(temp.getvalue()) + vals.update({'qr': qr_image}) + return super(Products, self).create(vals) + + @api.depends('sequence') + def generate_qr(self): + if qrcode and base64: + if not self.sequence: + prefix = self.env['ir.config_parameter'].sudo().get_param( + 'customer_product_qr.config.product_prefix') + if not prefix: + raise UserError( + _('Set A Customer Prefix In General Settings')) + prefix = str(prefix) + self.sequence = prefix + self.env['ir.sequence'].next_by_code( + 'product.product') or '/' + qr = qrcode.QRCode( + version=1, + error_correction=qrcode.constants.ERROR_CORRECT_L, + box_size=10, + border=4, + ) + qr.add_data(self.sequence) + qr.make(fit=True) + + img = qr.make_image() + temp = BytesIO() + img.save(temp, format="PNG") + qr_image = base64.b64encode(temp.getvalue()) + self.write({'qr': qr_image}) + return self.env.ref( + 'customer_product_qrcode.print_qr2').report_action(self, data={ + 'data': self.id, 'type': 'prod'}) + else: + raise UserError( + _('Necessary Requirements To Run This Operation Is Not Satisfied')) + + def get_product_by_qr(self, **args): + return self.env['product.product'].search( + [('sequence', '=', self.id), ], limit=1).id + + +class ProductTemplate(models.Model): + _inherit = 'product.template' + + def generate_qr(self): + product = self.env['product.product'].search( + [('product_tmpl_id', '=', self.id)]) + print(product,"product") + for rec in product: + rec.generate_qr() + return self.env.ref('customer_product_qrcode.print_qr2').report_action( + self, data={'data': self.id, 'type': 'all'}) + + +class ResConfigSettings(models.TransientModel): + _inherit = 'res.config.settings' + + customer_prefix = fields.Char(string="Customer QR Prefix") + product_prefix = fields.Char(string="Product QR Prefix") + + def get_values(self): + res = super(ResConfigSettings, self).get_values() + customer_prefix = self.env["ir.config_parameter"].get_param( + "customer_product_qr.config.customer_prefix") + product_prefix = self.env["ir.config_parameter"].get_param( + "customer_product_qr.config.product_prefix") + res.update({ + 'customer_prefix': customer_prefix if type( + customer_prefix) else False, + 'product_prefix': product_prefix if type(product_prefix) else False + } + ) + return res + + def set_values(self): + self.env['ir.config_parameter'].sudo().set_param( + 'customer_product_qr.config.customer_prefix', self.customer_prefix) + self.env['ir.config_parameter'].sudo().set_param( + 'customer_product_qr.config.product_prefix', self.product_prefix) diff --git a/customer_product_qrcode/report/__init__.py b/customer_product_qrcode/report/__init__.py new file mode 100755 index 000000000..f4ba7d127 --- /dev/null +++ b/customer_product_qrcode/report/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2021-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 parser diff --git a/customer_product_qrcode/report/paperformat.xml b/customer_product_qrcode/report/paperformat.xml new file mode 100755 index 000000000..dab9a0264 --- /dev/null +++ b/customer_product_qrcode/report/paperformat.xml @@ -0,0 +1,17 @@ + + + PDF Report + + custom + 100 + 100 + Portrait + 10 + 0 + 10 + 10 + + 80 + 90 + + \ No newline at end of file diff --git a/customer_product_qrcode/report/parser.py b/customer_product_qrcode/report/parser.py new file mode 100755 index 000000000..233de2361 --- /dev/null +++ b/customer_product_qrcode/report/parser.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2021-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 odoo import models, api +from odoo.http import request + + +class CustomerBadge(models.AbstractModel): + _name = 'report.customer_product_qrcode.customer_qr_template' + + @api.model + def _get_report_values(self, docids, data=None): + print(data,"data") + if data['type'] == 'cust': + dat = [request.env['res.partner'].browse(data['data'])] + elif data['type'] == 'all': + dat = [request.env['product.product'].search([('product_tmpl_id', '=', data['data'])])] + else: + dat = request.env['product.product'].browse(data['data']) + return { + 'data': dat, + } diff --git a/customer_product_qrcode/report/report.xml b/customer_product_qrcode/report/report.xml new file mode 100755 index 000000000..189fd7b67 --- /dev/null +++ b/customer_product_qrcode/report/report.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/customer_product_qrcode/report/template.xml b/customer_product_qrcode/report/template.xml new file mode 100755 index 000000000..57584ee73 --- /dev/null +++ b/customer_product_qrcode/report/template.xml @@ -0,0 +1,50 @@ + + + + + + \ No newline at end of file diff --git a/customer_product_qrcode/static/description/assets/icons/check.png b/customer_product_qrcode/static/description/assets/icons/check.png new file mode 100644 index 000000000..c8e85f51d Binary files /dev/null and b/customer_product_qrcode/static/description/assets/icons/check.png differ diff --git a/customer_product_qrcode/static/description/assets/icons/chevron.png b/customer_product_qrcode/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..2089293d6 Binary files /dev/null and b/customer_product_qrcode/static/description/assets/icons/chevron.png differ diff --git a/customer_product_qrcode/static/description/assets/icons/cogs.png b/customer_product_qrcode/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/customer_product_qrcode/static/description/assets/icons/cogs.png differ diff --git a/customer_product_qrcode/static/description/assets/icons/consultation.png b/customer_product_qrcode/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/customer_product_qrcode/static/description/assets/icons/consultation.png differ diff --git a/customer_product_qrcode/static/description/assets/icons/ecom-black.png b/customer_product_qrcode/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/customer_product_qrcode/static/description/assets/icons/ecom-black.png differ diff --git a/customer_product_qrcode/static/description/assets/icons/education-black.png b/customer_product_qrcode/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/customer_product_qrcode/static/description/assets/icons/education-black.png differ diff --git a/customer_product_qrcode/static/description/assets/icons/hotel-black.png b/customer_product_qrcode/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/customer_product_qrcode/static/description/assets/icons/hotel-black.png differ diff --git a/customer_product_qrcode/static/description/assets/icons/license.png b/customer_product_qrcode/static/description/assets/icons/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/customer_product_qrcode/static/description/assets/icons/license.png differ diff --git a/customer_product_qrcode/static/description/assets/icons/lifebuoy.png b/customer_product_qrcode/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/customer_product_qrcode/static/description/assets/icons/lifebuoy.png differ diff --git a/customer_product_qrcode/static/description/assets/icons/manufacturing-black.png b/customer_product_qrcode/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/customer_product_qrcode/static/description/assets/icons/manufacturing-black.png differ diff --git a/customer_product_qrcode/static/description/assets/icons/pos-black.png b/customer_product_qrcode/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/customer_product_qrcode/static/description/assets/icons/pos-black.png differ diff --git a/customer_product_qrcode/static/description/assets/icons/puzzle.png b/customer_product_qrcode/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/customer_product_qrcode/static/description/assets/icons/puzzle.png differ diff --git a/customer_product_qrcode/static/description/assets/icons/restaurant-black.png b/customer_product_qrcode/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/customer_product_qrcode/static/description/assets/icons/restaurant-black.png differ diff --git a/customer_product_qrcode/static/description/assets/icons/service-black.png b/customer_product_qrcode/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/customer_product_qrcode/static/description/assets/icons/service-black.png differ diff --git a/customer_product_qrcode/static/description/assets/icons/trading-black.png b/customer_product_qrcode/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/customer_product_qrcode/static/description/assets/icons/trading-black.png differ diff --git a/customer_product_qrcode/static/description/assets/icons/training.png b/customer_product_qrcode/static/description/assets/icons/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/customer_product_qrcode/static/description/assets/icons/training.png differ diff --git a/customer_product_qrcode/static/description/assets/icons/update.png b/customer_product_qrcode/static/description/assets/icons/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/customer_product_qrcode/static/description/assets/icons/update.png differ diff --git a/customer_product_qrcode/static/description/assets/icons/user.png b/customer_product_qrcode/static/description/assets/icons/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/customer_product_qrcode/static/description/assets/icons/user.png differ diff --git a/customer_product_qrcode/static/description/assets/icons/wrench.png b/customer_product_qrcode/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/customer_product_qrcode/static/description/assets/icons/wrench.png differ diff --git a/customer_product_qrcode/static/description/assets/misc/categories.png b/customer_product_qrcode/static/description/assets/misc/categories.png new file mode 100644 index 000000000..bedf1e0b1 Binary files /dev/null and b/customer_product_qrcode/static/description/assets/misc/categories.png differ diff --git a/customer_product_qrcode/static/description/assets/misc/check-box.png b/customer_product_qrcode/static/description/assets/misc/check-box.png new file mode 100644 index 000000000..42caf24b9 Binary files /dev/null and b/customer_product_qrcode/static/description/assets/misc/check-box.png differ diff --git a/customer_product_qrcode/static/description/assets/misc/compass.png b/customer_product_qrcode/static/description/assets/misc/compass.png new file mode 100644 index 000000000..d5fed8faa Binary files /dev/null and b/customer_product_qrcode/static/description/assets/misc/compass.png differ diff --git a/customer_product_qrcode/static/description/assets/misc/corporate.png b/customer_product_qrcode/static/description/assets/misc/corporate.png new file mode 100644 index 000000000..2eb13edbf Binary files /dev/null and b/customer_product_qrcode/static/description/assets/misc/corporate.png differ diff --git a/customer_product_qrcode/static/description/assets/misc/customer-support.png b/customer_product_qrcode/static/description/assets/misc/customer-support.png new file mode 100644 index 000000000..79efc72ed Binary files /dev/null and b/customer_product_qrcode/static/description/assets/misc/customer-support.png differ diff --git a/customer_product_qrcode/static/description/assets/misc/cybrosys-logo.png b/customer_product_qrcode/static/description/assets/misc/cybrosys-logo.png new file mode 100644 index 000000000..cc3cc0ccf Binary files /dev/null and b/customer_product_qrcode/static/description/assets/misc/cybrosys-logo.png differ diff --git a/customer_product_qrcode/static/description/assets/misc/features.png b/customer_product_qrcode/static/description/assets/misc/features.png new file mode 100644 index 000000000..b41769f77 Binary files /dev/null and b/customer_product_qrcode/static/description/assets/misc/features.png differ diff --git a/customer_product_qrcode/static/description/assets/misc/logo.png b/customer_product_qrcode/static/description/assets/misc/logo.png new file mode 100644 index 000000000..478462d3e Binary files /dev/null and b/customer_product_qrcode/static/description/assets/misc/logo.png differ diff --git a/customer_product_qrcode/static/description/assets/misc/pictures.png b/customer_product_qrcode/static/description/assets/misc/pictures.png new file mode 100644 index 000000000..56d255fe9 Binary files /dev/null and b/customer_product_qrcode/static/description/assets/misc/pictures.png differ diff --git a/customer_product_qrcode/static/description/assets/misc/pie-chart.png b/customer_product_qrcode/static/description/assets/misc/pie-chart.png new file mode 100644 index 000000000..426e05244 Binary files /dev/null and b/customer_product_qrcode/static/description/assets/misc/pie-chart.png differ diff --git a/customer_product_qrcode/static/description/assets/misc/right-arrow.png b/customer_product_qrcode/static/description/assets/misc/right-arrow.png new file mode 100644 index 000000000..730984a06 Binary files /dev/null and b/customer_product_qrcode/static/description/assets/misc/right-arrow.png differ diff --git a/customer_product_qrcode/static/description/assets/misc/star.png b/customer_product_qrcode/static/description/assets/misc/star.png new file mode 100644 index 000000000..2eb9ab29f Binary files /dev/null and b/customer_product_qrcode/static/description/assets/misc/star.png differ diff --git a/customer_product_qrcode/static/description/assets/misc/support.png b/customer_product_qrcode/static/description/assets/misc/support.png new file mode 100644 index 000000000..4f18b8b82 Binary files /dev/null and b/customer_product_qrcode/static/description/assets/misc/support.png differ diff --git a/customer_product_qrcode/static/description/assets/misc/whatsapp.png b/customer_product_qrcode/static/description/assets/misc/whatsapp.png new file mode 100644 index 000000000..d513a5356 Binary files /dev/null and b/customer_product_qrcode/static/description/assets/misc/whatsapp.png differ diff --git a/customer_product_qrcode/static/description/assets/modules/budget_image.png b/customer_product_qrcode/static/description/assets/modules/budget_image.png new file mode 100644 index 000000000..b50130c7d Binary files /dev/null and b/customer_product_qrcode/static/description/assets/modules/budget_image.png differ diff --git a/customer_product_qrcode/static/description/assets/modules/credit_image.png b/customer_product_qrcode/static/description/assets/modules/credit_image.png new file mode 100644 index 000000000..3ad04ecfd Binary files /dev/null and b/customer_product_qrcode/static/description/assets/modules/credit_image.png differ diff --git a/customer_product_qrcode/static/description/assets/modules/employee_image.png b/customer_product_qrcode/static/description/assets/modules/employee_image.png new file mode 100644 index 000000000..30ad58232 Binary files /dev/null and b/customer_product_qrcode/static/description/assets/modules/employee_image.png differ diff --git a/customer_product_qrcode/static/description/assets/modules/export_image.png b/customer_product_qrcode/static/description/assets/modules/export_image.png new file mode 100644 index 000000000..492980ad0 Binary files /dev/null and b/customer_product_qrcode/static/description/assets/modules/export_image.png differ diff --git a/customer_product_qrcode/static/description/assets/modules/gantt_image.png b/customer_product_qrcode/static/description/assets/modules/gantt_image.png new file mode 100644 index 000000000..1ae7cfe3b Binary files /dev/null and b/customer_product_qrcode/static/description/assets/modules/gantt_image.png differ diff --git a/customer_product_qrcode/static/description/assets/modules/quotation_image.png b/customer_product_qrcode/static/description/assets/modules/quotation_image.png new file mode 100644 index 000000000..499b1a72f Binary files /dev/null and b/customer_product_qrcode/static/description/assets/modules/quotation_image.png differ diff --git a/customer_product_qrcode/static/description/assets/screenshots/hero.gif b/customer_product_qrcode/static/description/assets/screenshots/hero.gif new file mode 100644 index 000000000..d2efd6ef1 Binary files /dev/null and b/customer_product_qrcode/static/description/assets/screenshots/hero.gif differ diff --git a/customer_product_qrcode/static/description/assets/screenshots/q1.png b/customer_product_qrcode/static/description/assets/screenshots/q1.png new file mode 100644 index 000000000..e516ebf9a Binary files /dev/null and b/customer_product_qrcode/static/description/assets/screenshots/q1.png differ diff --git a/customer_product_qrcode/static/description/assets/screenshots/q2.png b/customer_product_qrcode/static/description/assets/screenshots/q2.png new file mode 100644 index 000000000..f6a7fff33 Binary files /dev/null and b/customer_product_qrcode/static/description/assets/screenshots/q2.png differ diff --git a/customer_product_qrcode/static/description/assets/screenshots/q3.png b/customer_product_qrcode/static/description/assets/screenshots/q3.png new file mode 100644 index 000000000..1b909cdfb Binary files /dev/null and b/customer_product_qrcode/static/description/assets/screenshots/q3.png differ diff --git a/customer_product_qrcode/static/description/assets/screenshots/q4.png b/customer_product_qrcode/static/description/assets/screenshots/q4.png new file mode 100644 index 000000000..075104fc3 Binary files /dev/null and b/customer_product_qrcode/static/description/assets/screenshots/q4.png differ diff --git a/customer_product_qrcode/static/description/banner.png b/customer_product_qrcode/static/description/banner.png new file mode 100644 index 000000000..c1f30354a Binary files /dev/null and b/customer_product_qrcode/static/description/banner.png differ diff --git a/customer_product_qrcode/static/description/icon.png b/customer_product_qrcode/static/description/icon.png new file mode 100644 index 000000000..a8e301cc9 Binary files /dev/null and b/customer_product_qrcode/static/description/icon.png differ diff --git a/customer_product_qrcode/static/description/index.html b/customer_product_qrcode/static/description/index.html new file mode 100644 index 000000000..b05e04bae --- /dev/null +++ b/customer_product_qrcode/static/description/index.html @@ -0,0 +1,573 @@ +
+ +
+ +
+
+ Community +
+
+ Enterprise +
+
+ Odoo.sh +
+
+
+ + + +

Customer + and Product QR Code Generator

+

Generate Unique QR Codes for + Customers and Products.

+ + + +
+ + +
+
+ +
+

Explore This + Module

+
+ + + + +
+
+ +
+

Overview +

+
+
+
+ If QR codes aren't the part of your current marketing strategy, + you might be missing the large chunks of benefits. Use QR codes + to generate customer interest, drive traffic, and increase sales + via print, online, or email. The Customer and Product QR Code + Generator allows the users to scan QR codes simply and easily + from within your browser. + This module helps to set up a unique QR code to both your + products and customers. +
+
+ + + +
+
+ +
+

Features +

+
+
+
+
+ + Community & Enterprise Support. +
Available in Odoo 14.0 Community and Enterprise.
+
+
+ + Enables to configure a word prefix to QR code for unique identification. +
+
+ + QR code for whole product template variants. +
+
+ + Unique QR code for products and customers. +
+
+ + QR code for individual product variants.. +
+
+
+ + + +
+
+ +
+

Screenshots +

+
+
+
+ +
+

Product and customer + prefix

+

Set the product and + customer prefixes from General Settings Menu. + Set a Unique and Denotable Prefix to Your Customers.

+ +
+ +
+

Generate QR + button

+

Goto The Customer or + Product Form.Click the Generate QR Button. + The QR Sequence will be generated and the QR Code will be printed as a PDF.

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

Generated QR + Code

+

Each Customer or + Product will have a unique qr sequence. Simply go to scan from menu bar + and grant access to your device camera, you’re ready to scan a QR code using your + laptop or mobile devices.

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

Related + 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

+
+
+
+
+
+
+
+ +
+
+
+ \ No newline at end of file diff --git a/customer_product_qrcode/views/view.xml b/customer_product_qrcode/views/view.xml new file mode 100755 index 000000000..b7a10c6aa --- /dev/null +++ b/customer_product_qrcode/views/view.xml @@ -0,0 +1,105 @@ + + + + + res.partner.form.qr.inherit + res.partner + + +
+ +
+ + + + +
+ + product.product.form.qr.inherit + product.product + + +
+ +
+ + + + +
+ + product.template.form.qr.inherit + product.template + + +
+ + +
+
+
+ + res.config.inherit.qr + res.config.settings + + + +
+

Setup QRCode

+
+
+
+
+
+
+
+
+
+
+
+ + + customer_sequence + res.partner + + 5 + + + + + product_sequence + product.product + + 5 + + +
\ No newline at end of file diff --git a/dashboard_pos/README.rst b/dashboard_pos/README.rst new file mode 100644 index 000000000..fde32b476 --- /dev/null +++ b/dashboard_pos/README.rst @@ -0,0 +1,21 @@ +POS Dashboard v16 +================= +POS Dashboard + +Installation +============ + - www.odoo.com/documentation/16.0/setup/install.html + - Install our custom addon + +Configuration +============= + + No additional configurations needed + +Credits +======= +Developer: Irfan v13 @ cybrosys, Contact: odoo@cybrosys.com + Jibin James V14 @ cybrosys, Contact: odoo@cybrosys.com + Irfan V15 @ cybrosys, Contact: odoo@cybrosys.com + Amaya Aravind EV V16 @ cybrosys, Contact: odoo@cybrosys.com + diff --git a/dashboard_pos/__init__.py b/dashboard_pos/__init__.py new file mode 100644 index 000000000..6f1457fa4 --- /dev/null +++ b/dashboard_pos/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +################################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2022-TODAY Cybrosys Technologies (). +# Author: Irfan () +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################### + +from . import models diff --git a/dashboard_pos/__manifest__.py b/dashboard_pos/__manifest__.py new file mode 100644 index 000000000..bcc063dfb --- /dev/null +++ b/dashboard_pos/__manifest__.py @@ -0,0 +1,53 @@ +# -*- coding: utf-8 -*- +################################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2022-TODAY Cybrosys Technologies (). +# Author: Irfan () +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################### +{ + 'name': "POS Dashboard", + 'version': '16.0.1.0.0', + 'summary': """POS Dashboard""", + 'description': """POS Dashboard""", + 'category': 'Point of Sale', + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'website': "https://www.cybrosys.com", + 'depends': ['hr', 'point_of_sale'], + 'external_dependencies': { + 'python': ['pandas'], + }, + 'data': [ + 'views/dashboard_views.xml' + ], + 'assets': { + 'web.assets_backend': [ + 'dashboard_pos/static/src/js/pos_dashboard.js', + 'dashboard_pos/static/src/css/pos_dashboard.css', + 'https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.js', + ], + 'web.assets_qweb': [ + 'dashboard_pos/static/src/xml/pos_dashboard.xml', + ], + }, + 'images': ['static/description/banner.png'], + 'license': "AGPL-3", + 'installable': True, + 'application': False, +} \ No newline at end of file diff --git a/dashboard_pos/doc/RELEASE_NOTES.md b/dashboard_pos/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..f7f38a236 --- /dev/null +++ b/dashboard_pos/doc/RELEASE_NOTES.md @@ -0,0 +1,7 @@ +## Module + +#### 09.10.2021 +#### Version 16.0.1.0.0 + +##### Initial Commit for pos_dashboard + diff --git a/dashboard_pos/models/__init__.py b/dashboard_pos/models/__init__.py new file mode 100644 index 000000000..aa6375645 --- /dev/null +++ b/dashboard_pos/models/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +################################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2022-TODAY Cybrosys Technologies (). +# Author: Irfan () +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################### + +from . import pos_dashboard diff --git a/dashboard_pos/models/pos_dashboard.py b/dashboard_pos/models/pos_dashboard.py new file mode 100644 index 000000000..ccf5f127b --- /dev/null +++ b/dashboard_pos/models/pos_dashboard.py @@ -0,0 +1,231 @@ +# -*- coding: utf-8 -*- +################################################################################### +# +# Cybrosys Technologies Pvt. Ltd. +# Copyright (C) 2022-TODAY Cybrosys Technologies (). +# Author: Irfan () +# +# This program is free software: you can modify +# it under the terms of the GNU Affero General Public License (AGPL) as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +################################################################################### +import pytz +from odoo import models, fields, api +from datetime import timedelta, datetime, date + + +class PosDashboard(models.Model): + _inherit = 'pos.order' + + @api.model + def get_department(self, option): + company_id = self.env.company.id + if option == 'pos_hourly_sales': + + user_tz = self.env.user.tz if self.env.user.tz else pytz.UTC + query = '''select EXTRACT(hour FROM date_order at time zone 'utc' at time zone '{}') + as date_month,sum(amount_total) from pos_order where + EXTRACT(month FROM date_order::date) = EXTRACT(month FROM CURRENT_DATE) + AND pos_order.company_id = ''' + str( + company_id) + ''' group by date_month ''' + query = query.format(user_tz) + label = 'HOURS' + elif option == 'pos_monthly_sales': + query = '''select date_order::date as date_month,sum(amount_total) from pos_order where + EXTRACT(month FROM date_order::date) = EXTRACT(month FROM CURRENT_DATE) AND pos_order.company_id = ''' + str( + company_id) + ''' group by date_month ''' + label = 'DAYS' + else: + query = '''select TO_CHAR(date_order,'MON')date_month,sum(amount_total) from pos_order where + EXTRACT(year FROM date_order::date) = EXTRACT(year FROM CURRENT_DATE) AND pos_order.company_id = ''' + str( + company_id) + ''' group by date_month''' + label = 'MONTHS' + + self._cr.execute(query) + docs = self._cr.dictfetchall() + order = [] + for record in docs: + order.append(record.get('sum')) + today = [] + for record in docs: + today.append(record.get('date_month')) + final = [order, today, label] + return final + + @api.model + def get_details(self): + company_id = self.env.company.id + cr = self._cr + cr.execute( + """select pos_payment_method.name,sum(amount) from pos_payment inner join pos_payment_method on + pos_payment_method.id=pos_payment.payment_method_id group by pos_payment_method.name ORDER + BY sum(amount) DESC; """) + payment_details = cr.fetchall() + cr.execute( + '''select hr_employee.name,sum(pos_order.amount_paid) as total,count(pos_order.amount_paid) as orders + from pos_order inner join hr_employee on pos_order.user_id = hr_employee.user_id + where pos_order.company_id =''' + str( + company_id) + '''GROUP BY hr_employee.name order by total DESC;''') + salesperson = cr.fetchall() + total_sales = [] + for rec in salesperson: + rec = list(rec) + sym_id = rec[1] + company = self.env.company + if company.currency_id.position == 'after': + rec[1] = "%s %s" % (sym_id, company.currency_id.symbol) + else: + rec[1] = "%s %s" % (company.currency_id.symbol, sym_id) + rec = tuple(rec) + total_sales.append(rec) + cr.execute( + '''select DISTINCT(product_template.name) as product_name,sum(qty) as total_quantity from + pos_order_line inner join product_product on product_product.id=pos_order_line.product_id inner join + product_template on product_product.product_tmpl_id = product_template.id where pos_order_line.company_id =''' + str( + company_id) + ''' group by product_template.id ORDER + BY total_quantity DESC Limit 10 ''') + selling_product = cr.fetchall() + sessions = self.env['pos.config'].search([]) + sessions_list = [] + dict = { + 'opened': 'Opened', + 'opening_control': "Opening Control" + } + for session in sessions: + st = dict.get(session.pos_session_state) + if st == None: + sessions_list.append({ + 'session': session.name, + 'status': 'Closed' + }) + else: + sessions_list.append({ + 'session': session.name, + 'status': dict.get(session.pos_session_state) + }) + + payments = [] + for rec in payment_details: + rec = list(rec) + sym_id = rec[1] + company = self.env.company + if company.currency_id.position == 'after': + rec[1] = "%s %s" % (sym_id, company.currency_id.symbol) + else: + rec[1] = "%s %s" % (company.currency_id.symbol, sym_id) + rec = tuple(rec) + payments.append(rec) + return { + 'payment_details': payments, + 'salesperson': total_sales, + 'selling_product': sessions_list, + } + + @api.model + def get_refund_details(self): + default_date = datetime.today().date() + pos_order = self.env['pos.order'].search([]) + total = 0 + today_refund_total = 0 + total_order_count = 0 + total_refund_count = 0 + today_sale = 0 + a = 0 + for rec in pos_order: + if rec.amount_total < 0.0 and rec.date_order.date() == default_date: + today_refund_total = today_refund_total + 1 + total_sales = rec.amount_total + total = total + total_sales + total_order_count = total_order_count + 1 + if rec.date_order.date() == default_date: + today_sale = today_sale + 1 + if rec.amount_total < 0.0: + total_refund_count = total_refund_count + 1 + magnitude = 0 + while abs(total) >= 1000: + magnitude += 1 + total /= 1000.0 + # add more suffixes if you need them + val = '%.2f%s' % (total, ['', 'K', 'M', 'G', 'T', 'P'][magnitude]) + pos_session = self.env['pos.session'].search([]) + total_session = 0 + for record in pos_session: + total_session = total_session + 1 + return { + 'total_sale': val, + 'total_order_count': total_order_count, + 'total_refund_count': total_refund_count, + 'total_session': total_session, + 'today_refund_total': today_refund_total, + 'today_sale': today_sale, + } + + @api.model + def get_the_top_customer(self, ): + company_id = self.env.company.id + query = '''select res_partner.name as customer,pos_order.partner_id,sum(pos_order.amount_paid) as amount_total from pos_order + inner join res_partner on res_partner.id = pos_order.partner_id where pos_order.company_id = ''' + str( + company_id) + ''' GROUP BY pos_order.partner_id, + res_partner.name ORDER BY amount_total DESC LIMIT 10;''' + self._cr.execute(query) + docs = self._cr.dictfetchall() + + order = [] + for record in docs: + order.append(record.get('amount_total')) + day = [] + for record in docs: + day.append(record.get('customer')) + final = [order, day] + return final + + @api.model + def get_the_top_products(self): + company_id = self.env.company.id + + query = '''select DISTINCT(product_template.name) as product_name,sum(qty) as total_quantity from + pos_order_line inner join product_product on product_product.id=pos_order_line.product_id inner join + product_template on product_product.product_tmpl_id = product_template.id where pos_order_line.company_id = ''' + str( + company_id) + ''' group by product_template.id ORDER + BY total_quantity DESC Limit 10 ''' + + self._cr.execute(query) + top_product = self._cr.dictfetchall() + + total_quantity = [] + for record in top_product: + total_quantity.append(record.get('total_quantity')) + product_name = [] + for record in top_product: + product_name.append(record.get('product_name')) + final = [total_quantity, product_name] + return final + + @api.model + def get_the_top_categories(self): + company_id = self.env.company.id + query = '''select DISTINCT(product_category.complete_name) as product_category,sum(qty) as total_quantity + from pos_order_line inner join product_product on product_product.id=pos_order_line.product_id inner join + product_template on product_product.product_tmpl_id = product_template.id inner join product_category on + product_category.id =product_template.categ_id where pos_order_line.company_id = ''' + str( + company_id) + ''' group by product_category ORDER BY total_quantity DESC ''' + self._cr.execute(query) + top_product = self._cr.dictfetchall() + total_quantity = [] + for record in top_product: + total_quantity.append(record.get('total_quantity')) + product_categ = [] + for record in top_product: + product_categ.append(record.get('product_category')) + final = [total_quantity, product_categ] + return final diff --git a/dashboard_pos/static/description/assets/icons/check.png b/dashboard_pos/static/description/assets/icons/check.png new file mode 100644 index 000000000..c8e85f51d Binary files /dev/null and b/dashboard_pos/static/description/assets/icons/check.png differ diff --git a/dashboard_pos/static/description/assets/icons/chevron.png b/dashboard_pos/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..2089293d6 Binary files /dev/null and b/dashboard_pos/static/description/assets/icons/chevron.png differ diff --git a/dashboard_pos/static/description/assets/icons/cogs.png b/dashboard_pos/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/dashboard_pos/static/description/assets/icons/cogs.png differ diff --git a/dashboard_pos/static/description/assets/icons/consultation.png b/dashboard_pos/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/dashboard_pos/static/description/assets/icons/consultation.png differ diff --git a/dashboard_pos/static/description/assets/icons/ecom-black.png b/dashboard_pos/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/dashboard_pos/static/description/assets/icons/ecom-black.png differ diff --git a/dashboard_pos/static/description/assets/icons/education-black.png b/dashboard_pos/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/dashboard_pos/static/description/assets/icons/education-black.png differ diff --git a/dashboard_pos/static/description/assets/icons/hotel-black.png b/dashboard_pos/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/dashboard_pos/static/description/assets/icons/hotel-black.png differ diff --git a/dashboard_pos/static/description/assets/icons/license.png b/dashboard_pos/static/description/assets/icons/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/dashboard_pos/static/description/assets/icons/license.png differ diff --git a/dashboard_pos/static/description/assets/icons/lifebuoy.png b/dashboard_pos/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/dashboard_pos/static/description/assets/icons/lifebuoy.png differ diff --git a/dashboard_pos/static/description/assets/icons/manufacturing-black.png b/dashboard_pos/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/dashboard_pos/static/description/assets/icons/manufacturing-black.png differ diff --git a/dashboard_pos/static/description/assets/icons/pos-black.png b/dashboard_pos/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/dashboard_pos/static/description/assets/icons/pos-black.png differ diff --git a/dashboard_pos/static/description/assets/icons/puzzle.png b/dashboard_pos/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/dashboard_pos/static/description/assets/icons/puzzle.png differ diff --git a/dashboard_pos/static/description/assets/icons/restaurant-black.png b/dashboard_pos/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/dashboard_pos/static/description/assets/icons/restaurant-black.png differ diff --git a/dashboard_pos/static/description/assets/icons/service-black.png b/dashboard_pos/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/dashboard_pos/static/description/assets/icons/service-black.png differ diff --git a/dashboard_pos/static/description/assets/icons/trading-black.png b/dashboard_pos/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/dashboard_pos/static/description/assets/icons/trading-black.png differ diff --git a/dashboard_pos/static/description/assets/icons/training.png b/dashboard_pos/static/description/assets/icons/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/dashboard_pos/static/description/assets/icons/training.png differ diff --git a/dashboard_pos/static/description/assets/icons/update.png b/dashboard_pos/static/description/assets/icons/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/dashboard_pos/static/description/assets/icons/update.png differ diff --git a/dashboard_pos/static/description/assets/icons/user.png b/dashboard_pos/static/description/assets/icons/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/dashboard_pos/static/description/assets/icons/user.png differ diff --git a/dashboard_pos/static/description/assets/icons/wrench.png b/dashboard_pos/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/dashboard_pos/static/description/assets/icons/wrench.png differ diff --git a/dashboard_pos/static/description/assets/misc/categories.png b/dashboard_pos/static/description/assets/misc/categories.png new file mode 100644 index 000000000..bedf1e0b1 Binary files /dev/null and b/dashboard_pos/static/description/assets/misc/categories.png differ diff --git a/dashboard_pos/static/description/assets/misc/check-box.png b/dashboard_pos/static/description/assets/misc/check-box.png new file mode 100644 index 000000000..42caf24b9 Binary files /dev/null and b/dashboard_pos/static/description/assets/misc/check-box.png differ diff --git a/dashboard_pos/static/description/assets/misc/compass.png b/dashboard_pos/static/description/assets/misc/compass.png new file mode 100644 index 000000000..d5fed8faa Binary files /dev/null and b/dashboard_pos/static/description/assets/misc/compass.png differ diff --git a/dashboard_pos/static/description/assets/misc/corporate.png b/dashboard_pos/static/description/assets/misc/corporate.png new file mode 100644 index 000000000..2eb13edbf Binary files /dev/null and b/dashboard_pos/static/description/assets/misc/corporate.png differ diff --git a/dashboard_pos/static/description/assets/misc/customer-support.png b/dashboard_pos/static/description/assets/misc/customer-support.png new file mode 100644 index 000000000..79efc72ed Binary files /dev/null and b/dashboard_pos/static/description/assets/misc/customer-support.png differ diff --git a/dashboard_pos/static/description/assets/misc/cybrosys-logo.png b/dashboard_pos/static/description/assets/misc/cybrosys-logo.png new file mode 100644 index 000000000..cc3cc0ccf Binary files /dev/null and b/dashboard_pos/static/description/assets/misc/cybrosys-logo.png differ diff --git a/dashboard_pos/static/description/assets/misc/features.png b/dashboard_pos/static/description/assets/misc/features.png new file mode 100644 index 000000000..b41769f77 Binary files /dev/null and b/dashboard_pos/static/description/assets/misc/features.png differ diff --git a/dashboard_pos/static/description/assets/misc/logo.png b/dashboard_pos/static/description/assets/misc/logo.png new file mode 100644 index 000000000..478462d3e Binary files /dev/null and b/dashboard_pos/static/description/assets/misc/logo.png differ diff --git a/dashboard_pos/static/description/assets/misc/pictures.png b/dashboard_pos/static/description/assets/misc/pictures.png new file mode 100644 index 000000000..56d255fe9 Binary files /dev/null and b/dashboard_pos/static/description/assets/misc/pictures.png differ diff --git a/dashboard_pos/static/description/assets/misc/pie-chart.png b/dashboard_pos/static/description/assets/misc/pie-chart.png new file mode 100644 index 000000000..426e05244 Binary files /dev/null and b/dashboard_pos/static/description/assets/misc/pie-chart.png differ diff --git a/dashboard_pos/static/description/assets/misc/right-arrow.png b/dashboard_pos/static/description/assets/misc/right-arrow.png new file mode 100644 index 000000000..730984a06 Binary files /dev/null and b/dashboard_pos/static/description/assets/misc/right-arrow.png differ diff --git a/dashboard_pos/static/description/assets/misc/star.png b/dashboard_pos/static/description/assets/misc/star.png new file mode 100644 index 000000000..2eb9ab29f Binary files /dev/null and b/dashboard_pos/static/description/assets/misc/star.png differ diff --git a/dashboard_pos/static/description/assets/misc/support.png b/dashboard_pos/static/description/assets/misc/support.png new file mode 100644 index 000000000..4f18b8b82 Binary files /dev/null and b/dashboard_pos/static/description/assets/misc/support.png differ diff --git a/dashboard_pos/static/description/assets/misc/whatsapp.png b/dashboard_pos/static/description/assets/misc/whatsapp.png new file mode 100644 index 000000000..d513a5356 Binary files /dev/null and b/dashboard_pos/static/description/assets/misc/whatsapp.png differ diff --git a/dashboard_pos/static/description/assets/modules/1.png b/dashboard_pos/static/description/assets/modules/1.png new file mode 100644 index 000000000..5238bdeab Binary files /dev/null and b/dashboard_pos/static/description/assets/modules/1.png differ diff --git a/dashboard_pos/static/description/assets/modules/2.png b/dashboard_pos/static/description/assets/modules/2.png new file mode 100644 index 000000000..1ae7cfe3b Binary files /dev/null and b/dashboard_pos/static/description/assets/modules/2.png differ diff --git a/dashboard_pos/static/description/assets/modules/3.png b/dashboard_pos/static/description/assets/modules/3.png new file mode 100644 index 000000000..3c3ff1afb Binary files /dev/null and b/dashboard_pos/static/description/assets/modules/3.png differ diff --git a/dashboard_pos/static/description/assets/modules/4.png b/dashboard_pos/static/description/assets/modules/4.png new file mode 100644 index 000000000..3fae4631e Binary files /dev/null and b/dashboard_pos/static/description/assets/modules/4.png differ diff --git a/dashboard_pos/static/description/assets/modules/5.gif b/dashboard_pos/static/description/assets/modules/5.gif new file mode 100644 index 000000000..2a5f8e659 Binary files /dev/null and b/dashboard_pos/static/description/assets/modules/5.gif differ diff --git a/dashboard_pos/static/description/assets/modules/6.png b/dashboard_pos/static/description/assets/modules/6.png new file mode 100644 index 000000000..7f2815273 Binary files /dev/null and b/dashboard_pos/static/description/assets/modules/6.png differ diff --git a/dashboard_pos/static/description/assets/screenshots/1.png b/dashboard_pos/static/description/assets/screenshots/1.png new file mode 100644 index 000000000..6098706d7 Binary files /dev/null and b/dashboard_pos/static/description/assets/screenshots/1.png differ diff --git a/dashboard_pos/static/description/assets/screenshots/2.png b/dashboard_pos/static/description/assets/screenshots/2.png new file mode 100644 index 000000000..ebed5d1ce Binary files /dev/null and b/dashboard_pos/static/description/assets/screenshots/2.png differ diff --git a/dashboard_pos/static/description/assets/screenshots/3.png b/dashboard_pos/static/description/assets/screenshots/3.png new file mode 100644 index 000000000..1f1076f43 Binary files /dev/null and b/dashboard_pos/static/description/assets/screenshots/3.png differ diff --git a/dashboard_pos/static/description/assets/screenshots/4.png b/dashboard_pos/static/description/assets/screenshots/4.png new file mode 100644 index 000000000..fc0ad6d54 Binary files /dev/null and b/dashboard_pos/static/description/assets/screenshots/4.png differ diff --git a/dashboard_pos/static/description/assets/screenshots/hero.gif b/dashboard_pos/static/description/assets/screenshots/hero.gif new file mode 100644 index 000000000..3b1077fe8 Binary files /dev/null and b/dashboard_pos/static/description/assets/screenshots/hero.gif differ diff --git a/dashboard_pos/static/description/banner.png b/dashboard_pos/static/description/banner.png new file mode 100644 index 000000000..17c14989e Binary files /dev/null and b/dashboard_pos/static/description/banner.png differ diff --git a/dashboard_pos/static/description/icon.png b/dashboard_pos/static/description/icon.png new file mode 100644 index 000000000..29791a88b Binary files /dev/null and b/dashboard_pos/static/description/icon.png differ diff --git a/dashboard_pos/static/description/index.html b/dashboard_pos/static/description/index.html new file mode 100644 index 000000000..3b9dd8c2e --- /dev/null +++ b/dashboard_pos/static/description/index.html @@ -0,0 +1,554 @@ +
+ +
+ +
+
+ Community +
+
+ Enterprise +
+
+ Odoo.sh +
+
+
+ + + +

POS Dashboard

+

Detailed Dashboard View for POS.

+ + + +
+ + +
+
+ +
+

Explore This + Module

+
+ + + + +
+
+ +
+

Overview +

+
+
+
+ This module helps you to see the Overview of POS, here You can see the total orders, sessions, top + customers, top products etc. +
+
+ + + +
+
+ +
+

Features +

+
+
+
+
+ + Total POS Orders. +
+
+ + Session Details. +
+
+ + Refund Details. +
+
+ + Sale Details. +
+
+ + Sale Report Charts. +
+
+ + Top products. +
+
+
+ + + +
+
+ +
+

Screenshots +

+
+
+
+ +
+

Open POS

+ +
+ +
+

Order and Session details.

+

Order and Session counts are displayed in the dashboard.

+ +
+ +
+

Details in Charts

+

Possible to see the POS details in different charts.

+ +
+ +
+

Bank, session & salesperson details

+

Details like bank, session status, salesperson details are listed.

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

Related + 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

+
+
+
+
+
+
+
+ +
+
+
+ \ No newline at end of file diff --git a/dashboard_pos/static/src/css/pos_dashboard.css b/dashboard_pos/static/src/css/pos_dashboard.css new file mode 100644 index 000000000..ec1b234cc --- /dev/null +++ b/dashboard_pos/static/src/css/pos_dashboard.css @@ -0,0 +1,1009 @@ +.oh_dashboards{ + padding-top :15px; + background-color: #f8faff !important; +} + +.oh-card h4 { + font-size: 1.1rem; +} +.breadcrumbs { + margin-top: 0; +} + +.buttons button { + margin: 2px 0; } + +/* Button Reset */ +.btn, .button { + display: inline-block; + font-weight: 400; + text-align: center; + white-space: nowrap; + vertical-align: middle; + transition: all .15s ease-in-out; + border-radius: 0; + cursor: pointer; } + + +/* 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); +} +.hr_birthday { + font-size: 28px; + text-align: center; + padding: 20px 0; + color: #00438b; + font-weight: 600; +} +body .text-color { + color: #00438b; +} +.slice { + stroke: #fff; + stroke-width: 0px; +} + +/* Leave graph */ + +path { stroke: #fff; } +path:hover { opacity:0.9; } +rect:hover { fill:#934da5; } +.axis { font: 10px sans-serif; } +.legend tr{ border-bottom:1px solid grey; } +.legend tr:first-child{ border-top:1px solid grey; } + +.axis path, +.axis line { + fill: none; + stroke: #000; + shape-rendering: crispEdges; +} + +.x.axis path { display: none; } +.legend{ + border-collapse: collapse; + border-spacing: 0px; + display: inline-block; +} +.legend td, .legend .legend_col{ + padding:4px 5px; + vertical-align:bottom; +} +.legendFreq, .legendPerc{ + align:right; + width:50px; +} + +/* Leave broadfactor graph */ + +.broad_factor_graph .axis path, +.broad_factor_graph .axis line { + fill: none; + stroke: black; + shape-rendering: crispEdges; +} +.broad_factor_graph .axis text { + font-family: sans-serif; + font-size: 11px; +} + +.broad_factor_graph rect { + -moz-transition: all 0.3s; + -webkit-transition: all 0.3s; + -o-transition: all 0.3s; + transition: all 0.3s; +} +.broad_factor_graph rect:hover{ + fill: #ff618a; +} + +#broad_factor_pdf { + background-color: #ffffff; + border: 0; + color : #000000; + float: right; +} +#broad_factor_pdf i { + color: red; +} + +.leave_broad_factor{ + overflow-x: auto !important; + overflow-y: hidden !important; + height: auto; +} + +/*=====================New Dashboard===========================*/ + +.oh_dashboards { + background-color: #f8faff !important; + padding: 0px !important; + +} +.container-fluid.o_pos_dashboard { + padding: 0px !important; +} +.employee-prof { + + padding: 0px; + height: 100%; + background-color: #3e6282; + /*background-image: linear-gradient(180deg, #3e6282, #41666f);*/ + position: fixed; + z-index: 999; +} +.employee-prof .oh-card:hover { + + transform:none !important; + box-shadow: none !important; + +} + +/*.dummy{ + height:130vh; +}*/ +.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; + +} +.employee-prof .employee-icon { + + float: left; + padding-right: 0px; + width: 100%; + height: 185px; + overflow: hidden; + background: #fff; + +} +.employee-prof .employee-icon img{ + width: 100%; + background: #fff; +} + +.employee-prof .employee-name h2 { + + text-align: center; + font-weight: 300; + text-transform: uppercase; + font-size: 17px; + margin-top: 12px; + margin-bottom: 2px; + color: #fff; + +} +.media-body.employee-name { + + background: #466b8d; + float: left; + margin: 0; + width: 100% + +} +.employee-prof .employee-name p { + + margin: 0 0 9px; + text-align: center; + font-size: 12px; + color: #f3f3f3; + +} +.employee-prof p { + margin: 0 0 9px; + color: #fff; +} +.employee-gender { + width: 40%; + margin-left: 10%; + padding: 8% 10% 4%; + text-align: center; + border-right: 1px solid #4d769b; + margin-top: 14%; + float: left; + border-bottom: 1px solid #4d769b; +} +.employee-gender p { + margin: 0px 0 4px !important; + color: #fff; +} +.employee-age { + width: 40%; + margin-right: 10%; + padding: 4% 10% 7%; + text-align: center; + margin-top: 18%; + float: left; + border-bottom: 1px solid #4d769b; +} +.employee-age p { + margin: 0 0 1px; + color: #fff; +} +.employee-experience { + + width: 100%; + text-align: center; + padding-top: 8%; + float: left; + padding-bottom: 3%; + +} +.employee-country { + width: 40%; + margin-left: 10%; + padding: 9% 0% 4%; + text-align: center; + border-right: 1px solid #4d769b; + margin-top: 2%; + float: left; + border-top: 1px solid #4d769b; + +} +.employee-country p { + margin: 0px 0 1px !important; + color: #fff; +} +.employee-mobile { + width: 40%; + margin-right: 10%; + padding: 9% 0% 7%; + text-align: center; + margin-top: 2%; + float: left; + border-top: 1px solid #4d769b; +} +.employee-mobile p { + margin: 0 0 1px; + color: #fff; +} +.oh-payslip { + + margin-top: 4.5%; + +} +.oh-payslip .stat-icon { + + width: 30%; + height: 85px; + text-align: center; + background: #ff8762; + color: #fff; + width: 32%; + padding-top: 2%; + font-size: xxx-large; + +} +.oh-payslip .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-payslip .stat-icon { + + width: 30%; + height: 85px; + text-align: center; + padding-top: 2%; + +} +.oh-timesheets .stat-icon{ + background: #5ebade !important; +} +.oh-contracts .stat-icon{ + background: #b298e1 !important; +} +.oh-broad-factor .stat-icon{ + background: #70cac1 !important; +} +.oh-timesheets .stat-widget-one .stat-text { + color: #5ebade; +} +.oh-contracts .stat-widget-one .stat-text { + color: #b298e1; +} +.oh-broad-factor .stat-widget-one .stat-text { + color: #70cac1; +} +.leave-manager { + + background-color: #fff; + 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); + padding: 0px; + margin: 15px; + +} +.hr_leave_request_approve { + padding: 0; + padding-bottom: 0em; + padding-top: 0em; + transition: transform 0.2s ease, box-shadow 0.2s ease; + will-change: transform, box-shadow; +} +.leaves_request_month { + padding: 0; + padding-top: 0px; + padding-bottom: 0px; + padding-bottom: 0em; + padding-top: 0em; + transition: transform 0.2s ease, box-shadow 0.2s ease; + will-change: transform, box-shadow; + border-bottom: 1px solid #f1f1f133; +} +.leaves_request_today{ + padding: 0; + padding-bottom: 0em; + padding-top: 0em; + transition: transform 0.2s ease, box-shadow 0.2s ease; + will-change: transform, box-shadow; + +} +.hr_leave_request_approve:hover, .leaves_request_month:hover, .leaves_request_today:hover{ + transform: translateY(-2px) translateZ(0) !important; + box-shadow: 0 10px 10px 0 rgba(62, 57, 107, 0.12), 0 0 0 transparent !important; +} +.hr_leave_request_approve p { + font-size: 14px; + color: #ff8762; + margin-left: 1rem; + margin-bottom: 0px; + text-align: left; + width: 64%; + font-weight: bold; + float: left; +} +.leaves_request_today p { + font-size: 14px; + color: #5ebade; + margin-left: 1rem; + margin-bottom: 0px; + text-align: left; + width:64%; + float:left; + font-weight: bold; +} +.leaves_request_month p{ + font-size: 14px; + color: #b298e1; + margin-left: 1rem; + margin-bottom:0px; + text-align: left; + width:64%; + float:left; + font-weight: bold; +} +h4 .stat-count { + font-size: 17px; + text-align: center; + color: #000 !important; + margin-top: 0px; + width: 100%; + float: left; + margin: 0; +} +.leave-manager h4 { + float: left; + width: 23%; + +} +.hr_leave_request_approve h4 { + + padding: 5.2rem 0; + margin: 0; + background: #ff8762; + color: #fff; + +} +.leaves_request_today h4 { + + padding: 2.2rem 0; + margin: 0 !important; + background: #5ebade; + color: #fff; + +} +.leaves_request_month h4 { + + padding: 2.1rem 0; + margin: 0 !important; + background: #b298e1; + color: #fff; + +} +.leaves_request_today h4 .stat-count ,.leaves_request_month h4 .stat-count , .hr_leave_request_approve h4 .stat-count +{ + color:#fff !important; +} +.graph_view .legend { + margin-bottom: 27px; + display: inline-block; + border-collapse: collapse; + border-spacing: 0px; + margin-left: 29px; +} +.hr-chart-1{ + margin: 15px 0px; + background: #fff; + padding: 0px !important; + 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); +} +.hr-chart-1:hover{ + transform: translateY(-2px) translateZ(0) !important; + box-shadow: 0 10px 10px 0 rgba(62, 57, 107, 0.12), 0 0 0 transparent !important; +} +.stat-head { + text-align: left !important; + font-weight: 300; + font-size: 15px; + margin-bottom: 25px; + margin-left: 24px; + width: 100%; +} +.emp_graph { + padding-left: 90px; + height: auto; + padding-bottom: 65px; + text-align: center !important; +} +.hr_leave_allocations_approve p { + font-size: 14px; + color: #ff8762; + margin-left: 1rem; + margin-bottom: 0px; + text-align: left; + width: 70%; + float: left; + font-weight: bold; +} +.hr_leave_allocations_approve h4 { + + padding: 2.5rem 0; + margin: 0; + background: #ff8762; + color: #fff; + width: 26%; + float: left; +} +.hr_leave_allocations_approve .stat-count { + + font-size: 17px; + text-align: center; + color: #fff !important; + margin-top: 0px; + width: 100%; + float: left; + margin: 0; + +} +.hr_leave_allocations_approve { + + padding: 0; + padding-top: 0px; + padding-bottom: 0px; + padding-bottom: 0em; + padding-top: 0em; + box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62,57,107,0.06); + transition: transform 0.2s ease, box-shadow 0.2s ease; + will-change: transform, box-shadow; + background: #fff; + height: 80px; + +} +.hr_leave_allocations_approve:hover{ + transform: translateY(-2px) translateZ(0) !important; + box-shadow: 0 10px 10px 0 rgba(62, 57, 107, 0.12), 0 0 0 transparent !important; +} +.leave-manager { + + background-color: #fff; + 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); + padding: 0px; + margin: 15px; + margin-right: 15px; + margin-right: 0px; + width: 95% !important; + padding: 0; + +} +.hr_job_application_approve { + padding: 0; + padding-top: 0px; + padding-bottom: 0px; + padding-top: 0px; + padding-bottom: 0px; + padding-top: 0px; + padding-bottom: 0px; + padding-bottom: 0em; + padding-top: 0em; + box-shadow: 0 10px 40px 0 rgba(62,57,107,0.07), 0 2px 9px 0 rgba(62,57,107,0.06); + transition: transform 0.2s ease, box-shadow 0.2s ease; + will-change: transform, box-shadow; + background: #fff; + margin-top: 15px; + height: 80px; + +} +.hr_job_application_approve p { + font-size: 14px; + color: #70cac1; + margin-left: 1rem; + margin-bottom: 0px; + text-align: left; + width: 70%; + float: left; + font-weight: bold; +} +.hr_job_application_approve h4 { + + padding: 2.5rem 0; + margin: 0; + background: #70cac1; + color: #fff; + width: 26%; + float: left; + +} +.hr_job_application_approve .stat-count { + + font-size: 17px !important; + color: #fff !important; + margin-top: 0px !important; + width: 100%; + float: left; + margin: 0; + margin: 0px !important; + text-align: center !important; + width: 100% !important; + +} +.hr_job_application_approve:hover{ + transform: translateY(-2px) translateZ(0) !important; + box-shadow: 0 10px 10px 0 rgba(62, 57, 107, 0.12), 0 0 0 transparent !important; +} +.hr_attendance_login .oh-card { + margin: 0; + margin-bottom: 0px; + margin-bottom: 0px; + background: #134c8a; + padding-bottom: 7px; + 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); +} +.hr_attendance_login .stat-widget-one { + background: none; +} +.hr_attendance_login .stat-widget-one .stat-icon { + text-align: center; + padding-top: 9px; +} +.hr_attendance_login .stat-content { + width: 100%; + color: #fff !important; +} +.hr_attendance_login .stat-widget-one .stat-text { + margin: 0; + text-align: center; + width: 100% !important; + padding: 0; + color: #fff; +} +.hr_attendance_login .stat-widget-one .stat-icon .fa { + font-size: 50px; +} +.hr_attendance_login .stat-widget-one .stat-icon .fa { + font-size: 50px; + margin: 0px; + box-shadow: none; +} +.hr_attendance_login { + margin-top: 1.5%; +} +.monthly_leave_graph_view .oh-card { + background: #fff; + 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); + padding: 15px; +} +.broad_factor_graph .oh-card { + padding: 15px !important; + background: #fff; + 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); + padding: 15px; +} +.leave_broad_factor { + overflow-x: auto !important; + overflow-y: hidden !important; + height: 336px; + padding: 0px; + padding-left: 0px; +} +#broad_factor_pdf { + + background-color: #ffffff; + float: right; + border-radius: 30px; + 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); + border: 1px solid #4ec3b7; + color: #757575; + padding-top: 9px; + color: #4ec3b7; + +} +#broad_factor_pdf:hover{ + transform: translateY(-2px) translateZ(0) !important; + box-shadow: 0 10px 10px 0 rgba(62, 57, 107, 0.12), 0 0 0 transparent !important; +} +.hr_birthday { + font-size: 17px; + text-align: center; + padding: 20px 0; + color: #00438b; + font-weight: 300; +} +.hr_notification img { + width: 40px; + height: 40px; + border-radius: 100%; +} +.hr_notification { + background: #fff; + 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; +} +.hr_notification_head { + font-size: 17px; + text-align: center; + padding: 12px 0; + color: #fff; + font-weight: 300; + background: #de6a5e; + margin-bottom: 9px; +} +.monthly_leave_trend .oh-card{ + background: #fff; + transition: none !important; + will-change: none !important; + box-shadow: none !important; + margin-bottom: 5px; +} + +.monthly_leave_trend path { + stroke: #70cac1; + stroke-width: 2; + fill: none; +} + +.monthly_leave_trend .axis path, +.monthly_leave_trend .axis line { + fill: none; + stroke: grey; + stroke-width: 1; + shape-rendering: crispEdges; +} +.monthly_leave_trend circle{ + fill: #ffffff; + stroke: #44b7ac; + stroke-width: 1.5; +} +.hr-chart-1 { + margin: 15px 0px; + background: #fff; + padding: 0px !important; + padding-top: 0px; + 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); + padding-top: 3px !important; +} +.monthly_leave_trend { + background: #fff; + 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); +} +.monthly_leave_trend:hover{ + transform: translateY(-2px) translateZ(0) !important; + box-shadow: 0 10px 10px 0 rgba(62, 57, 107, 0.12), 0 0 0 transparent !important; +} + + +/*----------------------*/ +.monthly_join_resign_trend{ + padding-right: 0px !important; +} + +.monthly_join_resign_trend .oh-card { + background: #fff; + 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); + padding: 15px; +} + +.monthly_join_resign_trend .axis path, +.monthly_join_resign_trend .axis line { + fill: none; + shape-rendering: crispEdges; + } + +.monthly_join_resign_trend .line { + fill: none; + stroke-width: 3px; + + } + +.monthly_join_resign_trend .area { + fill: steelblue; + opacity: 0.5; + } + +.monthly_join_resign_trend .dot { + fill: steelblue; + stroke: steelblue; + stroke-width: 1.5px; + } + +/*----------------------------------------*/ + + +.monthly_attrition_rate path { + stroke: #70cac1; + stroke-width: 2; + fill: none; +} + +.monthly_attrition_rate .axis path, +.monthly_attrition_rate .axis line { + fill: none; + stroke: grey; + stroke-width: 1; + shape-rendering: crispEdges; +} +.monthly_attrition_rate circle{ + fill: #ffffff; + stroke: #44b7ac; + stroke-width: 1.5; +} + +.monthly_attrition_rate .oh-card { + background: #fff; + 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); + padding: 15px; +} + +.monthly_attrition_rate .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; +} + + +.row.main-section { + margin-right: 0px; !important; +} +/* width */ +.hr_notification::-webkit-scrollbar { + width: 4px; +} + +/* Track */ +.hr_notification::-webkit-scrollbar-track { + background: #f1f1f1; +} + +/* Handle */ +.hr_notification::-webkit-scrollbar-thumb { + background: #5ebade; +} + +/* Handle on hover */ +.hr_notification::-webkit-scrollbar-thumb:hover { + background: #598da1; +} + +.oh-card-body { + display: flex; + justify-content: space-between; + align-items: center; +} + +.oh-ribbon { + position: absolute; + left: -5px; top: -5px; + z-index: 1; + overflow: hidden; + width: 150px; height: 150px; + text-align: right; +} +.oh-ribbon span { + font-size: 10px; + font-weight: bold; + color: #FFF; + text-transform: uppercase; + text-align: center; + line-height: 20px; + transform: rotate(-45deg); + -webkit-transform: rotate(-45deg); + width: 200px; + display: block; + background: #79A70A; + background: linear-gradient(#2989d8 0%, #1e5799 100%); + box-shadow: 0 3px 10px -5px rgba(0, 0, 0, 1); + position: absolute; + top: 56px; + left: -35px; +} +.oh-ribbon span::before { + content: ""; + position: absolute; left: 0px; top: 100%; + z-index: -1; + border-left: 3px solid #1e5799; + border-right: 3px solid transparent; + border-bottom: 3px solid transparent; + border-top: 3px solid #1e5799; +} +.oh-ribbon span::after { + content: ""; + position: absolute; right: 0px; top: 100%; + z-index: -1; + border-left: 3px solid transparent; + border-right: 3px solid #1e5799; + border-bottom: 3px solid transparent; + border-top: 3px solid #1e5799; +} + +.o_action_manager{ + overflow-y: scroll !important; + max-width:100%; + } + + .hr_notification { + + margin-top: 20px; +} + +.stat_count{ + margin-top: -111px; + margin-left: 35px; + font-size: 48px; +} + + +.stat-head { + text-align: left !important; + font-weight: 300; + font-size: 18px; + margin-bottom: 25px; + margin-left: 24px; + width: 100%; + margin-top: 57px; +} \ No newline at end of file diff --git a/dashboard_pos/static/src/js/pos_dashboard.js b/dashboard_pos/static/src/js/pos_dashboard.js new file mode 100644 index 000000000..808320b23 --- /dev/null +++ b/dashboard_pos/static/src/js/pos_dashboard.js @@ -0,0 +1,527 @@ +odoo.define('dashboard_pos.Dashboard', function (require) { +"use strict"; + +var AbstractAction = require('web.AbstractAction'); +var ajax = require('web.ajax'); +var core = require('web.core'); +var rpc = require('web.rpc'); +var session = require('web.session'); +var web_client = require('web.web_client'); +var _t = core._t; +var QWeb = core.qweb; + +var PosDashboard = AbstractAction.extend({ + template: 'PosDashboard', + events: { + 'click .pos_order_today':'pos_order_today', + 'click .pos_order':'pos_order', + 'click .pos_total_sales':'pos_order', + 'click .pos_session':'pos_session', + 'click .pos_refund_orders':'pos_refund_orders', + 'click .pos_refund_today_orders':'pos_refund_today_orders', + 'change #pos_sales': 'onclick_pos_sales', + }, + + init: function(parent, context) { + this._super(parent, context); + this.dashboards_templates = ['PosOrders','PosChart','PosCustomer']; + this.payment_details = []; + this.top_salesperson = []; + this.selling_product = []; + this.total_sale = []; + this.total_order_count = []; + this.total_refund_count = []; + this.total_session = []; + this.today_refund_total = []; + this.today_sale = []; + }, + + willStart: function() { + var self = this; + return $.when(ajax.loadLibs(this), this._super()).then(function() { + return self.fetch_data(); + }); + }, + + start: function() { + var self = this; + this.set("title", 'Dashboard'); + return this._super().then(function() { + self.render_dashboards(); + self.render_graphs(); + self.$el.parent().addClass('oe_background_grey'); + }); + }, + + fetch_data: function() { + var self = this; + var def1 = this._rpc({ + model: 'pos.order', + method: 'get_refund_details' + }).then(function(result) { + self.total_sale = result['total_sale'], + self.total_order_count = result['total_order_count'] + self.total_refund_count = result['total_refund_count'] + self.total_session = result['total_session'] + self.today_refund_total = result['today_refund_total'] + self.today_sale = result['today_sale'] + }); + var def2 = self._rpc({ + model: "pos.order", + method: "get_details", + }) + .then(function (res) { + self.payment_details = res['payment_details']; + self.top_salesperson = res['salesperson']; + self.selling_product = res['selling_product']; + }); + return $.when(def1,def2); + }, + + render_dashboards: function() { + var self = this; + _.each(this.dashboards_templates, function(template) { + self.$('.o_pos_dashboard').append(QWeb.render(template, {widget: self})); + }); + }, + render_graphs: function(){ + var self = this; + self.render_top_customer_graph(); + self.render_top_product_graph(); + self.render_product_category_graph(); + }, + + + + + pos_order_today: function(e){ + var self = this; + var date = new Date(); + var yesterday = new Date(date.getTime()); + yesterday.setDate(date.getDate() - 1); + e.stopPropagation(); + e.preventDefault(); + + session.user_has_group('hr.group_hr_user').then(function(has_group){ + if(has_group){ + var options = { + on_reverse_breadcrumb: self.on_reverse_breadcrumb, + }; + self.do_action({ + name: _t("Today Order"), + type: 'ir.actions.act_window', + res_model: 'pos.order', + view_mode: 'tree,form,calendar', + view_type: 'form', + views: [[false, 'list'],[false, 'form']], + domain: [['date_order','<=', date],['date_order', '>=', yesterday]], + target: 'current' + }, options) + } + }); + + }, + + + pos_refund_orders: function(e){ + var self = this; + var date = new Date(); + var yesterday = new Date(date.getTime()); + yesterday.setDate(date.getDate() - 1); + e.stopPropagation(); + e.preventDefault(); + + session.user_has_group('hr.group_hr_user').then(function(has_group){ + if(has_group){ + var options = { + on_reverse_breadcrumb: self.on_reverse_breadcrumb, + }; + self.do_action({ + name: _t("Refund Orders"), + type: 'ir.actions.act_window', + res_model: 'pos.order', + view_mode: 'tree,form,calendar', + view_type: 'form', + views: [[false, 'list'],[false, 'form']], + domain: [['amount_total', '<', 0.0]], + target: 'current' + }, options) + } + }); + + }, + pos_refund_today_orders: function(e){ + var self = this; + var date = new Date(); + var yesterday = new Date(date.getTime()); + yesterday.setDate(date.getDate() - 1); + e.stopPropagation(); + e.preventDefault(); + + session.user_has_group('hr.group_hr_user').then(function(has_group){ + if(has_group){ + var options = { + on_reverse_breadcrumb: self.on_reverse_breadcrumb, + }; + self.do_action({ + name: _t("Refund Orders"), + type: 'ir.actions.act_window', + res_model: 'pos.order', + view_mode: 'tree,form,calendar', + view_type: 'form', + views: [[false, 'list'],[false, 'form']], + domain: [['amount_total', '<', 0.0],['date_order','<=', date],['date_order', '>=', yesterday]], + target: 'current' + }, options) + } + }); + + }, + + pos_order: function(e){ + var self = this; + var date = new Date(); + var yesterday = new Date(date.getTime()); + yesterday.setDate(date.getDate() - 1); + e.stopPropagation(); + e.preventDefault(); + session.user_has_group('hr.group_hr_user').then(function(has_group){ + if(has_group){ + var options = { + on_reverse_breadcrumb: self.on_reverse_breadcrumb, + }; + self.do_action({ + name: _t("Total Order"), + type: 'ir.actions.act_window', + res_model: 'pos.order', + view_mode: 'tree,form,calendar', + view_type: 'form', + views: [[false, 'list'],[false, 'form']], + target: 'current' + }, options) + } + }); + + }, + pos_session: function(e){ + var self = this; + e.stopPropagation(); + e.preventDefault(); + session.user_has_group('hr.group_hr_user').then(function(has_group){ + if(has_group){ + var options = { + on_reverse_breadcrumb: self.on_reverse_breadcrumb, + }; + self.do_action({ + name: _t("sessions"), + type: 'ir.actions.act_window', + res_model: 'pos.session', + view_mode: 'tree,form,calendar', + view_type: 'form', + views: [[false, 'list'],[false, 'form']], + target: 'current' + }, options) + } + }); + + }, + + onclick_pos_sales:function(events){ + var option = $(events.target).val(); + var self = this + var ctx = self.$("#canvas_1"); + rpc.query({ + model: "pos.order", + method: "get_department", + args: [option], + }).then(function (arrays) { + var data = { + labels: arrays[1], + datasets: [ + { + label: arrays[2], + data: arrays[0], + backgroundColor: [ + "rgba(255, 99, 132,1)", + "rgba(54, 162, 235,1)", + "rgba(75, 192, 192,1)", + "rgba(153, 102, 255,1)", + "rgba(10,20,30,1)" + ], + borderColor: [ + "rgba(255, 99, 132, 0.2)", + "rgba(54, 162, 235, 0.2)", + "rgba(75, 192, 192, 0.2)", + "rgba(153, 102, 255, 0.2)", + "rgba(10,20,30,0.3)" + ], + borderWidth: 1 + }, + + ] + }; + + //options + var options = { + responsive: true, + title: { + display: true, + position: "top", + text: "SALE DETAILS", + fontSize: 18, + fontColor: "#111" + }, + legend: { + display: true, + position: "bottom", + labels: { + fontColor: "#333", + fontSize: 16 + } + }, + scales: { + yAxes: [{ + ticks: { + min: 0 + } + }] + } + }; + + //create Chart class object + if (window.myCharts != undefined) + window.myCharts.destroy(); + window.myCharts = new Chart(ctx, { + type: "bar", + data: data, + options: options + }); + + }); + }, + + + render_top_customer_graph:function(){ + var self = this + var ctx = self.$(".top_customer"); + rpc.query({ + model: "pos.order", + method: "get_the_top_customer", + }).then(function (arrays) { + + + var data = { + labels: arrays[1], + datasets: [ + { + label: "", + data: arrays[0], + backgroundColor: [ + "rgb(148, 22, 227)", + "rgba(54, 162, 235)", + "rgba(75, 192, 192)", + "rgba(153, 102, 255)", + "rgba(10,20,30)" + ], + borderColor: [ + "rgba(255, 99, 132,)", + "rgba(54, 162, 235,)", + "rgba(75, 192, 192,)", + "rgba(153, 102, 255,)", + "rgba(10,20,30,)" + ], + borderWidth: 1 + }, + + ] + }; + + //options + var options = { + responsive: true, + title: { + display: true, + position: "top", + text: " Top Customer", + fontSize: 18, + fontColor: "#111" + }, + legend: { + display: true, + position: "bottom", + labels: { + fontColor: "#333", + fontSize: 16 + } + }, + scales: { + yAxes: [{ + ticks: { + min: 0 + } + }] + } + }; + + //create Chart class object + var chart = new Chart(ctx, { + type: "pie", + data: data, + options: options + }); + + }); + }, + + render_top_product_graph:function(){ + var self = this + var ctx = self.$(".top_selling_product"); + rpc.query({ + model: "pos.order", + method: "get_the_top_products", + }).then(function (arrays) { + + + var data = { + labels: arrays[1], + datasets: [ + { + label: "Quantity", + data: arrays[0], + backgroundColor: [ + "rgba(255, 99, 132,1)", + "rgba(54, 162, 235,1)", + "rgba(75, 192, 192,1)", + "rgba(153, 102, 255,1)", + "rgba(10,20,30,1)" + ], + borderColor: [ + "rgba(255, 99, 132, 0.2)", + "rgba(54, 162, 235, 0.2)", + "rgba(75, 192, 192, 0.2)", + "rgba(153, 102, 255, 0.2)", + "rgba(10,20,30,0.3)" + ], + borderWidth: 1 + }, + + ] + }; + + //options + var options = { + responsive: true, + title: { + display: true, + position: "top", + text: " Top products", + fontSize: 18, + fontColor: "#111" + }, + legend: { + display: true, + position: "bottom", + labels: { + fontColor: "#333", + fontSize: 16 + } + }, + scales: { + yAxes: [{ + ticks: { + min: 0 + } + }] + } + }; + + //create Chart class object + var chart = new Chart(ctx, { + type: "horizontalBar", + data: data, + options: options + }); + + }); + }, + + render_product_category_graph:function(){ + var self = this + var ctx = self.$(".top_product_categories"); + rpc.query({ + model: "pos.order", + method: "get_the_top_categories", + }).then(function (arrays) { + + + var data = { + labels: arrays[1], + datasets: [ + { + label: "Quantity", + data: arrays[0], + backgroundColor: [ + "rgba(255, 99, 132,1)", + "rgba(54, 162, 235,1)", + "rgba(75, 192, 192,1)", + "rgba(153, 102, 255,1)", + "rgba(10,20,30,1)" + ], + borderColor: [ + "rgba(255, 99, 132, 0.2)", + "rgba(54, 162, 235, 0.2)", + "rgba(75, 192, 192, 0.2)", + "rgba(153, 102, 255, 0.2)", + "rgba(10,20,30,0.3)" + ], + borderWidth: 1 + }, + + + ] + }; + + //options + var options = { + responsive: true, + title: { + display: true, + position: "top", + text: " Top product categories", + fontSize: 18, + fontColor: "#111" + }, + legend: { + display: true, + position: "bottom", + labels: { + fontColor: "#333", + fontSize: 16 + } + }, + scales: { + yAxes: [{ + ticks: { + min: 0 + } + }] + } + }; + + //create Chart class object + var chart = new Chart(ctx, { + type: "horizontalBar", + data: data, + options: options + }); + + }); + }, +}); + + +core.action_registry.add('pos_dashboard', PosDashboard); + +return PosDashboard; + +}); diff --git a/dashboard_pos/static/src/xml/pos_dashboard.xml b/dashboard_pos/static/src/xml/pos_dashboard.xml new file mode 100644 index 000000000..cc8ba2896 --- /dev/null +++ b/dashboard_pos/static/src/xml/pos_dashboard.xml @@ -0,0 +1,294 @@ + + + +
+
+
+
+
+ +
+
+
+
+
+
+
+
Today Orders
+
+
+
+
+
+
+
+
+
+
+
+
+
Total Orders
+
+
+
+
+
+
+
+
+
+
+
+
+
Total Sales
+
+
+
+
+
+
+
+
+
+
+
+
+
Sessions
+
+
+
+
+
+
+ +
+
+
+
+
+
+
Total Refund Orders
+
+
+
+
+
+
+
+
+
+
+
+
+
Today Refund Order
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+ +

SALE REPORT

+
+
+
+ +
+
+
+
+
+

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

+

+
+ +
+
+
+
+
+

+

+
+ +
+
+
+
+
+

+

+
+ +
+
+
+
+ +
+ + +
+
+
+
+
+ Sale by Salesperson +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + +
Name   ordersAmount
+

+ +

+
+

+ +

+
+

+ +

+
+
+
+
+
+
+
+
+ Payment Method +
+
+
+
+
+
+ + + + + + + + + + + + + + + +
Payment Method   Amount
+

+ +

+
+

+ +

+
+
+
+
+
+ + +
+
+
+ Session Status +
+
+
+
+
+
+ + + + + + + + + + + + + + + +
Session   Status
+

+ +

+
+

+ +

+
+
+
+
+
+ +
+
+ + +
+
diff --git a/dashboard_pos/views/dashboard_views.xml b/dashboard_pos/views/dashboard_views.xml new file mode 100644 index 000000000..31e4267e7 --- /dev/null +++ b/dashboard_pos/views/dashboard_views.xml @@ -0,0 +1,14 @@ + + + + Dashboard + pos_dashboard + + + + + + diff --git a/insurance_management_cybro/README.rst b/insurance_management_cybro/README.rst new file mode 100644 index 000000000..f060ed70c --- /dev/null +++ b/insurance_management_cybro/README.rst @@ -0,0 +1,48 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +Insurance Management +==================== +This module will used for Insurance Management & Operations. + + +Configuration +============= +* No additional configurations needed + +Company +------- +* `Cybrosys Techno Solutions `__ + +Credits +------- +* Developer: Niyas Raphy@cybrosys + Sreejith P @cybrosys + version 13: Nimisha Murali @cybrosys + version 14: Muhammed Nafih @cybrosys + version 15: Abhishek E T @cybrosys + +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/insurance_management_cybro/__init__.py b/insurance_management_cybro/__init__.py new file mode 100755 index 000000000..9ccc676aa --- /dev/null +++ b/insurance_management_cybro/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from . import models diff --git a/insurance_management_cybro/__manifest__.py b/insurance_management_cybro/__manifest__.py new file mode 100755 index 000000000..4de9cf307 --- /dev/null +++ b/insurance_management_cybro/__manifest__.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +{ + 'name': 'Insurance Management', + 'version': '16.0.1.0.0', + 'summary': """Insurance Management & Operations""", + 'description': """Insurance Management""", + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'website': 'https://www.cybrosys.com', + 'category': 'Industries', + 'depends': ['account', 'base'], + 'license': 'AGPL-3', + 'data': [ + 'security/ir.model.access.csv', + 'data/insurance_management_data.xml', + 'views/claim_details_views.xml', + 'views/employee_details_views.xml', + 'views/insurance_details_views.xml', + 'views/policy_details_views.xml', + 'views/insurance_management_menus.xml' + ], + 'images': ['static/description/banner.png'], + 'installable': True, + 'application': True, + 'auto_install': False, +} diff --git a/insurance_management_cybro/data/insurance_management_data.xml b/insurance_management_cybro/data/insurance_management_data.xml new file mode 100755 index 000000000..4ad7ff3d5 --- /dev/null +++ b/insurance_management_cybro/data/insurance_management_data.xml @@ -0,0 +1,20 @@ + + + + + Insurance Details + insurance.details + INS/ + 3 + + + + + Claim Details + claim.details + CLM/ + 3 + + + + \ No newline at end of file diff --git a/insurance_management_cybro/doc/RELEASE_NOTES.md b/insurance_management_cybro/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..e6160b8ec --- /dev/null +++ b/insurance_management_cybro/doc/RELEASE_NOTES.md @@ -0,0 +1,7 @@ +## Module + +#### 11.11.2022 +#### Version 16.0.1.0.0 +#### ADD + +- Initial commit for Insurance Management diff --git a/insurance_management_cybro/models/__init__.py b/insurance_management_cybro/models/__init__.py new file mode 100755 index 000000000..6c122ffd7 --- /dev/null +++ b/insurance_management_cybro/models/__init__.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from . import account_move +from . import claim_details +from . import employee_details +from . import insurance_details +from . import policy_details diff --git a/insurance_management_cybro/models/account_move.py b/insurance_management_cybro/models/account_move.py new file mode 100644 index 000000000..734b6cae9 --- /dev/null +++ b/insurance_management_cybro/models/account_move.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import models, fields + + +class AccountMove(models.Model): + _inherit = 'account.move' + + insurance_id = fields.Many2one('insurance.details', string='Insurance') + claim_id = fields.Many2one('claim.details', string='Insurance') diff --git a/insurance_management_cybro/models/claim_details.py b/insurance_management_cybro/models/claim_details.py new file mode 100755 index 000000000..d6536baa3 --- /dev/null +++ b/insurance_management_cybro/models/claim_details.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import api, fields, models, _ + + +class ClaimDetails(models.Model): + _name = 'claim.details' + + name = fields.Char(string='Name', required=True, copy=False, + readonly=True, index=True, default=lambda self: _('New')) + name_2 = fields.Char( + string='Name 2', required=True, copy=False, readonly=True, index=True, + default=lambda self: _('New')) + insurance_id = fields.Many2one('insurance.details', required=True, + domain=[('state', '=', 'confirmed')], + help="Confirmed orders can be selected") + partner_id = fields.Many2one(related='insurance_id.partner_id', + string='Customer', readonly=True) + policy_id = fields.Many2one(related='insurance_id.policy_id', + string='Policy', readonly=True) + employee_id = fields.Many2one(related='insurance_id.employee_id', + string='Agent', readonly=True) + currency_id = fields.Many2one( + 'res.currency', string='Currency', required=True, + default=lambda self: self.env.user.company_id.currency_id.id) + amount = fields.Monetary(related='insurance_id.amount', string='Amount') + date_claimed = fields.Date( + string='Date Applied', default=fields.Date.context_today) + invoice_id = fields.Many2one('account.move', string='Invoiced', + readonly=True, copy=False) + note_field = fields.Html(string='Comment') + + @api.model + def create(self, vals): + if vals.get('name', 'New') == 'New': + vals['name'] = self.env['ir.sequence'].next_by_code( + 'claim.details') or 'New' + return super(ClaimDetails, self).create(vals) + + def action_create_bill(self): + if not self.invoice_id: + invoice_val = self.env['account.move'].sudo().create({ + 'move_type': 'in_invoice', + 'invoice_date': fields.Date.context_today(self), + 'partner_id': self.partner_id.id, + 'invoice_user_id': self.env.user.id, + 'claim_id': self.id, + 'invoice_origin': self.name, + 'invoice_line_ids': [(0, 0, { + 'name': 'Invoice For Insurance Claim', + 'quantity': 1, + 'price_unit': self.amount, + 'account_id': 41, + })], + }) + self.invoice_id = invoice_val diff --git a/insurance_management_cybro/models/employee_details.py b/insurance_management_cybro/models/employee_details.py new file mode 100755 index 000000000..926cc8ba9 --- /dev/null +++ b/insurance_management_cybro/models/employee_details.py @@ -0,0 +1,97 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +import re + +from odoo import api, fields, models, _ +from odoo.exceptions import UserError, ValidationError + + +class EmployeeDetails(models.Model): + _name = 'employee.details' + + name = fields.Char(string='Name', required=True) + user_id = fields.Many2one( + 'res.users', string='Related User', copy=False) + sex = fields.Selection( + [('male', 'Male'), ('female', 'Female'), ('others', 'Others')]) + phone = fields.Char(string='Phone Number') + salary_type = fields.Selection( + [('fixed', 'Fixed'), ('commission', 'Commission'), ('both', 'Both')], + default='commission', required=True) + currency_id = fields.Many2one( + 'res.currency', string='Currency', required=True, + default=lambda self: self.env.user.company_id.currency_id.id) + base_salary = fields.Monetary(string='Base Salary') + last_salary_date = fields.Date(string='Last Payment On', copy=False) + insurance_ids = fields.One2many('insurance.details', 'employee_id', + string='Last Payment On', readonly=True) + note_field = fields.Html(string='Comment') + invoice_id = fields.Many2one( + 'account.move', string='Last payment', copy=False, readonly=True) + + def action_salary_payment(self): + if self.invoice_id: + if self.invoice_id.state == 'draft': + raise UserError(_("You must validate the last payment made in " + "order to create a new payment")) + amount = 0.0 + if self.base_salary == 0.0: + raise UserError(_("Amount should be greater than zero")) + if self.salary_type == 'fixed': + amount = self.base_salary + elif self.salary_type == 'commission': + for ins in self.insurance_ids: + if self.last_salary_date: + if ins.start_date > self.last_salary_date: + amount += (ins.commission_rate * ins.amount) / 100 + else: + amount = self.base_salary + for ins in self.insurance_ids: + if ins.start_date > self.last_salary_date: + amount += (ins.commission_rate * ins.amount) / 100 + invoice_date = self.env['account.move'].sudo().create({ + 'move_type': 'in_invoice', + 'invoice_date': fields.Date.context_today(self), + 'partner_id': self.user_id.partner_id.id, + 'invoice_user_id': self.env.user.id, + 'claim_id': self.id, + 'invoice_origin': self.name, + 'invoice_line_ids': [(0, 0, { + 'name': 'Invoice For Insurance Claim', + 'quantity': 1, + 'price_unit': amount, + 'account_id': 41, + })], + }) + self.sudo().write({ + 'invoice_id': invoice_date.id, + 'last_salary_date': fields.Date.context_today(self), + }) + + @api.constrains('phone') + def check_phone(self): + """ make sure phone contains only numbers""" + for rec in self: + if not re.match('^[0-9]*$', rec.phone): + raise ValidationError( + _('Only numbers are permitted in phone number')) diff --git a/insurance_management_cybro/models/insurance_details.py b/insurance_management_cybro/models/insurance_details.py new file mode 100755 index 000000000..bfdd3c11a --- /dev/null +++ b/insurance_management_cybro/models/insurance_details.py @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import api, fields, models, _ +from odoo.exceptions import UserError, ValidationError + + +class InsuranceDetails(models.Model): + _name = 'insurance.details' + + name = fields.Char( + string='Name', required=True, copy=False, readonly=True, index=True, + default=lambda self: _('New')) + partner_id = fields.Many2one('res.partner', string='Customer', + required=True) + start_date = fields.Date( + string='Date Started', default=fields.Date.context_today, required=True) + close_date = fields.Date(string='Date Closed', readonly=True) + invoice_ids = fields.One2many('account.move', 'insurance_id', + string='Invoices', readonly=True) + employee_id = fields.Many2one( + 'employee.details', string='Agent', required=True) + commission_rate = fields.Float(string='Commission Percentage') + policy_id = fields.Many2one( + 'policy.details', string='Policy', required=True) + currency_id = fields.Many2one( + 'res.currency', string='Currency', required=True, + default=lambda self: self.env.user.company_id.currency_id.id) + amount = fields.Monetary(related='policy_id.amount', string='Amount') + state = fields.Selection( + [('draft', 'Draft'), ('confirmed', 'Confirmed'), ('closed', 'Closed')], + required=True, default='draft') + hide_inv_button = fields.Boolean(copy=False) + note_field = fields.Html(string='Comment') + + @api.constrains('commission_rate') + def _check_commission_rate(self): + if self.filtered( + lambda reward: ( + reward.commission_rate < 0 or reward.commission_rate > 100)): + raise ValidationError( + _('Commission Percentage should be between 1-100')) + + def action_confirm_insurance(self): + if self.amount > 0: + self.state = 'confirmed' + self.hide_inv_button = True + else: + raise UserError(_("Amount should be greater than zero")) + + def action_create_invoice(self): + created_invoice = self.env['account.move'].sudo().create({ + 'move_type': 'out_invoice', + 'invoice_date': fields.Date.context_today(self), + 'partner_id': self.partner_id.id, + 'invoice_user_id': self.env.user.id, + 'invoice_origin': self.name, + 'invoice_line_ids': [(0, 0, { + 'name': 'Invoice For Insurance', + 'quantity': 1, + 'price_unit': self.amount, + 'account_id': 41, + })], + }) + self.invoice_ids = created_invoice + if self.policy_id.payment_type == 'fixed': + self.hide_inv_button = False + + def action_close_insurance(self): + for records in self.invoice_ids: + if records.state == 'paid': + raise UserError(_("All invoices must be paid")) + self.state = 'closed' + self.close_date = fields.Date.context_today(self) + self.hide_inv_button = False + + @api.model + def create(self, vals): + if vals.get('name', 'New') == 'New': + vals['name'] = self.env['ir.sequence'].next_by_code( + 'insurance.details') or 'New' + return super(InsuranceDetails, self).create(vals) diff --git a/insurance_management_cybro/models/policy_details.py b/insurance_management_cybro/models/policy_details.py new file mode 100755 index 000000000..7bd0813dc --- /dev/null +++ b/insurance_management_cybro/models/policy_details.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies(). +# Author: Cybrosys Techno Solutions(odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from odoo import fields, models + + +class PolicyDetails(models.Model): + _name = 'policy.details' + + name = fields.Char(string='Name', required=True) + policy_type_id = fields.Many2one( + 'policy.type', string='Policy Type', required=True) + payment_type = fields.Selection( + [('fixed', 'Fixed'), ('installment', 'Installment')], + required=True, default='fixed') + currency_id = fields.Many2one( + 'res.currency', string='Currency', required=True, + default=lambda self: self.env.user.company_id.currency_id.id) + amount = fields.Monetary(string='Amount', required=True) + policy_duration = fields.Integer(string='Duration in Days', required=True) + note_field = fields.Html(string='Comment') + + +class PolicyType(models.Model): + _name = 'policy.type' + + name = fields.Char(string='Name') diff --git a/insurance_management_cybro/security/ir.model.access.csv b/insurance_management_cybro/security/ir.model.access.csv new file mode 100755 index 000000000..88d364996 --- /dev/null +++ b/insurance_management_cybro/security/ir.model.access.csv @@ -0,0 +1,7 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_claim_details,claim.details,model_claim_details,base.group_user,1,1,1,1 +access_employee_details,employee.details,model_employee_details,base.group_user,1,1,1,1 +access_insurance_details,insurance.details,model_insurance_details,base.group_user,1,1,1,1 +access_policy_details,policy.details,model_policy_details,base.group_user,1,1,1,1 +access_policy_type,policy.type,model_policy_type,base.group_user,1,1,1,1 +access_account_move,account.move,model_account_move,base.group_user,1,1,1,1 diff --git a/insurance_management_cybro/static/description/assets/icons/check.png b/insurance_management_cybro/static/description/assets/icons/check.png new file mode 100644 index 000000000..c8e85f51d Binary files /dev/null and b/insurance_management_cybro/static/description/assets/icons/check.png differ diff --git a/insurance_management_cybro/static/description/assets/icons/chevron.png b/insurance_management_cybro/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..2089293d6 Binary files /dev/null and b/insurance_management_cybro/static/description/assets/icons/chevron.png differ diff --git a/insurance_management_cybro/static/description/assets/icons/cogs.png b/insurance_management_cybro/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/insurance_management_cybro/static/description/assets/icons/cogs.png differ diff --git a/insurance_management_cybro/static/description/assets/icons/consultation.png b/insurance_management_cybro/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/insurance_management_cybro/static/description/assets/icons/consultation.png differ diff --git a/insurance_management_cybro/static/description/assets/icons/ecom-black.png b/insurance_management_cybro/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/insurance_management_cybro/static/description/assets/icons/ecom-black.png differ diff --git a/insurance_management_cybro/static/description/assets/icons/education-black.png b/insurance_management_cybro/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/insurance_management_cybro/static/description/assets/icons/education-black.png differ diff --git a/insurance_management_cybro/static/description/assets/icons/hotel-black.png b/insurance_management_cybro/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/insurance_management_cybro/static/description/assets/icons/hotel-black.png differ diff --git a/insurance_management_cybro/static/description/assets/icons/license.png b/insurance_management_cybro/static/description/assets/icons/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/insurance_management_cybro/static/description/assets/icons/license.png differ diff --git a/insurance_management_cybro/static/description/assets/icons/lifebuoy.png b/insurance_management_cybro/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/insurance_management_cybro/static/description/assets/icons/lifebuoy.png differ diff --git a/insurance_management_cybro/static/description/assets/icons/manufacturing-black.png b/insurance_management_cybro/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/insurance_management_cybro/static/description/assets/icons/manufacturing-black.png differ diff --git a/insurance_management_cybro/static/description/assets/icons/pos-black.png b/insurance_management_cybro/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/insurance_management_cybro/static/description/assets/icons/pos-black.png differ diff --git a/insurance_management_cybro/static/description/assets/icons/puzzle.png b/insurance_management_cybro/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/insurance_management_cybro/static/description/assets/icons/puzzle.png differ diff --git a/insurance_management_cybro/static/description/assets/icons/restaurant-black.png b/insurance_management_cybro/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/insurance_management_cybro/static/description/assets/icons/restaurant-black.png differ diff --git a/insurance_management_cybro/static/description/assets/icons/service-black.png b/insurance_management_cybro/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/insurance_management_cybro/static/description/assets/icons/service-black.png differ diff --git a/insurance_management_cybro/static/description/assets/icons/trading-black.png b/insurance_management_cybro/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/insurance_management_cybro/static/description/assets/icons/trading-black.png differ diff --git a/insurance_management_cybro/static/description/assets/icons/training.png b/insurance_management_cybro/static/description/assets/icons/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/insurance_management_cybro/static/description/assets/icons/training.png differ diff --git a/insurance_management_cybro/static/description/assets/icons/update.png b/insurance_management_cybro/static/description/assets/icons/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/insurance_management_cybro/static/description/assets/icons/update.png differ diff --git a/insurance_management_cybro/static/description/assets/icons/user.png b/insurance_management_cybro/static/description/assets/icons/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/insurance_management_cybro/static/description/assets/icons/user.png differ diff --git a/insurance_management_cybro/static/description/assets/icons/wrench.png b/insurance_management_cybro/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/insurance_management_cybro/static/description/assets/icons/wrench.png differ diff --git a/insurance_management_cybro/static/description/assets/misc/categories.png b/insurance_management_cybro/static/description/assets/misc/categories.png new file mode 100644 index 000000000..bedf1e0b1 Binary files /dev/null and b/insurance_management_cybro/static/description/assets/misc/categories.png differ diff --git a/insurance_management_cybro/static/description/assets/misc/check-box.png b/insurance_management_cybro/static/description/assets/misc/check-box.png new file mode 100644 index 000000000..42caf24b9 Binary files /dev/null and b/insurance_management_cybro/static/description/assets/misc/check-box.png differ diff --git a/insurance_management_cybro/static/description/assets/misc/compass.png b/insurance_management_cybro/static/description/assets/misc/compass.png new file mode 100644 index 000000000..d5fed8faa Binary files /dev/null and b/insurance_management_cybro/static/description/assets/misc/compass.png differ diff --git a/insurance_management_cybro/static/description/assets/misc/corporate.png b/insurance_management_cybro/static/description/assets/misc/corporate.png new file mode 100644 index 000000000..2eb13edbf Binary files /dev/null and b/insurance_management_cybro/static/description/assets/misc/corporate.png differ diff --git a/insurance_management_cybro/static/description/assets/misc/customer-support.png b/insurance_management_cybro/static/description/assets/misc/customer-support.png new file mode 100644 index 000000000..79efc72ed Binary files /dev/null and b/insurance_management_cybro/static/description/assets/misc/customer-support.png differ diff --git a/insurance_management_cybro/static/description/assets/misc/cybrosys-logo.png b/insurance_management_cybro/static/description/assets/misc/cybrosys-logo.png new file mode 100644 index 000000000..cc3cc0ccf Binary files /dev/null and b/insurance_management_cybro/static/description/assets/misc/cybrosys-logo.png differ diff --git a/insurance_management_cybro/static/description/assets/misc/features.png b/insurance_management_cybro/static/description/assets/misc/features.png new file mode 100644 index 000000000..b41769f77 Binary files /dev/null and b/insurance_management_cybro/static/description/assets/misc/features.png differ diff --git a/insurance_management_cybro/static/description/assets/misc/logo.png b/insurance_management_cybro/static/description/assets/misc/logo.png new file mode 100644 index 000000000..478462d3e Binary files /dev/null and b/insurance_management_cybro/static/description/assets/misc/logo.png differ diff --git a/insurance_management_cybro/static/description/assets/misc/pictures.png b/insurance_management_cybro/static/description/assets/misc/pictures.png new file mode 100644 index 000000000..56d255fe9 Binary files /dev/null and b/insurance_management_cybro/static/description/assets/misc/pictures.png differ diff --git a/insurance_management_cybro/static/description/assets/misc/pie-chart.png b/insurance_management_cybro/static/description/assets/misc/pie-chart.png new file mode 100644 index 000000000..426e05244 Binary files /dev/null and b/insurance_management_cybro/static/description/assets/misc/pie-chart.png differ diff --git a/insurance_management_cybro/static/description/assets/misc/right-arrow.png b/insurance_management_cybro/static/description/assets/misc/right-arrow.png new file mode 100644 index 000000000..730984a06 Binary files /dev/null and b/insurance_management_cybro/static/description/assets/misc/right-arrow.png differ diff --git a/insurance_management_cybro/static/description/assets/misc/star.png b/insurance_management_cybro/static/description/assets/misc/star.png new file mode 100644 index 000000000..2eb9ab29f Binary files /dev/null and b/insurance_management_cybro/static/description/assets/misc/star.png differ diff --git a/insurance_management_cybro/static/description/assets/misc/support.png b/insurance_management_cybro/static/description/assets/misc/support.png new file mode 100644 index 000000000..4f18b8b82 Binary files /dev/null and b/insurance_management_cybro/static/description/assets/misc/support.png differ diff --git a/insurance_management_cybro/static/description/assets/misc/whatsapp.png b/insurance_management_cybro/static/description/assets/misc/whatsapp.png new file mode 100644 index 000000000..d513a5356 Binary files /dev/null and b/insurance_management_cybro/static/description/assets/misc/whatsapp.png differ diff --git a/insurance_management_cybro/static/description/assets/modules/1.png b/insurance_management_cybro/static/description/assets/modules/1.png new file mode 100644 index 000000000..5238bdeab Binary files /dev/null and b/insurance_management_cybro/static/description/assets/modules/1.png differ diff --git a/insurance_management_cybro/static/description/assets/modules/2.png b/insurance_management_cybro/static/description/assets/modules/2.png new file mode 100644 index 000000000..1ae7cfe3b Binary files /dev/null and b/insurance_management_cybro/static/description/assets/modules/2.png differ diff --git a/insurance_management_cybro/static/description/assets/modules/3.png b/insurance_management_cybro/static/description/assets/modules/3.png new file mode 100644 index 000000000..3c3ff1afb Binary files /dev/null and b/insurance_management_cybro/static/description/assets/modules/3.png differ diff --git a/insurance_management_cybro/static/description/assets/modules/4.png b/insurance_management_cybro/static/description/assets/modules/4.png new file mode 100644 index 000000000..3fae4631e Binary files /dev/null and b/insurance_management_cybro/static/description/assets/modules/4.png differ diff --git a/insurance_management_cybro/static/description/assets/modules/5.gif b/insurance_management_cybro/static/description/assets/modules/5.gif new file mode 100644 index 000000000..2a5f8e659 Binary files /dev/null and b/insurance_management_cybro/static/description/assets/modules/5.gif differ diff --git a/insurance_management_cybro/static/description/assets/modules/6.png b/insurance_management_cybro/static/description/assets/modules/6.png new file mode 100644 index 000000000..7f2815273 Binary files /dev/null and b/insurance_management_cybro/static/description/assets/modules/6.png differ diff --git a/insurance_management_cybro/static/description/assets/screenshots/1.png b/insurance_management_cybro/static/description/assets/screenshots/1.png new file mode 100644 index 000000000..e6d197299 Binary files /dev/null and b/insurance_management_cybro/static/description/assets/screenshots/1.png differ diff --git a/insurance_management_cybro/static/description/assets/screenshots/2.png b/insurance_management_cybro/static/description/assets/screenshots/2.png new file mode 100644 index 000000000..8f28e3d38 Binary files /dev/null and b/insurance_management_cybro/static/description/assets/screenshots/2.png differ diff --git a/insurance_management_cybro/static/description/assets/screenshots/3.png b/insurance_management_cybro/static/description/assets/screenshots/3.png new file mode 100644 index 000000000..58fc3adaa Binary files /dev/null and b/insurance_management_cybro/static/description/assets/screenshots/3.png differ diff --git a/insurance_management_cybro/static/description/assets/screenshots/4.png b/insurance_management_cybro/static/description/assets/screenshots/4.png new file mode 100644 index 000000000..279c1eab7 Binary files /dev/null and b/insurance_management_cybro/static/description/assets/screenshots/4.png differ diff --git a/insurance_management_cybro/static/description/assets/screenshots/5.png b/insurance_management_cybro/static/description/assets/screenshots/5.png new file mode 100644 index 000000000..ff3b4b9cb Binary files /dev/null and b/insurance_management_cybro/static/description/assets/screenshots/5.png differ diff --git a/insurance_management_cybro/static/description/assets/screenshots/hero.gif b/insurance_management_cybro/static/description/assets/screenshots/hero.gif new file mode 100644 index 000000000..c2b0dc26c Binary files /dev/null and b/insurance_management_cybro/static/description/assets/screenshots/hero.gif differ diff --git a/insurance_management_cybro/static/description/banner.png b/insurance_management_cybro/static/description/banner.png new file mode 100644 index 000000000..6350a5b2e Binary files /dev/null and b/insurance_management_cybro/static/description/banner.png differ diff --git a/insurance_management_cybro/static/description/icon.png b/insurance_management_cybro/static/description/icon.png new file mode 100644 index 000000000..ec4975fa7 Binary files /dev/null and b/insurance_management_cybro/static/description/icon.png differ diff --git a/insurance_management_cybro/static/description/index.html b/insurance_management_cybro/static/description/index.html new file mode 100644 index 000000000..85362850c --- /dev/null +++ b/insurance_management_cybro/static/description/index.html @@ -0,0 +1,700 @@ +
+ +
+ +
+
+ Community +
+
+
+ + + +

+ Insurance Management

+

+ A Module for Manage Insurance Business.

+ + + +
+ + +
+
+ +
+

Explore This + Module

+
+ + + + +
+
+ +
+

+ Overview +

+
+
+
+ This module crafted by Cybrosys Technologies, allows the user to + create insurance policies. + Insurances can be created under these policies. We can manage the + insurance claims and the + salary of agents with or without the commission. +
+
+ + + +
+
+ +
+

+ Configuration +

+
+
+
+ The accounting localization for the country has to be installed +
+
+ + + +
+
+ +
+

+ Features +

+
+
+
+
+ + Create insurance policies for customers. +
+
+ + Manage insurance claims and details.. +
+
+ + Manage salary and commission of agents. +
+
+ + Create accounting entries for all.
+

+ Invoices/ Bills can be created for insurance, claims and the + salary/commission of agents.

+
+
+
+ + + +
+
+ +
+

+ Screenshots +

+
+
+
+ +
+

+ View and manage customers

+

+ Configuration -> Customers.

+ +
+ +
+

+ Manage policies

+

+ Configuration -> Policies

+ Create new policies and add the policy details.

+ +
+ +
+

+ Manage Agents(Employee)

+

+ Agent -> Agent

+ Create new agent and add the details. The salary type can be + selected as fixed, commission or both(salary + commission). + The salary payment can be done where the salary is computed + based on the salary type selected. The commission is + calculated + based on the percentage mentioned in the insurances under + the agent..

+ +
+ +
+

+ Manage insurances

+

+ Insurance Management -> Claims

+ Create insurance to customers based on a policy. Add the + agent and the commission of agent in percentage. + The insurance can be confirmed after adding all required + details. Invoice can be created for the insurance..

+ +
+ +
+

+ Manage claims

+

+ Insurance Management -> Insurance

+ Create insurance to customers based on a policy. Add the + agent and the commission of agent in percentage. + The insurance can be confirmed after adding all required + details. Invoice can be created for the insurance.

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

+ Related + 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

+
+
+
+
+
+
+
+ +
+
+
+ + \ No newline at end of file diff --git a/insurance_management_cybro/views/claim_details_views.xml b/insurance_management_cybro/views/claim_details_views.xml new file mode 100755 index 000000000..375815a2f --- /dev/null +++ b/insurance_management_cybro/views/claim_details_views.xml @@ -0,0 +1,69 @@ + + + + + claim.details.view.form + claim.details + +
+
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + claim.details.view.tree + claim.details + + + + + + + + + + + + + + Claim Management + claim.details + tree,form + +

+ You haven't created any claims yet. +

+
+
+ +
\ No newline at end of file diff --git a/insurance_management_cybro/views/employee_details_views.xml b/insurance_management_cybro/views/employee_details_views.xml new file mode 100755 index 000000000..fddb2cb2f --- /dev/null +++ b/insurance_management_cybro/views/employee_details_views.xml @@ -0,0 +1,71 @@ + + + + + employee.details.view.form + employee.details + +
+
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + employee.details.view.tree + employee.details + + + + + + + + + + + + + Employee Management + employee.details + tree,form + +

+ You haven't created any employee yet. +

+
+
+ +
\ No newline at end of file diff --git a/insurance_management_cybro/views/insurance_details_views.xml b/insurance_management_cybro/views/insurance_details_views.xml new file mode 100755 index 000000000..d101ed024 --- /dev/null +++ b/insurance_management_cybro/views/insurance_details_views.xml @@ -0,0 +1,79 @@ + + + + + insurance.details.view.form + insurance.details + +
+
+
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + insurance.details.view.tree + insurance.details + + + + + + + + + + + + + + + Insurance Management + insurance.details + tree,form + +

+ You haven't created any insurance yet. +

+
+
+ +
\ No newline at end of file diff --git a/insurance_management_cybro/views/insurance_management_menus.xml b/insurance_management_cybro/views/insurance_management_menus.xml new file mode 100755 index 000000000..1021af1ab --- /dev/null +++ b/insurance_management_cybro/views/insurance_management_menus.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + diff --git a/insurance_management_cybro/views/policy_details_views.xml b/insurance_management_cybro/views/policy_details_views.xml new file mode 100755 index 000000000..2c8819e4f --- /dev/null +++ b/insurance_management_cybro/views/policy_details_views.xml @@ -0,0 +1,62 @@ + + + + + policy.details.view.form + policy.details + +
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + +
+
+
+
+ + + policy.details.view.tree + policy.details + + + + + + + + + + + + + + Policy Management + policy.details + tree,form + +

+ You haven't created any policy yet. +

+
+
+ +
\ No newline at end of file diff --git a/invoice_multi_approval/README.rst b/invoice_multi_approval/README.rst new file mode 100644 index 000000000..dbacab571 --- /dev/null +++ b/invoice_multi_approval/README.rst @@ -0,0 +1,43 @@ +Invoice multi level approval +============================ +* Enables the option for adding multiple approvals to the invoice documents + +Installation +============ +- www.odoo.com/documentation/16.0/setup/install.html +- Install our custom addon + +License +------- +GNU AFFERO GENERAL PUBLIC LICENSE, Version 3 (AGPLv3) +(http://www.gnu.org/licenses/agpl.html) + +Company +------- +* `Cybrosys Techno Solutions `__ + +Credits +------- +* Developer: Sayooj A O + Version 14 Muhammed Nafih @cybrosys + Version 15 Akshay CK @cybrosys + Version 16 Sahla Sherin @cybrosys + + +Contacts +-------- +* Mail Contact : odoo@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 +========== +This module is maintained by Cybrosys Technologies. + +For support and more information, please visit https://www.cybrosys.com + +Further information +=================== +HTML Description: ``__ diff --git a/invoice_multi_approval/__init__.py b/invoice_multi_approval/__init__.py new file mode 100644 index 000000000..212d18e5a --- /dev/null +++ b/invoice_multi_approval/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies(). +# Author: Sayooj A O() +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# +from . import models diff --git a/invoice_multi_approval/__manifest__.py b/invoice_multi_approval/__manifest__.py new file mode 100644 index 000000000..28cf3827e --- /dev/null +++ b/invoice_multi_approval/__manifest__.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies(). +# Author: Sayooj A O() +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# +{ + 'name': "Invoice Multi level Approval", + 'version': '16.0.1.0.0', + 'summary': """This module add the multiple approval option for invoice, + bill,refund and credit notes.""", + 'description': """This module add the multiple approval option for invoice, + bill,refund and credit notes.""", + 'category': 'Accounting', + 'author': 'Cybrosys Techno Solutions', + 'company': 'Cybrosys Techno Solutions', + 'maintainer': 'Cybrosys Techno Solutions', + 'website': "https://www.cybrosys.com", + 'depends': ['account'], + 'data': [ + 'data/data.xml', + 'security/groups.xml', + 'security/ir.model.access.csv', + 'views/invoice_approval_view.xml', + 'views/account_move_inherited.xml', + ], + 'license': "AGPL-3", + 'images': ['static/description/banner.png'], + 'installable': True, + 'application': True, +} diff --git a/invoice_multi_approval/data/data.xml b/invoice_multi_approval/data/data.xml new file mode 100644 index 000000000..6e2af647f --- /dev/null +++ b/invoice_multi_approval/data/data.xml @@ -0,0 +1,9 @@ + + + + + True + True + + + \ No newline at end of file diff --git a/invoice_multi_approval/doc/RELEASE_NOTES.md b/invoice_multi_approval/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..9b45eccc6 --- /dev/null +++ b/invoice_multi_approval/doc/RELEASE_NOTES.md @@ -0,0 +1,6 @@ +## Module + +#### 31.10.2020 +#### Version 16.0.1.0.0 +##### ADD +- Initial commit diff --git a/invoice_multi_approval/models/__init__.py b/invoice_multi_approval/models/__init__.py new file mode 100644 index 000000000..cdce5df47 --- /dev/null +++ b/invoice_multi_approval/models/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies(). +# Author: Sayooj A O() +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# +from . import account_move +from . import invoice_approval diff --git a/invoice_multi_approval/models/account_move.py b/invoice_multi_approval/models/account_move.py new file mode 100644 index 000000000..8ca6a096d --- /dev/null +++ b/invoice_multi_approval/models/account_move.py @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies(). +# Author: Sayooj A O() +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# +from odoo import api, fields, models + + +class AccountMove(models.Model): + _inherit = 'account.move' + + approval_ids = fields.One2many('approval.line', 'move_id') + document_fully_approved = fields.Boolean(compute='_compute_document_fully_approved') + check_approve_ability = fields.Boolean(compute='_compute_check_approve_ability') + is_approved = fields.Boolean(compute='_compute_is_approved') + page_visibility = fields.Boolean(compute='_compute_page_visibility') + + @api.depends('approval_ids') + def _compute_page_visibility(self): + """Compute function for making the approval page visible/invisible""" + if self.approval_ids: + self.page_visibility = True + else: + self.page_visibility = False + + @api.onchange('partner_id') + def _onchange_partner_id(self): + """This is the onchange function of the partner which loads the + persons for the approval to the approver table of the account.move""" + res = super(AccountMove, self)._onchange_partner_id() + invoice_approval_id = self.env['invoice.approval'].search([]) + self.approval_ids = None + if invoice_approval_id.approve_customer_invoice and self.move_type == 'out_invoice': + for user in invoice_approval_id.invoice_approver_ids: + vals = { + 'approver_id': user.id + } + self.approval_ids |= self.approval_ids.new(vals) + elif invoice_approval_id.approve_vendor_bill and self.move_type == 'in_invoice': + for user in invoice_approval_id.bill_approver_ids: + vals = { + 'approver_id': user.id + } + self.approval_ids |= self.approval_ids.new(vals) + elif invoice_approval_id.approve_customer_credit and self.move_type == 'out_refund': + for user in invoice_approval_id.cust_credit_approver_ids: + vals = { + 'approver_id': user.id + } + self.approval_ids |= self.approval_ids.new(vals) + elif invoice_approval_id.approve_vendor_credit and self.move_type == 'in_refund': + for user in invoice_approval_id.vend_credit_approver_ids: + vals = { + 'approver_id': user.id + } + self.approval_ids |= self.approval_ids.new(vals) + return res + + @api.depends('approval_ids.approver_id') + def _compute_check_approve_ability(self): + """This is the compute function which check the current + logged in user is eligible or not for approving the document""" + current_user = self.env.uid + approvers_list = [] + for approver in self.approval_ids: + approvers_list.append(approver.approver_id.id) + if current_user in approvers_list: + self.check_approve_ability = True + else: + self.check_approve_ability = False + + def invoice_approve(self): + """This is the function of the approve button also + updates the approval table values according to the + approval of the users""" + self.ensure_one() + current_user = self.env.uid + for approval_id in self.approval_ids: + if current_user == approval_id.approver_id.id: + approval_id.update({'approval_status': True}) + + def _compute_is_approved(self): + """In this compute function we are verifying whether the document + is approved/not approved by the current logged in user""" + current_user = self.env.uid + if self.invoice_line_ids and self.approval_ids: + for approval_id in self.approval_ids: + if current_user == approval_id.approver_id.id: + if approval_id.approval_status: + self.is_approved = True + break + else: + self.is_approved = False + else: + self.is_approved = False + else: + self.is_approved = False + + @api.depends('approval_ids') + def _compute_document_fully_approved(self): + """This is the compute function which verifies whether + the document is completely approved or not""" + length_approval_ids = len(self.approval_ids) + approval_ids = self.approval_ids + approve_lines = approval_ids.filtered(lambda item: item.approval_status) + length_approve_lines = len(approve_lines) + if length_approval_ids == length_approve_lines: + self.document_fully_approved = True + else: + self.document_fully_approved = False + + +class ApprovalLine(models.Model): + _name = 'approval.line' + _description = 'Approval line in Move' + + move_id = fields.Many2one('account.move') + approver_id = fields.Many2one('res.users', string='Approver') + approval_status = fields.Boolean(string='Status') diff --git a/invoice_multi_approval/models/invoice_approval.py b/invoice_multi_approval/models/invoice_approval.py new file mode 100644 index 000000000..f61638871 --- /dev/null +++ b/invoice_multi_approval/models/invoice_approval.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2022-TODAY Cybrosys Technologies(). +# Author: Sayooj A O() +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# +from odoo import fields, models, _ +from odoo.exceptions import ValidationError + + +class InvoiceApproval(models.Model): + _name = 'invoice.approval' + _rec_name = 'name' + _inherit = ['mail.thread', 'mail.activity.mixin'] + _description = 'Invoice Approval' + + name = fields.Char(default='Approval Configuration') + approve_customer_invoice = fields.Boolean(string="Approval on Customer Invoice", + help='Enable this field for adding the approvals for the customer invoice') + invoice_approver_ids = fields.Many2many('res.users', 'invoice_id', string='Invoice Approver', domain=lambda self: [ + ('groups_id', 'in', self.env.ref('invoice_multi_approval.group_approver').id)], + help='In this field you can add the approvers for the customer invoice') + approve_vendor_bill = fields.Boolean(string="Approval on Vendor Bill", + help='Enable this field for adding the approvals for the Vendor bill') + bill_approver_ids = fields.Many2many('res.users', 'bill_id', string='Bill Approver', domain=lambda self: [ + ('groups_id', 'in', self.env.ref('invoice_multi_approval.group_approver').id)], + help='In this field you can add the approvers for the Vendor bill') + approve_customer_credit = fields.Boolean(string='Approval on Customer Refund', + help='Enable this field for adding the approvals for the customer credit note') + cust_credit_approver_ids = fields.Many2many('res.users', 'cust_credit_id', string='Customer Credit Note Approver', + domain=lambda self: [ + ('groups_id', 'in', + self.env.ref('invoice_multi_approval.group_approver').id)], + help='In this field you can add the approvers for the Customer credit note') + approve_vendor_credit = fields.Boolean(string='Approval on Vendor Refund', + help='Enable this field for adding the approvals for the Vendor credit note') + vend_credit_approver_ids = fields.Many2many('res.users', 'vend_credit_id', string='Vendor Credit Note Approver', + domain=lambda self: [ + ('groups_id', 'in', + self.env.ref('invoice_multi_approval.group_approver').id)], + help='In this field you can add the approvers for the Vendor credit note') + + def apply_configuration(self): + """Function for applying the approval configuration""" + return True diff --git a/invoice_multi_approval/security/groups.xml b/invoice_multi_approval/security/groups.xml new file mode 100644 index 000000000..1dbef2285 --- /dev/null +++ b/invoice_multi_approval/security/groups.xml @@ -0,0 +1,31 @@ + + + + + Invoice Approval + Access to the invoice approval menu + 3 + + + Approvers + + + + + Approve Manager + + + + + Billing Administrator + + + + + Billing + + + + + \ No newline at end of file diff --git a/invoice_multi_approval/security/ir.model.access.csv b/invoice_multi_approval/security/ir.model.access.csv new file mode 100644 index 000000000..c98787df0 --- /dev/null +++ b/invoice_multi_approval/security/ir.model.access.csv @@ -0,0 +1,7 @@ +id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink +invoice_approval_access_right_user_id,invoice_approval_access_right_user,model_invoice_approval,invoice_multi_approval.group_approver,1,1,1,1 +invoice_approval_access_right_manager_id,invoice_approval_access_right_manager,model_invoice_approval,invoice_multi_approval.group_approve_manager,1,1,1,1 +approval_line_access_right_user_id,approval_line_access_right_user,model_approval_line,invoice_multi_approval.group_approver,1,1,1,1 +approval_line_access_right_manager_id,approval_line_access_right_manager,model_approval_line,invoice_multi_approval.group_approve_manager,1,1,1,1 +approval_line_access_right_group_user_id,approval_line_access_right_group_user,model_approval_line,base.group_user,1,0,1,0 +invoice_approval_access_right_group_user_id,invoice_approval_access_right_group_user,model_invoice_approval,base.group_user,1,0,0,0 diff --git a/invoice_multi_approval/static/description/assets/icons/check.png b/invoice_multi_approval/static/description/assets/icons/check.png new file mode 100644 index 000000000..c8e85f51d Binary files /dev/null and b/invoice_multi_approval/static/description/assets/icons/check.png differ diff --git a/invoice_multi_approval/static/description/assets/icons/chevron.png b/invoice_multi_approval/static/description/assets/icons/chevron.png new file mode 100644 index 000000000..2089293d6 Binary files /dev/null and b/invoice_multi_approval/static/description/assets/icons/chevron.png differ diff --git a/invoice_multi_approval/static/description/assets/icons/cogs.png b/invoice_multi_approval/static/description/assets/icons/cogs.png new file mode 100644 index 000000000..95d0bad62 Binary files /dev/null and b/invoice_multi_approval/static/description/assets/icons/cogs.png differ diff --git a/invoice_multi_approval/static/description/assets/icons/consultation.png b/invoice_multi_approval/static/description/assets/icons/consultation.png new file mode 100644 index 000000000..8319d4baa Binary files /dev/null and b/invoice_multi_approval/static/description/assets/icons/consultation.png differ diff --git a/invoice_multi_approval/static/description/assets/icons/ecom-black.png b/invoice_multi_approval/static/description/assets/icons/ecom-black.png new file mode 100644 index 000000000..a9385ff13 Binary files /dev/null and b/invoice_multi_approval/static/description/assets/icons/ecom-black.png differ diff --git a/invoice_multi_approval/static/description/assets/icons/education-black.png b/invoice_multi_approval/static/description/assets/icons/education-black.png new file mode 100644 index 000000000..3eb09b27b Binary files /dev/null and b/invoice_multi_approval/static/description/assets/icons/education-black.png differ diff --git a/invoice_multi_approval/static/description/assets/icons/hotel-black.png b/invoice_multi_approval/static/description/assets/icons/hotel-black.png new file mode 100644 index 000000000..130f613be Binary files /dev/null and b/invoice_multi_approval/static/description/assets/icons/hotel-black.png differ diff --git a/invoice_multi_approval/static/description/assets/icons/license.png b/invoice_multi_approval/static/description/assets/icons/license.png new file mode 100644 index 000000000..a5869797e Binary files /dev/null and b/invoice_multi_approval/static/description/assets/icons/license.png differ diff --git a/invoice_multi_approval/static/description/assets/icons/lifebuoy.png b/invoice_multi_approval/static/description/assets/icons/lifebuoy.png new file mode 100644 index 000000000..658d56ccc Binary files /dev/null and b/invoice_multi_approval/static/description/assets/icons/lifebuoy.png differ diff --git a/invoice_multi_approval/static/description/assets/icons/manufacturing-black.png b/invoice_multi_approval/static/description/assets/icons/manufacturing-black.png new file mode 100644 index 000000000..697eb0e9f Binary files /dev/null and b/invoice_multi_approval/static/description/assets/icons/manufacturing-black.png differ diff --git a/invoice_multi_approval/static/description/assets/icons/pos-black.png b/invoice_multi_approval/static/description/assets/icons/pos-black.png new file mode 100644 index 000000000..97c0f90c1 Binary files /dev/null and b/invoice_multi_approval/static/description/assets/icons/pos-black.png differ diff --git a/invoice_multi_approval/static/description/assets/icons/puzzle.png b/invoice_multi_approval/static/description/assets/icons/puzzle.png new file mode 100644 index 000000000..65cf854e7 Binary files /dev/null and b/invoice_multi_approval/static/description/assets/icons/puzzle.png differ diff --git a/invoice_multi_approval/static/description/assets/icons/restaurant-black.png b/invoice_multi_approval/static/description/assets/icons/restaurant-black.png new file mode 100644 index 000000000..4a35eb939 Binary files /dev/null and b/invoice_multi_approval/static/description/assets/icons/restaurant-black.png differ diff --git a/invoice_multi_approval/static/description/assets/icons/service-black.png b/invoice_multi_approval/static/description/assets/icons/service-black.png new file mode 100644 index 000000000..301ab51cb Binary files /dev/null and b/invoice_multi_approval/static/description/assets/icons/service-black.png differ diff --git a/invoice_multi_approval/static/description/assets/icons/trading-black.png b/invoice_multi_approval/static/description/assets/icons/trading-black.png new file mode 100644 index 000000000..9398ba2f1 Binary files /dev/null and b/invoice_multi_approval/static/description/assets/icons/trading-black.png differ diff --git a/invoice_multi_approval/static/description/assets/icons/training.png b/invoice_multi_approval/static/description/assets/icons/training.png new file mode 100644 index 000000000..884ca024d Binary files /dev/null and b/invoice_multi_approval/static/description/assets/icons/training.png differ diff --git a/invoice_multi_approval/static/description/assets/icons/update.png b/invoice_multi_approval/static/description/assets/icons/update.png new file mode 100644 index 000000000..ecbc5a01a Binary files /dev/null and b/invoice_multi_approval/static/description/assets/icons/update.png differ diff --git a/invoice_multi_approval/static/description/assets/icons/user.png b/invoice_multi_approval/static/description/assets/icons/user.png new file mode 100644 index 000000000..6ffb23d9f Binary files /dev/null and b/invoice_multi_approval/static/description/assets/icons/user.png differ diff --git a/invoice_multi_approval/static/description/assets/icons/wrench.png b/invoice_multi_approval/static/description/assets/icons/wrench.png new file mode 100644 index 000000000..6c04dea0f Binary files /dev/null and b/invoice_multi_approval/static/description/assets/icons/wrench.png differ diff --git a/invoice_multi_approval/static/description/assets/misc/categories.png b/invoice_multi_approval/static/description/assets/misc/categories.png new file mode 100644 index 000000000..bedf1e0b1 Binary files /dev/null and b/invoice_multi_approval/static/description/assets/misc/categories.png differ diff --git a/invoice_multi_approval/static/description/assets/misc/check-box.png b/invoice_multi_approval/static/description/assets/misc/check-box.png new file mode 100644 index 000000000..42caf24b9 Binary files /dev/null and b/invoice_multi_approval/static/description/assets/misc/check-box.png differ diff --git a/invoice_multi_approval/static/description/assets/misc/compass.png b/invoice_multi_approval/static/description/assets/misc/compass.png new file mode 100644 index 000000000..d5fed8faa Binary files /dev/null and b/invoice_multi_approval/static/description/assets/misc/compass.png differ diff --git a/invoice_multi_approval/static/description/assets/misc/corporate.png b/invoice_multi_approval/static/description/assets/misc/corporate.png new file mode 100644 index 000000000..2eb13edbf Binary files /dev/null and b/invoice_multi_approval/static/description/assets/misc/corporate.png differ diff --git a/invoice_multi_approval/static/description/assets/misc/customer-support.png b/invoice_multi_approval/static/description/assets/misc/customer-support.png new file mode 100644 index 000000000..79efc72ed Binary files /dev/null and b/invoice_multi_approval/static/description/assets/misc/customer-support.png differ diff --git a/invoice_multi_approval/static/description/assets/misc/cybrosys-logo.png b/invoice_multi_approval/static/description/assets/misc/cybrosys-logo.png new file mode 100644 index 000000000..cc3cc0ccf Binary files /dev/null and b/invoice_multi_approval/static/description/assets/misc/cybrosys-logo.png differ diff --git a/invoice_multi_approval/static/description/assets/misc/features.png b/invoice_multi_approval/static/description/assets/misc/features.png new file mode 100644 index 000000000..b41769f77 Binary files /dev/null and b/invoice_multi_approval/static/description/assets/misc/features.png differ diff --git a/invoice_multi_approval/static/description/assets/misc/logo.png b/invoice_multi_approval/static/description/assets/misc/logo.png new file mode 100644 index 000000000..478462d3e Binary files /dev/null and b/invoice_multi_approval/static/description/assets/misc/logo.png differ diff --git a/invoice_multi_approval/static/description/assets/misc/pictures.png b/invoice_multi_approval/static/description/assets/misc/pictures.png new file mode 100644 index 000000000..56d255fe9 Binary files /dev/null and b/invoice_multi_approval/static/description/assets/misc/pictures.png differ diff --git a/invoice_multi_approval/static/description/assets/misc/pie-chart.png b/invoice_multi_approval/static/description/assets/misc/pie-chart.png new file mode 100644 index 000000000..426e05244 Binary files /dev/null and b/invoice_multi_approval/static/description/assets/misc/pie-chart.png differ diff --git a/invoice_multi_approval/static/description/assets/misc/right-arrow.png b/invoice_multi_approval/static/description/assets/misc/right-arrow.png new file mode 100644 index 000000000..730984a06 Binary files /dev/null and b/invoice_multi_approval/static/description/assets/misc/right-arrow.png differ diff --git a/invoice_multi_approval/static/description/assets/misc/star.png b/invoice_multi_approval/static/description/assets/misc/star.png new file mode 100644 index 000000000..2eb9ab29f Binary files /dev/null and b/invoice_multi_approval/static/description/assets/misc/star.png differ diff --git a/invoice_multi_approval/static/description/assets/misc/support.png b/invoice_multi_approval/static/description/assets/misc/support.png new file mode 100644 index 000000000..4f18b8b82 Binary files /dev/null and b/invoice_multi_approval/static/description/assets/misc/support.png differ diff --git a/invoice_multi_approval/static/description/assets/misc/whatsapp.png b/invoice_multi_approval/static/description/assets/misc/whatsapp.png new file mode 100644 index 000000000..d513a5356 Binary files /dev/null and b/invoice_multi_approval/static/description/assets/misc/whatsapp.png differ diff --git a/invoice_multi_approval/static/description/assets/modules/1.png b/invoice_multi_approval/static/description/assets/modules/1.png new file mode 100644 index 000000000..5238bdeab Binary files /dev/null and b/invoice_multi_approval/static/description/assets/modules/1.png differ diff --git a/invoice_multi_approval/static/description/assets/modules/2.png b/invoice_multi_approval/static/description/assets/modules/2.png new file mode 100644 index 000000000..1ae7cfe3b Binary files /dev/null and b/invoice_multi_approval/static/description/assets/modules/2.png differ diff --git a/invoice_multi_approval/static/description/assets/modules/3.png b/invoice_multi_approval/static/description/assets/modules/3.png new file mode 100644 index 000000000..3c3ff1afb Binary files /dev/null and b/invoice_multi_approval/static/description/assets/modules/3.png differ diff --git a/invoice_multi_approval/static/description/assets/modules/4.png b/invoice_multi_approval/static/description/assets/modules/4.png new file mode 100644 index 000000000..3fae4631e Binary files /dev/null and b/invoice_multi_approval/static/description/assets/modules/4.png differ diff --git a/invoice_multi_approval/static/description/assets/modules/5.gif b/invoice_multi_approval/static/description/assets/modules/5.gif new file mode 100644 index 000000000..2a5f8e659 Binary files /dev/null and b/invoice_multi_approval/static/description/assets/modules/5.gif differ diff --git a/invoice_multi_approval/static/description/assets/modules/6.png b/invoice_multi_approval/static/description/assets/modules/6.png new file mode 100644 index 000000000..7f2815273 Binary files /dev/null and b/invoice_multi_approval/static/description/assets/modules/6.png differ diff --git a/invoice_multi_approval/static/description/assets/screenshots/hero.gif b/invoice_multi_approval/static/description/assets/screenshots/hero.gif new file mode 100644 index 000000000..2f0dc71c6 Binary files /dev/null and b/invoice_multi_approval/static/description/assets/screenshots/hero.gif differ diff --git a/invoice_multi_approval/static/description/assets/screenshots/invoice_approval_01.png b/invoice_multi_approval/static/description/assets/screenshots/invoice_approval_01.png new file mode 100644 index 000000000..255608a2a Binary files /dev/null and b/invoice_multi_approval/static/description/assets/screenshots/invoice_approval_01.png differ diff --git a/invoice_multi_approval/static/description/assets/screenshots/invoice_approval_02.png b/invoice_multi_approval/static/description/assets/screenshots/invoice_approval_02.png new file mode 100644 index 000000000..60edb644e Binary files /dev/null and b/invoice_multi_approval/static/description/assets/screenshots/invoice_approval_02.png differ diff --git a/invoice_multi_approval/static/description/assets/screenshots/invoice_approval_03.png b/invoice_multi_approval/static/description/assets/screenshots/invoice_approval_03.png new file mode 100644 index 000000000..fdd4f394e Binary files /dev/null and b/invoice_multi_approval/static/description/assets/screenshots/invoice_approval_03.png differ diff --git a/invoice_multi_approval/static/description/assets/screenshots/invoice_approval_04.png b/invoice_multi_approval/static/description/assets/screenshots/invoice_approval_04.png new file mode 100644 index 000000000..7049f0809 Binary files /dev/null and b/invoice_multi_approval/static/description/assets/screenshots/invoice_approval_04.png differ diff --git a/invoice_multi_approval/static/description/assets/screenshots/invoice_approval_05.png b/invoice_multi_approval/static/description/assets/screenshots/invoice_approval_05.png new file mode 100644 index 000000000..a59c89ad6 Binary files /dev/null and b/invoice_multi_approval/static/description/assets/screenshots/invoice_approval_05.png differ diff --git a/invoice_multi_approval/static/description/banner.png b/invoice_multi_approval/static/description/banner.png new file mode 100644 index 000000000..7b0ac4b33 Binary files /dev/null and b/invoice_multi_approval/static/description/banner.png differ diff --git a/invoice_multi_approval/static/description/icon.png b/invoice_multi_approval/static/description/icon.png new file mode 100644 index 000000000..2638876e7 Binary files /dev/null and b/invoice_multi_approval/static/description/icon.png differ diff --git a/invoice_multi_approval/static/description/index.html b/invoice_multi_approval/static/description/index.html new file mode 100644 index 000000000..a6f769448 --- /dev/null +++ b/invoice_multi_approval/static/description/index.html @@ -0,0 +1,553 @@ +
+ +
+ +
+
+ Community +
+
+ Enterprise +
+
+ Odoo.sh +
+
+
+ + + +

Invoice + Multi Level Approval

+

Module Add the Multiple Approval + Option for Invoice, Bill, Refund and Credit Notes.

+ + + +
+ + +
+
+ +
+

Explore This + Module

+
+ + + + +
+
+ +
+

Overview +

+
+
+
+ The module allows to assign the users for the approval process in the invoice documents and the + document can be posted only after the approval process completed. +
+
+ + + +
+
+ +
+

Features +

+
+
+
+
+ + Seperate user groups for approver and approval managers. +
+
+ + TDocument can only validate when all approvals are completed. +
+
+ + Approval Option can be enabled/disabled from the configuration panel. +
+
+
+ + + +
+
+ +
+

Screenshots +

+
+
+
+ +
+

Two Security Groups

+

There are two security groups present "Approval User" and "Approval Manager".

+ +
+ +
+

Configure Approval Settings

+

There will be a menu for configuring the approval settings.

+ +
+ +
+

Select Approvers for Corresponding Documents

+

This is the configuration panel of approval. From here we can set the approvers for the + corresponding documents.

+ +
+ +
+

Track Approval Process Progress

+

There is a approval tab inside the documents from which we can see the progress of the + approval process and the list of persons included.

+ +
+ +
+

Approve Option for Users Included in the List.

+

There will a button "Approve" for the users who are included in the list.

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

Related + 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

+
+
+
+
+
+
+
+ +
+
+
+ \ No newline at end of file diff --git a/invoice_multi_approval/views/account_move_inherited.xml b/invoice_multi_approval/views/account_move_inherited.xml new file mode 100644 index 000000000..cc4409043 --- /dev/null +++ b/invoice_multi_approval/views/account_move_inherited.xml @@ -0,0 +1,48 @@ + + + + account.move.approval.inherited + account.move + + + + + + + + + +