brotherton-erpnext/erpnext/selling/page/sales_funnel/sales_funnel.js

186 lines
4.8 KiB
JavaScript
Raw Normal View History

2013-11-20 07:29:58 +00:00
// Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
2013-10-04 15:49:30 +00:00
// License: GNU General Public License v3. See license.txt
2014-12-19 10:50:32 +00:00
frappe.pages['sales-funnel'].onload = function(wrapper) {
2014-02-14 10:17:51 +00:00
frappe.ui.make_app_page({
2013-10-04 15:49:30 +00:00
parent: wrapper,
2014-09-10 07:36:53 +00:00
title: __('Sales Funnel'),
2013-10-04 15:49:30 +00:00
single_column: true
});
2014-12-19 10:50:32 +00:00
2013-10-31 13:36:11 +00:00
wrapper.sales_funnel = new erpnext.SalesFunnel(wrapper);
2014-12-19 10:50:32 +00:00
frappe.add_breadcrumbs("Selling");
2013-10-04 15:49:30 +00:00
}
2013-10-31 13:36:11 +00:00
erpnext.SalesFunnel = Class.extend({
2013-10-04 15:49:30 +00:00
init: function(wrapper) {
var me = this;
// 0 setTimeout hack - this gives time for canvas to get width and height
2014-12-19 10:50:32 +00:00
setTimeout(function() {
2013-10-04 15:49:30 +00:00
me.setup(wrapper);
me.get_data();
}, 0);
},
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
setup: function(wrapper) {
var me = this;
2014-12-19 10:50:32 +00:00
this.elements = {
2013-10-04 15:49:30 +00:00
layout: $(wrapper).find(".layout-main"),
2014-09-10 07:36:53 +00:00
from_date: wrapper.appframe.add_date(__("From Date")),
to_date: wrapper.appframe.add_date(__("To Date")),
2014-12-19 10:50:32 +00:00
refresh_btn: wrapper.appframe.set_title_right(__("Refresh"),
2013-10-04 15:49:30 +00:00
function() { me.get_data(); }, "icon-refresh"),
};
2014-12-19 10:50:32 +00:00
2014-09-10 07:36:53 +00:00
this.elements.no_data = $('<div class="alert alert-warning">' + __("No Data") + '</div>')
2013-10-04 15:49:30 +00:00
.toggle(false)
.appendTo(this.elements.layout);
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
this.elements.funnel_wrapper = $('<div class="funnel-wrapper text-center"></div>')
.appendTo(this.elements.layout);
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
this.options = {
2014-02-14 10:17:51 +00:00
from_date: frappe.datetime.add_months(frappe.datetime.get_today(), -1),
to_date: frappe.datetime.get_today()
2013-10-04 15:49:30 +00:00
};
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
// set defaults and bind on change
2014-12-19 10:50:32 +00:00
$.each(this.options, function(k, v) {
me.elements[k].val(frappe.datetime.str_to_user(v));
2013-10-04 15:49:30 +00:00
me.elements[k].on("change", function() {
2014-02-14 10:17:51 +00:00
me.options[k] = frappe.datetime.user_to_str($(this).val());
2013-10-04 15:49:30 +00:00
me.get_data();
});
});
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
// bind refresh
this.elements.refresh_btn.on("click", function() {
me.get_data(this);
});
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
// bind resize
$(window).resize(function() {
me.render();
});
},
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
get_data: function(btn) {
var me = this;
2014-02-14 10:17:51 +00:00
frappe.call({
2014-02-06 07:44:15 +00:00
method: "erpnext.selling.page.sales_funnel.sales_funnel.get_funnel_data",
2013-10-04 15:49:30 +00:00
args: {
from_date: this.options.from_date,
to_date: this.options.to_date
},
btn: btn,
callback: function(r) {
if(!r.exc) {
me.options.data = r.message;
me.render();
}
}
});
},
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
render: function() {
var me = this;
this.prepare();
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
var context = this.elements.context,
x_start = 0.0,
x_end = this.options.width,
x_mid = (x_end - x_start) / 2.0,
y = 0,
y_old = 0.0;
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
if(this.options.total_value === 0) {
this.elements.no_data.toggle(true);
return;
}
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
this.options.data.forEach(function(d) {
context.fillStyle = d.color;
context.strokeStyle = d.color;
me.draw_triangle(x_start, x_mid, x_end, y, me.options.height);
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
y_old = y;
// new y
y = y + d.height;
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
// new x
var half_side = (me.options.height - y) / Math.sqrt(3);
x_start = x_mid - half_side;
x_end = x_mid + half_side;
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
var y_mid = y_old + (y - y_old) / 2.0;
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
me.draw_legend(x_mid, y_mid, me.options.width, me.options.height, d.value + " - " + d.title);
});
},
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
prepare: function() {
var me = this;
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
this.elements.no_data.toggle(false);
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
// calculate width and height options
this.options.width = $(this.elements.funnel_wrapper).width() * 2.0 / 3.0;
this.options.height = (Math.sqrt(3) * this.options.width) / 2.0;
2014-12-19 10:50:32 +00:00
// calculate total weightage
// as height decreases, area decreases by the square of the reduction
// hence, compensating by squaring the index value
this.options.total_weightage = this.options.data.reduce(
function(prev, curr, i) { return prev + Math.pow(i+1, 2) * curr.value; }, 0.0);
2014-12-19 10:50:32 +00:00
// calculate height for each data
$.each(this.options.data, function(i, d) {
d.height = me.options.height * d.value * Math.pow(i+1, 2) / me.options.total_weightage;
});
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
this.elements.canvas = $('<canvas></canvas>')
.appendTo(this.elements.funnel_wrapper.empty())
.attr("width", $(this.elements.funnel_wrapper).width())
.attr("height", this.options.height);
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
this.elements.context = this.elements.canvas.get(0).getContext("2d");
},
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
draw_triangle: function(x_start, x_mid, x_end, y, height) {
var context = this.elements.context;
context.beginPath();
context.moveTo(x_start, y);
context.lineTo(x_end, y);
context.lineTo(x_mid, height);
context.lineTo(x_start, y);
context.closePath();
context.fill();
},
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
draw_legend: function(x_mid, y_mid, width, height, title) {
var context = this.elements.context;
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
// draw line
context.beginPath();
context.moveTo(x_mid, y_mid);
context.lineTo(width, y_mid);
context.closePath();
context.stroke();
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
// draw circle
context.beginPath();
context.arc(width, y_mid, 5, 0, Math.PI * 2, false);
context.closePath();
context.fill();
2014-12-19 10:50:32 +00:00
2013-10-04 15:49:30 +00:00
// draw text
context.fillStyle = "black";
context.textBaseline = "middle";
context.font = "1.1em sans-serif";
context.fillText(title, width + 20, y_mid);
}
2014-12-19 10:50:32 +00:00
});