partkeepr

fork of partkeepr
git clone https://git.e1e0.net/partkeepr.git
Log | Files | Refs | Submodules | README | LICENSE

commit 6155a9e3389933653f711a3ba141647a7eb7bd21
parent 804fb81e618d34f4970b279d70152319d2afe372
Author: Felicitus <felicitus@felicitus.org>
Date:   Tue, 28 Jun 2011 15:51:01 +0200

Added editing of the price+amounts for stock entries

Diffstat:
Mfrontend/js/Components/Part/PartStockHistory.js | 58+++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Mfrontend/js/Dialogs/Auth/LoginDialog.js | 14++++++++++++++
Mfrontend/js/PartKeepr.js | 21++++++++++++++++++++-
Msrc/de/RaumZeitLabor/PartKeepr/Stock/StockEntry.php | 46+++++++++++++++++++++++++++++-----------------
Msrc/de/RaumZeitLabor/PartKeepr/Stock/StockService.php | 30+++++++++++++++++++++++++++++-
5 files changed, 147 insertions(+), 22 deletions(-)

diff --git a/frontend/js/Components/Part/PartStockHistory.js b/frontend/js/Components/Part/PartStockHistory.js @@ -17,11 +17,19 @@ Ext.define('PartKeepr.PartStockHistory', { }, width: 20 }, - {header: i18n("User"), dataIndex: 'username', width: 80 }, - {header: i18n("Amount"), dataIndex: 'amount', width: 50}, + {header: i18n("User"), dataIndex: 'username', flex: 0.4, minWidth: 80 }, + {header: i18n("Amount"), dataIndex: 'amount', width: 50, + editor: { + xtype:'numberfield', + allowBlank:false + }}, {header: i18n("Date"), dataIndex: 'datetime', width: 120}, { header: i18n("Price"), + editor: { + xtype:'numberfield', + allowBlank:false + }, dataIndex: 'price', width: 60, renderer: function (val, p, rec) { @@ -34,10 +42,13 @@ Ext.define('PartKeepr.PartStockHistory', { } ], model: 'PartKeepr.StockEntry', + /** + * Initializes the stock history grid. + */ initComponent: function () { var config = { autoLoad: false, - autoSync: false, // Do not change. If true, new (empty) records would be immediately commited to the database. + autoSync: true, remoteFilter: false, remoteSort: false, model: 'PartKeepr.StockEntry', @@ -45,9 +56,50 @@ Ext.define('PartKeepr.PartStockHistory', { this.store = Ext.create('Ext.data.Store', config); + this.editing = Ext.create('Ext.grid.plugin.CellEditing', { + clicksToEdit: 1 + }); + + this.plugins = [ this.editing ]; + + this.editing.on("beforeedit", this.onBeforeEdit, this); + this.on("activate", this.onActivate, this); this.callParent(); }, + /** + * Called before editing a cell. Checks if the user may actually make the requested changes. + * + * @param e Passed from ExtJS + * @returns {Boolean} + */ + onBeforeEdit: function (e) { + + // Checks if the usernames match + var sameUser = e.record.get("username") == PartKeepr.getApplication().getUsername(); + + switch (e.field) { + case "price": + // Check the direction is "out". If yes, editing the price field is not allowed + if (e.record.get("direction") == "out") { + return false; + } + + // If it's not the same user or an admin, editing is not allowed + if ( !sameUser && !PartKeepr.getApplication().isAdmin()) { + return false; + } + break; + case "amount": + // Only an admin may edit the amount. Regular users must put the stock back in manually. + if (!PartKeepr.getApplication().isAdmin()) { + return false; + } + } + }, + /** + * Called when the view is activated. + */ onActivate: function () { var proxy = this.store.getProxy(); proxy.extraParams.item = this.part; diff --git a/frontend/js/Dialogs/Auth/LoginDialog.js b/frontend/js/Dialogs/Auth/LoginDialog.js @@ -74,19 +74,33 @@ Ext.define('PartKeepr.LoginDialog', { call.setHandler(Ext.bind(this.onLogin, this)); call.doCall(); }, + /** + * Callback after the login call was completed. + * + * @param obj The response object from the server + */ onLogin: function (obj) { + // Set session + username PartKeepr.getApplication().setSession(obj.sessionid); PartKeepr.getApplication().setUsername(obj.username); + // @todo Disable the "edit users" menu somehow else if (!obj.admin) { Ext.getCmp("edit-users").hide(); } else { Ext.getCmp("edit-users").show(); } + // Set the admin flag + PartKeepr.getApplication().setAdmin(obj.admin); + + // Call the "login" method, which initializes the system with the user PartKeepr.getApplication().login(); + // Write out a logging message PartKeepr.log(i18n("Logged in as")+" "+obj.username); + + // Close the window this.close(); } diff --git a/frontend/js/PartKeepr.js b/frontend/js/PartKeepr.js @@ -88,6 +88,12 @@ Ext.application({ autoLoad: false }); }, + setAdmin: function (admin) { + this.admin = admin; + }, + isAdmin: function () { + return this.admin; + }, getUnitStore: function () { return this.unitStore; }, @@ -249,10 +255,23 @@ Ext.application({ } }, + /** + * Sets the username. This should only be called from the login dialog. + * + * Also updates the statusbar to reflect the username. + * + * @param {string} username The username to set + */ setUsername: function (username) { this.username = username; - this.getStatusbar().setCurrentUser(username); + }, + /** + * Returns the current username + * @returns {string} + */ + getUsername: function () { + return this.username; } }); diff --git a/src/de/RaumZeitLabor/PartKeepr/Stock/StockEntry.php b/src/de/RaumZeitLabor/PartKeepr/Stock/StockEntry.php @@ -5,17 +5,11 @@ declare(encoding = 'UTF-8'); use de\RaumZeitLabor\PartKeepr\Part\Part; use de\RaumZeitLabor\PartKeepr\User\User; use de\RaumZeitLabor\PartKeepr\PartKeepr; +use de\RaumZeitLabor\PartKeepr\Util\BaseEntity; +use de\RaumZeitLabor\PartKeepr\Util\Serializable; /** @Entity @HasLifecycleCallbacks **/ -class StockEntry { - - /** - * @Id @Column(type="integer") - * @GeneratedValue(strategy="AUTO") - * @var int - */ - private $id; - +class StockEntry extends BaseEntity implements Serializable { /** * @Column(type="integer") */ @@ -163,14 +157,6 @@ class StockEntry { } /** - * Returns the ID for this entity. - * @return int The ID - */ - public function getId () { - return $this->id; - } - - /** * If the stock level is negative, we can't have a price. * @PrePersist */ @@ -189,6 +175,32 @@ class StockEntry { $this->updatePrice(); } + /** + * Returns if the current stock entry is a removal. + * @return boolean True if the entry is a removal, false otherwise + */ + public function isRemoval () { + if ($this->getStockLevel() < 0) { + return true; + } else { + return false; + } + } + + /** + * (non-PHPdoc) + * @see de\RaumZeitLabor\PartKeepr\Util.Serializable::serialize() + */ + public function serialize () { + return array( + "id" => $this->getId(), + "username" => is_object($this->getUser()) ? $this->getUser()->getUsername() : PartKeepr::i18n("Unknown User"), + "amount" => abs($this->getStockLevel()), + "datetime" => $this->getDateTime()->format("Y-m-d H:i:s"), + "direction" => ($this->getStockLevel() < 0) ? "out" : "in", + "price" => $this->getPrice() + ); + } public function updateStockLevel () { $query = PartKeepr::getEM()->createQuery("SELECT SUM(se.stockLevel) FROM de\RaumZeitLabor\PartKeepr\Stock\StockEntry se WHERE se.part = :part"); diff --git a/src/de/RaumZeitLabor/PartKeepr/Stock/StockService.php b/src/de/RaumZeitLabor/PartKeepr/Stock/StockService.php @@ -5,6 +5,7 @@ declare(encoding = 'UTF-8'); use de\RaumZeitLabor\PartKeepr\Stock\StockEntry, de\RaumZeitLabor\PartKeepr\PartKeepr, + de\RaumZeitLabor\PartKeepr\Session\SessionManager, de\RaumZeitLabor\PartKeepr\Service\RestfulService, de\RaumZeitLabor\PartKeepr\Service\Service;; @@ -41,8 +42,35 @@ class StockService extends Service implements RestfulService { throw new \Exception("Not yet implemented"); } + /** + * (non-PHPdoc) + * @see de\RaumZeitLabor\PartKeepr\Service.RestfulService::update() + */ public function update () { - throw new \Exception("Not yet implemented"); + $this->requireParameter("id"); + + $stockEntry = StockEntry::loadById($this->getParameter("id")); + + if (!SessionManager::getCurrentSession()->getUser()->isAdmin() || + (SessionManager::getCurrentSession()->getUser() && $stockEntry->getUser() && SessionManager::getCurrentSession()->getUser()->getId() != $stockEntry->getUser()->getId() )) { + throw new \Exception("Permission denied"); + } + + /* It's not allowed to edit a price for a removal */ + if (!$stockEntry->isRemoval()) { + $stockEntry->setPrice(abs($this->getParameter("price"))); + } + + /** + * Only an admin user may correct the in&out stock levels + */ + if (SessionManager::getCurrentSession()->getUser()->isAdmin()) { + $stockEntry->setStockLevel($this->getParameter("amount")); + } + + PartKeepr::getEM()->flush(); + + return array("data" => $stockEntry->serialize()); } public function destroy () {