commit 905dfd256de8c2731b07418a5aabc18bc44f9489
parent 8c53762f6b9125e0379858344b5697110f01d9d9
Author: Felicitus <felicitus@felicitus.org>
Date: Fri, 9 Sep 2011 09:28:34 +0200
Added initial chart support
Diffstat:
5 files changed, 239 insertions(+), 21 deletions(-)
diff --git a/frontend/js/Components/MenuBar.js b/frontend/js/Components/MenuBar.js
@@ -33,8 +33,17 @@ Ext.define('PartKeepr.MenuBar', {
icon: "resources/fugue-icons/icons/ruler.png"
},{
text: i18n("Statistics"),
- handler: this.showStatistics,
- icon: 'resources/silkicons/chart_bar.png'
+ icon: 'resources/silkicons/chart_bar.png',
+ menu: [
+ {
+ text: i18n("Summary"),
+ handler: this.showStatisticsSummary,
+ icon: 'resources/silkicons/chart_bar.png'
+ },{
+ text: i18n("Chart"),
+ handler: this.showStatisticsChart,
+ icon: 'resources/silkicons/chart_bar.png'
+ }]
},{
text: i18n("Units"),
handler: this.editUnits,
@@ -106,7 +115,7 @@ Ext.define('PartKeepr.MenuBar', {
PartKeepr.getApplication().addItem(j);
j.show();
},
- showStatistics: function () {
+ showStatisticsSummary: function () {
var j = Ext.create("PartKeepr.CurrentStatisticsPanel", {
iconCls: 'icon-chart-bar',
closable: true
@@ -116,6 +125,16 @@ Ext.define('PartKeepr.MenuBar', {
PartKeepr.getApplication().addItem(j);
j.show();
},
+ showStatisticsChart: function () {
+ var j = Ext.create("PartKeepr.StatisticsChartPanel", {
+ iconCls: 'icon-chart-bar',
+ closable: true
+ });
+
+
+ PartKeepr.getApplication().addItem(j);
+ j.show();
+ },
editStorageLocations: function () {
var j = Ext.create("PartKeepr.StorageLocationEditorComponent", {
title: i18n("Storage Locations"),
diff --git a/frontend/js/Components/Statistics/StatisticsChartPanel.js b/frontend/js/Components/Statistics/StatisticsChartPanel.js
@@ -0,0 +1,92 @@
+Ext.define('PartKeepr.StatisticsChartPanel', {
+ extend: 'Ext.chart.Chart',
+ shadow: true,
+ title: i18n("Statistics Chart"),
+ legend: {
+ position: 'right'
+ },
+ background: {
+ fill: '#fff'
+ },
+ axes: [{
+ type: 'Numeric',
+ minimum: 0,
+ position: 'left',
+ fields: ['parts', 'categories'],
+ title: i18n("Count"),
+ minorTickSteps: 1,
+ grid: {
+ odd: {
+ opacity: 1,
+ fill: '#ddd',
+ stroke: '#bbb',
+ 'stroke-width': 0.5
+ }
+ }
+ }, {
+ type: 'Time',
+ dateFormat: 'Y-m-d',
+ position: 'bottom',
+ fields: ['start'],
+ title: i18n("Date")
+ }],
+ series: [{
+ type: 'line',
+ highlight: {
+ size: 7,
+ radius: 7
+ },
+ axis: 'left',
+ xField: 'start',
+ yField: 'parts',
+ title: i18n("Parts"),
+ markerConfig: {
+ type: 'cross',
+ size: 4,
+ radius: 4,
+ 'stroke-width': 0
+ }
+ }, {
+ type: 'line',
+ highlight: {
+ size: 7,
+ radius: 7
+ },
+ axis: 'left',
+ title: i18n("Categories"),
+ smooth: true,
+ xField: 'start',
+ yField: 'categories',
+ markerConfig: {
+ type: 'circle',
+ size: 4,
+ radius: 4,
+ 'stroke-width': 0
+ }
+ }],
+ initComponent: function () {
+ this.store = Ext.create("Ext.data.Store", {
+ model: 'PartKeepr.StatisticSample',
+ proxy: {
+ type: 'ajax',
+ reader: {
+ type: 'json',
+ root: 'response.data'
+ },
+ url : 'service.php',
+ extraParams: {
+ "service": "Statistic",
+ "call": "getSampledStatistics",
+ "startDateTime": "2011-01-01 00:00:00",
+ "endDateTime": "2011-12-01 00:00:00"
+ },
+ headers: {
+ session :PartKeepr.getApplication().getSession()
+ }
+ },
+ autoLoad: true
+ });
+
+ this.callParent();
+ }
+});+
\ No newline at end of file
diff --git a/frontend/js/Models/StatisticSample.js b/frontend/js/Models/StatisticSample.js
@@ -0,0 +1,8 @@
+Ext.define("PartKeepr.StatisticSample", {
+ extend: "Ext.data.Model",
+ fields: [
+ { name: 'start', type: 'date'},
+ { name: 'parts', type: 'int'},
+ { name: 'categories', type: 'int'}
+ ]
+});+
\ No newline at end of file
diff --git a/frontend/service.php b/frontend/service.php
@@ -13,7 +13,13 @@ PartKeepr::initialize("");
try {
$request = $_REQUEST;
- $request["parameters"] = json_decode($_REQUEST["parameters"], true);
+
+ if (array_key_exists("parameters", $_REQUEST)) {
+ $request["parameters"] = json_decode($_REQUEST["parameters"], true);
+ } else {
+ $request["parameters"] = $_REQUEST;
+ }
+
$response = array();
$response["status"] = "ok";
diff --git a/src/de/RaumZeitLabor/PartKeepr/Statistic/StatisticService.php b/src/de/RaumZeitLabor/PartKeepr/Statistic/StatisticService.php
@@ -9,29 +9,120 @@ use de\RaumZeitLabor\PartKeepr\PartKeepr,
de\RaumZeitLabor\PartKeepr\PartUnit\PartUnitManager;
class StatisticService extends Service {
- public function getCurrentStats () {
+ public function getCurrentStats () {
- $aData = array();
- $aData["partCount"] = PartManager::getInstance()->getPartCount();
- $aData["categoryCount"] = PartCategoryManager::getInstance()->getCategoryCount();
- $aData["totalPrice"] = PartManager::getInstance()->getTotalPrice();
- $aData["averagePrice"] = PartManager::getInstance()->getAveragePrice();
- $aData["partsWithPrice"] = PartManager::getInstance()->getPartCount(true);
- $aData["partsWithoutPrice"] = $aData["partCount"] - $aData["partsWithPrice"];
-
- $result = PartUnitManager::getInstance()->getUnitCounts();
+ $aData = array();
+ $aData["partCount"] = PartManager::getInstance()->getPartCount();
+ $aData["categoryCount"] = PartCategoryManager::getInstance()->getCategoryCount();
+ $aData["totalPrice"] = PartManager::getInstance()->getTotalPrice();
+ $aData["averagePrice"] = PartManager::getInstance()->getAveragePrice();
+ $aData["partsWithPrice"] = PartManager::getInstance()->getPartCount(true);
+ $aData["partsWithoutPrice"] = $aData["partCount"] - $aData["partsWithPrice"];
+
+ $result = PartUnitManager::getInstance()->getUnitCounts();
+
+ $aUnits = array();
+
+ foreach ($result as $row) {
+ $aUnits[] = array(
+ "name" => $row[0]->getName(),
+ "stockLevel" => $row["stockLevel"]);
+ }
+
+ $aData["units"] = $aUnits;
+
+ return $aData;
+ }
- $aUnits = array();
+ /**
+ * Returns sampled statistics from the database.
+ *
+ * This call takes a start and an end time, and calculates a set of statistics
+ * for each interval.
+ *
+ * The sampleSize, which has a default of 50, specifies how many single statistic
+ * points in the given date interval will be returned.
+ *
+ * This function interpolates the statistics if there are not enough statistic samples available.
+ */
+ public function getSampledStatistics () {
+ $fooStart = microtime(true);
+
+ $this->requireParameter("startDateTime");
+ $this->requireParameter("endDateTime");
+
+
+ $start = \DateTime::createFromFormat("Y-m-d H:i:s", $this->getParameter("startDateTime"));
+ $end = \DateTime::createFromFormat("Y-m-d H:i:s", $this->getParameter("endDateTime"));
+
+ if ($this->hasParameter("sampleSize")) {
+ $sampleSize = $this->getParameter("sampleSize");
+ } else {
+ $sampleSize = 50;
+ }
+
+ $intervalSize = intval(($end->getTimestamp() - $start->getTimestamp()) / $sampleSize);
+
+ $queryStartTime = clone $start;
+ $queryEndTime = clone $start;
+ $queryEndTime->add(new \DateInterval("PT".$intervalSize."S"));
+
+ $partUnitQuery = "SELECT pu FROM de\RaumZeitLabor\PartKeepr\Part\PartUnit pu";
+ $query = PartKeepr::getEM()->createQuery($partUnitQuery);
+
+ $aPartUnits = $query->getResult();
+
+ $aRecords = array();
+
+ $dql = "SELECT AVG(sts.parts) AS parts, AVG(sts.categories) AS categories FROM de\RaumZeitLabor\PartKeepr\Statistic\StatisticSnapshot sts WHERE sts.dateTime >= :start AND sts.dateTime <= :end";
+ $mainQuery = PartKeepr::getEM()->createQuery($dql);
+
+ $dql = "SELECT AVG(stsu.stockLevel) AS stockLevel FROM de\RaumZeitLabor\PartKeepr\Statistic\StatisticSnapshotUnit stsu JOIN stsu.statisticSnapshot sts WHERE sts.dateTime >= :start AND sts.dateTime <= :end AND stsu.partUnit = :partUnit";
+ $subQuery = PartKeepr::getEM()->createQuery($dql);
+
+ for ($i=0;$i<$sampleSize;$i++) {
+
+
+ $mainQuery->setParameter("start", $queryStartTime);
+ $mainQuery->setParameter("end", $queryEndTime);
+
+ $result = $mainQuery->getResult();
- foreach ($result as $row) {
- $aUnits[] = array(
- "name" => $row[0]->getName(),
- "stockLevel" => $row["stockLevel"]);
+ $record = $result[0];
+
+ if ($record["parts"] !== null) {
+ $record["parts"] = floatval($record["parts"]);
+ }
+
+ if ($record["categories"] !== null) {
+ $record["categories"] = floatval($record["categories"]);
}
- $aData["units"] = $aUnits;
+ foreach ($aPartUnits as $partUnit) {
+ $subQuery->setParameter("start", $queryStartTime);
+ $subQuery->setParameter("end", $queryEndTime);
+ $subQuery->setParameter("partUnit", $partUnit);
+
+ $aResult = $subQuery->getResult();
+
+ if ($aResult[0]["stockLevel"] !== null) {
+ $record["units"][$partUnit->getName()] = floatval($aResult[0]["stockLevel"]);
+ } else {
+ $record["units"][$partUnit->getName()] = null;
+ }
+
+ }
+
+ $record["start"] = $queryStartTime->format("Y-m-d H:i:s");
+
+ $aRecords[] = $record;
- return $aData;
+ $queryStartTime->add(new \DateInterval("PT".$intervalSize."S"));
+ $queryEndTime->add(new \DateInterval("PT".$intervalSize."S"));
}
+
+
+ return array("status" => "ok", "data" => $aRecords);
+ }
}
\ No newline at end of file