commit 36a6aac0a0509f9338a08cf3080ebf3867abb257
parent 422239a7e56f9ec64b1c6556ebf03c6b0ad3c92b
Author: Felicitus <felicitus@felicitus.org>
Date: Sun, 25 Dec 2011 16:39:43 +0100
Added project reports
Diffstat:
5 files changed, 273 insertions(+), 1 deletion(-)
diff --git a/src/backend/de/RaumZeitLabor/PartKeepr/ProjectReport/ProjectReportService.php b/src/backend/de/RaumZeitLabor/PartKeepr/ProjectReport/ProjectReportService.php
@@ -0,0 +1,51 @@
+<?php
+namespace de\RaumZeitLabor\PartKeepr\ProjectReport;
+use de\RaumZeitLabor\PartKeepr\Service\RestfulService;
+
+declare(encoding = 'UTF-8');
+
+use de\RaumZeitLabor\PartKeepr\Service\Service;
+use de\RaumZeitLabor\PartKeepr\Project\ProjectManager,
+ de\RaumZeitLabor\PartKeepr\PartKeepr,
+ de\RaumZeitLabor\PartKeepr\Part\Part,
+ de\RaumZeitLabor\PartKeepr\Manager\ManagerFilter;
+
+class ProjectReportService extends Service implements RestfulService {
+ /**
+ * (non-PHPdoc)
+ * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::get()
+ */
+ public function get () {
+ $reportIds = explode(",",$this->getParameter("reports"));
+
+ $dql = "SELECT SUM(pp.quantity) AS quantity, p.id AS part_id, st.name AS storageLocation_name, p.stockLevel ";
+ $dql .= "AS stockLevel FROM de\RaumZeitLabor\PartKeepr\Project\ProjectPart pp JOIN pp.part p JOIN ";
+ $dql .= "p.storageLocation st JOIN pp.project pr WHERE pr.id IN (:projects) GROUP BY pp.part";
+
+ $query = PartKeepr::getEM()->createQuery($dql);
+ $query->setParameter("projects", $reportIds);
+
+ $aFinalResult = array();
+ foreach ($query->getResult() as $record) {
+ $missing = $record["quantity"] - $record["stockLevel"];
+
+ if ($missing < 0) { $missing = 0; }
+
+ $aFinalResult[] = array(
+ "quantity" => $record["quantity"],
+ "available" => $record["stockLevel"],
+ "missing" => $missing,
+ "part" => array("response" => array("totalCount" => 1, "data" => Part::loadById($record["part_id"])->serialize())),
+ "storageLocation_name" => $record["storageLocation_name"],
+ "sum_order" => 0
+ );
+ }
+ return array("data" => $aFinalResult);
+ }
+
+ public function create () {}
+
+ public function update () {}
+
+ public function destroy () {}
+}+
\ No newline at end of file
diff --git a/src/frontend/js/Components/MenuBar.js b/src/frontend/js/Components/MenuBar.js
@@ -62,6 +62,10 @@ Ext.define('PartKeepr.MenuBar', {
text: i18n("System Information"),
handler: this.showSystemInformation,
icon: 'resources/fugue-icons/icons/system-monitor.png'
+ },{
+ text: i18n("Project Reports"),
+ handler: this.showProjectReports,
+ icon: 'resources/fugue-icons/icons/drill.png'
}
]
});
@@ -229,6 +233,16 @@ Ext.define('PartKeepr.MenuBar', {
PartKeepr.getApplication().addItem(j);
j.show();
},
+ showProjectReports: function () {
+ var j = Ext.create("PartKeepr.ProjectReportView", {
+ title: i18n("Project Reports"),
+ iconCls: 'icon-drill',
+ closable: true
+ });
+
+ PartKeepr.getApplication().addItem(j);
+ j.show();
+ },
displayComponent: function (component) {
var j = Ext.create(component.type, {
title: component.title,
diff --git a/src/frontend/js/Components/Project/ProjectReport.js b/src/frontend/js/Components/Project/ProjectReport.js
@@ -0,0 +1,169 @@
+/**
+ * Represents the project report view
+ */
+Ext.define('PartKeepr.ProjectReportView', {
+ extend: 'Ext.panel.Panel',
+ alias: 'widget.ProjectReportView',
+
+ bodyStyle: 'background:#DBDBDB;padding: 10px;',
+ border: false,
+ layout: {
+ type: 'vbox',
+ align : 'stretch',
+ pack : 'start'
+ },
+ initComponent: function () {
+
+ this.createStores();
+
+ this.reportList = Ext.create("Ext.grid.Panel", {
+ title: i18n("Choose Projects to create a report for"),
+ selModel: {
+
+ mode: 'MULTI'
+ },
+ selType: 'checkboxmodel',
+ flex: 1,
+ columns: [{
+ header: i18n("Project Name"), dataIndex: 'name',
+ flex: 1
+ }],
+ store: this.store
+ });
+
+ this.editing = Ext.create('Ext.grid.plugin.CellEditing', {
+ clicksToEdit: 1
+ });
+
+ this.reportResult = Ext.create("Ext.grid.Panel", {
+ title: i18n("Project Report"),
+ flex: 1,
+ features: [{
+ ftype: 'summary'
+ }],
+ columns: [{
+ header: i18n("Quantity"), dataIndex: 'quantity',
+ width: 50
+ },{
+ header: i18n("Part"),
+ renderer: function (val, p, rec) {
+ return rec.part().getAt(0).get("name");
+ },
+ flex: 1
+ },{
+ header: i18n("Storage Location"), dataIndex: 'storageLocation_name',
+ width: 100
+ },{
+ header: i18n("Available"), dataIndex: 'available',
+ width: 75
+ },{
+ header: i18n("Missing"), dataIndex: 'missing',
+ width: 75
+ },{
+ header: i18n("Distributor"), dataIndex: 'distributor_id',
+ renderer: function (val,p,rec) {
+ return rec.get("distributor_name");
+ },
+ flex: 1,
+ editor: {
+ xtype: 'DistributorComboBox',
+ triggerAction: 'query',
+ ignoreQuery: true,
+ forceSelection: true,
+ editable: false
+ }
+ },{
+ header: i18n("Price per Item"), dataIndex: 'price',
+ width: 100
+ },{
+ header: i18n("Sum"),
+ renderer: function (val,p,rec) {
+ if (!isNaN(rec.get("price"))) {
+ return rec.get("quantity") * rec.get("price");
+ }
+
+ return 0;
+
+ },
+ width: 100
+ },{
+ header: i18n("Sum (Order)"),
+ dataIndex: 'sum_order',
+ summaryType: 'sum',
+ width: 100
+ }],
+ store: this.projectReportStore,
+ plugins: [ this.editing ]
+ });
+
+ this.reportResult.on("beforeedit", this.onBeforeEdit, this);
+ this.reportResult.on("edit", this.onEdit, this);
+ this.items = [ this.reportList, { xtype: 'button', text: i18n("Create Report"), margin: { top: 5, bottom: 5 }, listeners: { click: this.onCreateReportClick, scope: this }}, this.reportResult ];
+
+
+
+ this.callParent();
+ },
+ onBeforeEdit: function (e) {
+
+ var distributors = e.record.part().getAt(0).distributors();
+
+ var filterIds = new Array();
+ for (var i=0;i<distributors.count();i++) {
+ filterIds.push(distributors.getAt(i).get("distributor_id"));
+ }
+
+ e.column.getEditor().store.clearFilter();
+ e.column.getEditor().store.filter({filterFn: function(item) {
+ for (var i=0;i<filterIds.length;i++) {
+ if (item.get("id") == filterIds[i]) {
+ return true;
+ }
+ }
+ return false;
+ }});
+ },
+ onEdit: function (editor, e) {
+ if (e.field == "distributor_id") {
+ var distributors = e.record.part().getAt(0).distributors();
+
+ for (var i = 0; i < distributors.count(); i++) {
+ if (distributors.getAt(i).get("distributor_id") == e.value) {
+ e.record.set("distributor_name", distributors.getAt(i).get("distributor_name"));
+ e.record.set("price", distributors.getAt(i).get("price"));
+
+ e.record.set("sum_order", e.record.get("missing") * e.record.get("price"));
+ }
+ }
+ }
+
+ this.reportResult.getView().refresh(true);
+
+ },
+ onCreateReportClick: function () {
+ selection = this.reportList.getSelectionModel().getSelection();
+
+ var params = new Array();
+
+ for (var i=0;i<selection.length;i++) {
+ params.push(selection[i].get("id"));
+ }
+
+ this.projectReportStore.getProxy().extraParams.reports = params.join(",");
+ this.projectReportStore.load();
+ },
+ createStores: function () {
+ var config = {
+ autoLoad: true,
+ model: "PartKeepr.Project",
+ pageSize: -1
+ };
+
+ this.store = Ext.create('Ext.data.Store', config);
+
+ this.projectReportStore = Ext.create('Ext.data.Store', {
+ model: "PartKeepr.ProjectReport",
+ pageSize: -1
+ });
+ }
+});+
\ No newline at end of file
diff --git a/src/frontend/js/Components/Widgets/DistributorComboBox.js b/src/frontend/js/Components/Widgets/DistributorComboBox.js
@@ -7,7 +7,8 @@ Ext.define("PartKeepr.DistributorComboBox",{
queryMode: 'local',
triggerAction: 'all',
forceSelection: true,
- editable: true,
+ editable: true,
+ ignoreQuery: false,
initComponent: function () {
this.store = PartKeepr.getApplication().getDistributorStore();
@@ -22,6 +23,23 @@ Ext.define("PartKeepr.DistributorComboBox",{
}, this);
this.callParent();
+ },
+ onTriggerClick: function() {
+ if (!this.ignoreQuery) {
+ this.callParent();
+ } else {
+ var me = this;
+ if (!me.readOnly && !me.disabled) {
+ if (me.isExpanded) {
+ me.collapse();
+ } else {
+ me.onFocus({});
+ me.expand();
+ }
+ me.inputEl.focus();
+ }
+ }
+
}
});
diff --git a/src/frontend/js/Models/ProjectReport.js b/src/frontend/js/Models/ProjectReport.js
@@ -0,0 +1,17 @@
+/**
+ * Represents a project report
+ */
+Ext.define("PartKeepr.ProjectReport", {
+ extend: "Ext.data.Model",
+ fields: [
+ { name: 'quantity', type: 'int'},
+ { name: 'storageLocation_name', type: 'string'},
+ { name: 'available', type: 'int'},
+ { name: 'missing', type: 'int'},
+ { name: 'sum_order', type: 'float'}
+ ],
+ hasMany: [
+ { model: 'PartKeepr.Part', name: 'part'}
+ ],
+ proxy: PartKeepr.getRESTProxy("ProjectReport")
+});+
\ No newline at end of file