12 changed files with 462 additions and 0 deletions
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Linto CT (<https://www.cybrosys.com>) |
|||
# |
|||
# 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 <https://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################### |
|||
import models |
@ -0,0 +1,41 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Linto CT (<https://www.cybrosys.com>) |
|||
# |
|||
# 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 <https://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################### |
|||
{ |
|||
'name': 'Donut Diagram For Sales', |
|||
'version': '10.0.1.0.0', |
|||
'category': 'Sales', |
|||
'summary': 'Donut Analysis on Salesperson Target.', |
|||
'description': 'We can analyse the total target and analysis of each salesperson.', |
|||
'author': 'Cybrosys Techno Solutions', |
|||
'maintainer': 'Cybrosys Techno Solutions', |
|||
'company': 'Cybrosys Techno Solutions', |
|||
'depends': ['crm', 'sale', 'sales_team'], |
|||
'website': 'https://www.cybrosys.com', |
|||
'data': [ |
|||
'views/templates.xml', |
|||
], |
|||
'images': ['static/description/banner.jpg'], |
|||
'license': 'AGPL-3', |
|||
'application': False, |
|||
'installable': True, |
|||
'auto_install': False, |
|||
} |
@ -0,0 +1,22 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Linto CT (<https://www.cybrosys.com>) |
|||
# |
|||
# 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 <https://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################### |
|||
import find_user_target |
@ -0,0 +1,122 @@ |
|||
# -*- coding: utf-8 -*- |
|||
################################################################################### |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
|||
# Author: Linto CT (<https://www.cybrosys.com>) |
|||
# |
|||
# 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 <https://www.gnu.org/licenses/>. |
|||
# |
|||
################################################################################### |
|||
import datetime |
|||
from odoo import models, fields |
|||
|
|||
|
|||
class CrmTargetAchievement(models.Model): |
|||
_inherit = 'crm.team' |
|||
|
|||
def find_target(self, uid): |
|||
"""This function will return the target and achievement in a list, |
|||
based on the user. |
|||
input: id of the user |
|||
output: list of dictionary with name and percentage """ |
|||
cr = self._cr |
|||
today = datetime.date.today() |
|||
begning = today.replace(day=1) |
|||
target = 0 |
|||
tmp = {} |
|||
achieved_total = 0 |
|||
if uid == 1: |
|||
# admin will see the details of all users |
|||
# taking all invoices |
|||
for user in self.env['res.users'].search([]): |
|||
target += user.target_sales_invoiced |
|||
cr.execute("select ai.user_id, sum(ai.amount_untaxed) as total from account_invoice ai" |
|||
" where ai.state in ('open', 'paid') and ai.type='out_invoice' " |
|||
" and ai.date_invoice >= %s group by ai.user_id", (begning,)) |
|||
achieved = cr.dictfetchall() |
|||
for i in achieved: |
|||
rec = self.env['res.users'].browse(i['user_id']) |
|||
tmp[rec.name] = i['total'] |
|||
achieved_total += i['total'] |
|||
|
|||
else: |
|||
# checking wheather this user is team lead or not |
|||
team = self.env['crm.team'].search([('user_id', '=', self._uid)], limit=1) |
|||
if team: |
|||
# this user is team lead |
|||
members = team.member_ids |
|||
# taking team member's targets' |
|||
for member in members: |
|||
target += member.target_sales_invoiced |
|||
# taking his target |
|||
target += self.env.user.target_sales_invoiced |
|||
ids = members.ids |
|||
ids.append(self._uid) |
|||
cr.execute("select ai.user_id, sum(ai.amount_untaxed) as total from account_invoice ai" |
|||
" where ai.state in ('open', 'paid') and ai.type='out_invoice' " |
|||
" and ai.user_id in %s and ai.date_invoice >= %s group by ai.user_id", |
|||
(tuple(ids), begning)) |
|||
achieved = cr.dictfetchall() |
|||
|
|||
for i in achieved: |
|||
rec = self.env['res.users'].browse(i['user_id']) |
|||
tmp[rec.name] = i['total'] |
|||
achieved_total += i['total'] |
|||
|
|||
else: |
|||
# this is just a user, not a team lead |
|||
target += self.env.user.target_sales_invoiced |
|||
cr.execute("select sum(amount_untaxed) as total from account_invoice " |
|||
" where state in ('open', 'paid') and ai.type='out_invoice' " |
|||
" and date_invoice >= %s and user_id=%s", (begning, self._uid)) |
|||
invoices = cr.dictfetchall() |
|||
|
|||
for i in invoices: |
|||
tmp[self.env.user.name] = i['total'] |
|||
achieved_total += i['total'] |
|||
# checking the achieved amount is greater than target or not |
|||
target_bal = target - achieved_total |
|||
result = [] |
|||
|
|||
if target_bal < 0: |
|||
# achieved amount is greater than target |
|||
for i in tmp: |
|||
temp = { |
|||
'name': i + ":" + str(tmp[i]), |
|||
'percent': round((tmp[i] / target) * 100, 1), |
|||
} |
|||
result.append(temp) |
|||
# taking the difference in target and achieved |
|||
temp = { |
|||
'name': 'Target Exceeded ' + ":" + str(-1*target_bal), |
|||
'percent': round(-1 * (target_bal / target) * 100, 1), |
|||
} |
|||
result.append(temp) |
|||
else: |
|||
# achieved amount is lesser than or equal to target |
|||
for i in tmp: |
|||
temp = { |
|||
'name': i + ":" + str(tmp[i]), |
|||
'percent': round((tmp[i] / target) * 100, 1), |
|||
} |
|||
result.append(temp) |
|||
# taking the difference in target and achieved |
|||
temp = { |
|||
'name': 'Target Pending ' + ":" + str(target_bal), |
|||
'percent': round((target_bal / target) * 100, 1), |
|||
} |
|||
result.append(temp) |
|||
|
|||
return result |
After Width: | Height: | Size: 87 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 51 KiB |
After Width: | Height: | Size: 34 KiB |
@ -0,0 +1,102 @@ |
|||
<section class="oe_container"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h2 class="oe_slogan">Donut Diagram For Sales</h2> |
|||
<h3 class="oe_slogan">Target vs Achievement Analysis With The Help of a Donut Diagram</h3> |
|||
<h4 class="oe_slogan"><a href="https://www.cybrosys.com">Cybrosys Technologies</a> </h4> |
|||
</div> |
|||
<div class="oe_row oe_spaced" style="padding-left:65px;"> |
|||
<h4>Features:</h4> |
|||
<div> |
|||
<span style="color:green;"> ☑ </span> Admin can see total target and achievements of each employee.<br/> |
|||
<span style="color:green;"> ☑ </span> Team leader can see the performance chart of his team.<br/> |
|||
<span style="color:green;"> ☑ </span> Each team member can see his own performance chart.<br/> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container oe_dark"> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_picture"> |
|||
<h3 class="oe_slogan">Overview</h3> |
|||
<p class="oe_mt32"> |
|||
The module gives a detailed analysis report of the Invoice target and Achievement of the |
|||
Individual employee, Team as well as the Organization. The administrator and Team Lead |
|||
can view their own individual achievements well as Employee/Member wise achievements. |
|||
The employee can see their individual performance also. Everything is presented as donut |
|||
chart. |
|||
</p> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container"> |
|||
<div class="oe_row oe_spaced"> |
|||
<div> |
|||
<div class="oe_span12"> |
|||
<div class="oe_demo oe_picture oe_screenshot"> |
|||
<img src="donut-sample-dashboard.png"> |
|||
</div> |
|||
</div> |
|||
<br><br><br> |
|||
<p>For the perfect working of this module, first, we have to configure targets for the users. If you |
|||
are using sales teams, you have to configure sales teams and team members first. |
|||
</p> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
<section class="oe_container oe_dark"> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class=""> |
|||
<p> |
|||
The administrator can see the total target and achievements of each salesperson in a donut |
|||
chart. In the chart, you can see the percentage of amount achieved by each user. The amount |
|||
invoiced by each user will be specified near the chart. |
|||
</p> |
|||
<p> |
|||
The calculation is as follows, first, the system will take the targets of all the users, and then it |
|||
will consider each employees achievements. You can also see the difference between the total |
|||
target and total achieved amount. |
|||
</p> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container"> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class=""> |
|||
<p> |
|||
For the team lead, he will see the total target of his team including the team lead if there are any |
|||
and the amount achieved by each members including team lead. |
|||
<p> |
|||
<p> |
|||
For the salesperson, he will see his target and the amount invoiced by him. |
|||
</p> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container oe_dark"> |
|||
<h2 class="oe_slogan" style="margin-top:20px;" >Need Any Help?</h2> |
|||
<div class="oe_slogan" style="margin-top:10px !important;"> |
|||
<div> |
|||
<a class="btn btn-primary btn-lg mt8" |
|||
style="color: #FFFFFF !important;border-radius: 0;" href="https://www.cybrosys.com"><i |
|||
class="fa fa-envelope"></i> Email </a> <a |
|||
class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;border-radius: 0;" |
|||
href="https://www.cybrosys.com/contact/"><i |
|||
class="fa fa-phone"></i> Contact Us </a> <a |
|||
class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;border-radius: 0;" |
|||
href="https://www.cybrosys.com/odoo-customization-and-installation/"><i |
|||
class="fa fa-check-square"></i> Request Customization </a> |
|||
</div> |
|||
<br> |
|||
<img src="cybro_logo.png" style="width: 190px; margin-bottom: 20px;" class="center-block"> |
|||
<div> |
|||
<a href="https://twitter.com/cybrosys" target="_blank"><i class="fa fa-2x fa-twitter" style="color:white;background: #00a0d1;width:35px;"></i></a></td> |
|||
<a href="https://www.linkedin.com/company/cybrosys-technologies-pvt-ltd" target="_blank"><i class="fa fa-2x fa-linkedin" style="color:white;background: #31a3d6;width:35px;padding-left: 3px;"></i></a></td> |
|||
<a href="https://www.facebook.com/cybrosystechnologies" target="_blank"><i class="fa fa-2x fa-facebook" style="color:white;background: #3b5998;width:35px;padding-left: 8px;"></i></a></td> |
|||
<a href="https://plus.google.com/106641282743045431892/about" target="_blank"><i class="fa fa-2x fa-google-plus" style="color:white;background: #c53c2c;width:35px;padding-left: 3px;"></i></a></td> |
|||
<a href="https://in.pinterest.com/cybrosys" target="_blank"><i class="fa fa-2x fa-pinterest" style="color:white;background: #ac0f18;width:35px;padding-left: 3px;"></i></a></td> |
|||
</div> |
|||
</div> |
|||
</section> |
@ -0,0 +1,3 @@ |
|||
.dashboard_donut_chart{ |
|||
margin-left: 25%; |
|||
} |
@ -0,0 +1,139 @@ |
|||
odoo.define('target_achievement_invoice.dashboard', function (require) { |
|||
"use strict"; |
|||
var core = require('web.core'); |
|||
var CrmDashboard = require('sales_team.dashboard'); |
|||
var Model = require('web.Model'); |
|||
var QWeb = core.qweb; |
|||
CrmDashboard.include({ |
|||
render: function() { |
|||
this._super(); |
|||
var self = this; |
|||
self.fetch_data().then(function(result) { |
|||
var sales_dashboard = QWeb.render('sales_team.SalesDashboard', { |
|||
widget: self, |
|||
show_demo: self.show_demo, |
|||
values: result, |
|||
}); |
|||
|
|||
var pie_div = "<div class='dashboard_donut_chart'></div>"; |
|||
var $pie_div = $(pie_div); |
|||
|
|||
var width = 550; |
|||
var height = 350; |
|||
var radius = height/2; |
|||
var color = d3.scale.category10(); |
|||
// getting data to show
|
|||
var uid = self.dataset.context.uid; |
|||
new Model('crm.team').call('find_target', ['', uid]).done(function (res_data) { |
|||
console.log("res_data: ", res_data) |
|||
var dataset = res_data; |
|||
|
|||
var pie=d3.layout.pie() |
|||
.value(function(d){return d.percent}) |
|||
.sort(null) |
|||
.padAngle(.03); |
|||
|
|||
var w=300,h=300; |
|||
|
|||
var outerRadius=w/2; |
|||
var innerRadius=85; |
|||
|
|||
var color = d3.scale.category10(); |
|||
|
|||
var arc=d3.svg.arc() |
|||
.outerRadius(outerRadius) |
|||
.innerRadius(innerRadius); |
|||
|
|||
var svg=d3.select($pie_div[0]) |
|||
.append("svg") |
|||
.attr({ |
|||
width:w+300, |
|||
height:h, |
|||
class:'shadow' |
|||
}).append('g') |
|||
.attr({ |
|||
transform:'translate('+w/2+','+h/2+')' |
|||
}); |
|||
var path=svg.selectAll('path') |
|||
.data(pie(dataset)) |
|||
.enter() |
|||
.append('path') |
|||
.attr({ |
|||
d:arc, |
|||
fill:function(d,i){ |
|||
return color(d.data.name); |
|||
} |
|||
}); |
|||
|
|||
var text=svg.selectAll('text') |
|||
.data(pie(dataset)) |
|||
.enter() |
|||
.append("text") |
|||
.attr("transform", function (d) { |
|||
return "translate(" + arc.centroid(d) + ")"; |
|||
}) |
|||
.attr("dy", ".4em") |
|||
.attr("text-anchor", "middle") |
|||
.text(function(d){ |
|||
return d.data.percent+"%"; |
|||
}) |
|||
.style({ |
|||
fill:'black', |
|||
'font-size':'10px', |
|||
'color':'black' |
|||
}); |
|||
var legendRectSize=20; |
|||
var legendSpacing=7; |
|||
var legendHeight=legendRectSize+legendSpacing; |
|||
|
|||
|
|||
var legend=svg.selectAll('.legend') |
|||
.data(color.domain()) |
|||
.enter() |
|||
.append('g') |
|||
.attr({ |
|||
class:'legend', |
|||
transform:function(d,i){ |
|||
//Just a calculation for x and y position
|
|||
return 'translate(185,' + ((i*legendHeight)-65) + ')'; |
|||
} |
|||
}); |
|||
legend.append('rect') |
|||
.attr({ |
|||
width:legendRectSize, |
|||
height:legendRectSize, |
|||
rx:70, |
|||
ry:20 |
|||
}) |
|||
.style({ |
|||
fill:color, |
|||
stroke:color |
|||
}); |
|||
|
|||
legend.append('text') |
|||
.attr({ |
|||
x:75, |
|||
y:15 |
|||
}) |
|||
.text(function(d){ |
|||
return d; |
|||
}).style({ |
|||
fill:'#929DAF', |
|||
'font-size':'14px' |
|||
}); |
|||
|
|||
var target = svg.select('target') |
|||
.data("Target") |
|||
.enter() |
|||
.append('g'); |
|||
|
|||
var html_string = $pie_div[0].outerHTML; |
|||
$(html_string).prependTo(self.$el); |
|||
}); |
|||
}); |
|||
return; |
|||
}, |
|||
}); |
|||
|
|||
}); |
|||
|
@ -0,0 +1,11 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
<template id="assets_backend" name="donut_dashboard" inherit_id="web.assets_backend"> |
|||
<xpath expr="." position="inside"> |
|||
<script type="text/javascript" src="/target_achievement_invoice/static/src/js/pie_dashboard.js"></script> |
|||
<link href="/target_achievement_invoice/static/src/css/style.css" rel="stylesheet"/> |
|||
</xpath> |
|||
</template> |
|||
</data> |
|||
</openerp> |
Loading…
Reference in new issue