Commit 2c3048c4 authored by Frank Bergmann's avatar Frank Bergmann

- Started to implement project-phases-volume indicator

parent fe89ad2a
<div id=@diagram_id@></div>
<script type='text/javascript' <if @::__csp_nonce@ not nil>nonce="@::__csp_nonce;literal@"</if>>
Ext.require(['Ext.chart.*', 'Ext.Window', 'Ext.fx.target.Sprite', 'Ext.layout.container.Fit']);
Ext.onReady(function () {
projectPhasesStore = Ext.create('Ext.data.Store', {
fields: ['date', 'planned_ts_value', 'total_planned_ts_value', 'timesheet', 'invoice', 'quote', 'po'],
autoLoad: true,
proxy: {
type: 'rest',
url: '/intranet-reporting-dashboard/project-eva.json',
extraParams: { // Parameters to the data-source
diagram_project_id: @diagram_project_id@ // Number of customers to show
},
reader: { type: 'json', root: 'data' }
}
});
projectEvaChart = new Ext.chart.Chart({
animate: false,
store: projectPhasesStore,
legend: { position: 'right' },
insetPadding: 20,
theme: 'Base:gradients',
axes: [{
type: 'Numeric',
minimum: 0,
position: 'left',
fields: [
'planned_ts_value',
'invoice',
'quote',
'po',
'timesheet'
]
}, {
type: 'Time',
position: 'bottom',
fields: 'date',
dateFormat: 'M d'
}],
series: [{
// Planned value composed of planned timesheet plus POs (purchase orders - external costs)
type: 'area',
axis: 'left',
xField: 'date',
yField: ['planned_ts_value', 'po'],
highlight: true
}, {
// Horizontal line for total planned value
type: 'line',
title: '@axis_title_total_planned_ts_value_l10n@',
axis: 'left',
xField: 'date',
yField: 'total_planned_ts_value',
showMarkers: false,
style: { fill: '#FF0000', stroke: '#FF0000', 'stroke-width': 1 }
}, {
// Invoices
type: 'line',
title: '@axis_title_invoices_l10n@',
axis: 'left',
xField: 'date',
yField: 'invoice',
showMarkers: false,
style: { stroke: '#@invoice_color@', 'stroke-width': 1 }
}, {
// Quotes
type: 'line',
title: '@axis_title_quotes_l10n@',
axis: 'left',
xField: 'date',
yField: 'quote',
showMarkers: false,
style: { stroke: '#@quote_color@', 'stroke-width': 1 }
}, {
// Actual costs area chart
type: 'area',
axis: 'left',
xField: 'date',
yField: ['timesheet', 'bills', 'expbundle'],
showMarkers: false,
tips: {
trackMouse: false,
renderer: function(storeItem, item) {
this.setTitle(storeItem.get('date'));
this.update(storeItem.get('total_planned_ts_value'));
}
},
style: {
fill: '#FF0000',
stroke: '#FF0000',
'stroke-width': 1
}
}]
});
var projectEvaPanel = Ext.create('widget.panel', {
width: @diagram_width@,
height: @diagram_height@,
title: '@diagram_title@',
renderTo: '@diagram_id@',
layout: 'fit',
header: false,
tbar: [{
xtype: 'combo',
editable: false,
store: false,
mode: 'local',
displayField: 'display',
valueField: 'value',
triggerAction: 'all',
width: 150,
forceSelection: true,
value: 'all_time',
listeners:{select:{fn:function(combo, comboValues) {
var value = comboValues[0].data.value;
var extraParams = projectPhasesStore.getProxy().extraParams;
extraParams.diagram_interval = value;
projectPhasesStore.load();
}
}
}
}],
items: projectEvaChart
});
});
</script>
# /packages/intranet-reporting-dashboard/lib/project-phases-volume.tcl
#
# Copyright (C) 2014 ]project-open[
#
# All rights reserved. Please check
# http://www.project-open.com/license/ for details.
# ----------------------------------------------------------------------
# Variables
# ---------------------------------------------------------------------
# The following variables are expected in the environment
# defined by the calling /tcl/*.tcl libary:
if {![info exists diagram_width]} { set diagram_width 600 }
if {![info exists diagram_height]} { set diagram_height 400 }
if {![info exists diagram_title]} { set diagram_title [lang::message::lookup "" intranet-reporting-dashboard.Project_Phases_Volume "Volume of Project Phases"] }
# Create a random ID for the diagram
set diagram_rand [expr {round(rand() * 100000000.0)}]
set diagram_id "project_phases_volume_$diagram_rand"
set default_currency [im_parameter -package_id [im_package_cost_id] "DefaultCurrency" "" "EUR"]
# ----------------------------------------------------------------------
# Calculate Diagram Parameters
# ---------------------------------------------------------------------
db_1row project_info "
select 1
"
......@@ -573,3 +573,24 @@ SELECT acs_permission__grant_permission(
'read'
);
-- Revenues by year over months
--
SELECT im_component_plugin__new (
null, 'im_component_plugin', now(), null, null, null,
'Volume of Project Phases', -- plugin_name
'intranet-reporting-dashboard', -- package_name
'top', -- location
'/intranet-invoices/dashboard', -- page_url
null, -- view_name
10, -- sort_order
'im_dashboard_project_phases_volume -diagram_width 600 -diagram_height 500',
'lang::message::lookup "" intranet-reporting-dashboard.Project_Phases_Volume "Volume of Project Phases"'
);
SELECT acs_permission__grant_permission(
(select plugin_id from im_component_plugins where plugin_name = 'Volume of Project Phases'),
(select group_id from groups where group_name = 'Senior Managers'),
'read'
);
......@@ -950,3 +950,35 @@ ad_proc -public im_dashboard_revenue_by_year_monthly {
# ---------------------------------------------------------------
# Revenues by month over year
# ---------------------------------------------------------------
ad_proc -public im_dashboard_project_phases_volume {
{-diagram_width 600}
{-diagram_height 500}
{-diagram_title ""}
} {
Returns a HTML component with a diagram of project volumes per phase
} {
# Sencha check and permissions
if {![im_sencha_extjs_installed_p]} { return "" }
set current_user_id [ad_conn user_id]
if {![im_permission $current_user_id view_finance]} { return "You don't have the right to see financial data" }
im_sencha_extjs_load_libraries
# Call the portlet page
set params [list \
[list diagram_width $diagram_width] \
[list diagram_height $diagram_height] \
[list diagram_title $diagram_title] \
]
set result [ad_parse_template -params $params "/packages/intranet-reporting-dashboard/lib/project-phases-volume"]
return [string trim $result]
}
# /packages/intranet-reporting-dashboard/www/project-phases-volume.tcl
#
# Copyright (C) 2014 ]project-open[
#
# All rights reserved. Please check
# http://www.project-open.com/license/ for details.
ad_page_contract {
Datasource for top-customers Sencha pie chart.
} {
}
# ----------------------------------------------------
# Defaults & Permissions
# ----------------------------------------------------
set current_user_id [ad_conn user_id]
if {![im_permission $current_user_id view_finance]} {
set json "{\"success\": false, \"message\": \"Insufficient permissions - you need the view_finance privilege to see this page.\" }"
doc_return 400 "application/json" $json
ad_script_abort
}
set default_currency [im_parameter -package_id [im_package_cost_id] "DefaultCurrency" "" "EUR"]
set default_hourly_cost [im_parameter -package_id [im_package_cost_id] "DefaultTimesheetHourlyCost" "" 30]
set message "Data loaded"
# ----------------------------------------------------
# Calculate diagram data
# ----------------------------------------------------
set sql "
select main_p.project_id as project_id,
main_p.project_name as project_name,
main_p.project_status_id,
-- Presales Opportunities
main_p.presales_value,
main_p.presales_probability,
-- Planned Hours
(
select sum(coalesce(t.planned_units,0))
from im_projects p,
im_timesheet_tasks t
where p.project_id = t.task_id and
p.tree_sortkey between main_p.tree_sortkey and tree_right(main_p.tree_sortkey) and
not exists (select project_id from im_projects leaf_p where leaf_p.parent_id = p.project_id)
) as planned_hours,
-- Value of planned hours
round((
select sum(coalesce(planned_units, 0) * coalesce(sum_hourly_rate, :default_hourly_cost::float) / (coalesce(sum_percentage)+0.00000001))
from (
select planned_units,
(
select sum(coalesce(bom.percentage, 100::numeric) * coalesce(e.hourly_cost, :default_hourly_cost::numeric))
from im_employees e,
acs_rels r,
im_biz_object_members bom
where r.object_id_one = p.project_id and
r.object_id_two = e.employee_id and
r.rel_id = bom.rel_id
) as sum_hourly_rate,
(
select sum(coalesce(bom.percentage, 100::numeric))
from acs_rels r,
im_biz_object_members bom
where r.object_id_one = p.project_id and
r.rel_id = bom.rel_id
) as sum_percentage
from im_projects p,
im_timesheet_tasks t
where p.project_id = t.task_id and
p.tree_sortkey between main_p.tree_sortkey and tree_right(main_p.tree_sortkey) and
not exists (select project_id from im_projects leaf_p where leaf_p.parent_id = p.project_id)
) t
)::numeric, 2) as planned_hours_value
from im_projects main_p
where main_p.parent_id is null and
main_p.project_status_id not in ([im_project_status_deleted])
"
ad_return_complaint 1 [im_ad_hoc_query -format html $sql]
# ----------------------------------------------------
# Format and return the data
# ----------------------------------------------------
set json [im_sencha_sql_to_store -include_empty_p 0 -data_source_p 1 -sql $sql]
doc_return 200 "application/json" $json
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment