partkeepr

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

commit 787508e1e027bc062acca20345d7c2708ebf0003
parent b91259a4ea8121d0eef767f0d217345bcd09fc21
Author: Timo A. Hummel <timo@netraver.de>
Date:   Wed,  8 Jun 2011 20:18:21 +0200

Added better stock add/remove window

Diffstat:
Mfrontend/index.html | 1+
Mfrontend/js/Components/Part/PartDisplay.js | 22++++++++++------------
Afrontend/js/Components/Part/PartStockWindow.js | 148+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/de/RaumZeitLabor/PartDB2/Part/PartService.php | 6++++++
Msrc/de/RaumZeitLabor/PartDB2/Stock/StockEntry.php | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtesting/SetupDatabase.php | 14+++++++++++++-
6 files changed, 244 insertions(+), 13 deletions(-)

diff --git a/frontend/index.html b/frontend/index.html @@ -114,6 +114,7 @@ <script type="text/javascript" src="js/Components/Part/PartEditorWindow.js"></script> <script type="text/javascript" src="js/Components/Part/PartEditor.js"></script> <script type="text/javascript" src="js/Components/Part/PartDisplay.js"></script> + <script type="text/javascript" src="js/Components/Part/PartStockWindow.js"></script> </head> <body> diff --git a/frontend/js/Components/Part/PartDisplay.js b/frontend/js/Components/Part/PartDisplay.js @@ -112,43 +112,41 @@ Ext.define('PartDB2.PartDisplay', { * Prompt the user for the stock level he wishes to add. */ addPartPrompt: function () { - Ext.Msg.prompt(i18n("Add stock"), i18n("Amount"), this.addPartHandler, this); + var j = new PartDB2.PartStockWindow(); + j.addStock(this.addPartHandler, this); }, /** * Callback after the "add stock" dialog is complete. */ - addPartHandler: function (btn,a,c) { - if (btn == "ok") { + addPartHandler: function (quantity, price) { var call = new PartDB2.ServiceCall( "Part", "addStock"); - call.setParameter("stock", a); + call.setParameter("stock", quantity); + call.setParameter("price", price); call.setParameter("part", this.record.get("id")); - call.setLoadMessage('$[de.RaumZeitLabor.PartDB2.CategoryEditor.loadCategories]'); call.setHandler(Ext.bind(this.reloadPart, this)); call.doCall(); - } }, /** * Prompts the user for the stock level to decrease for the item. */ deletePartPrompt: function () { - Ext.Msg.prompt(i18n("Remove Stock"), i18n("Amount"), this.deletePartHandler, this); + var j = new PartDB2.PartStockWindow(); + j.removeStock(this.deletePartHandler, this); + //Ext.Msg.prompt(i18n("Remove Stock"), i18n("Amount"), this.deletePartHandler, this); }, /** * Callback after the "delete stock" dialog is complete. */ - deletePartHandler: function (btn,a,c) { - if (btn == "ok") { + deletePartHandler: function (quantity) { var call = new PartDB2.ServiceCall( "Part", "deleteStock"); - call.setParameter("stock", a); + call.setParameter("stock", quantity); call.setParameter("part", this.record.get("id")); - call.setLoadMessage('$[de.RaumZeitLabor.PartDB2.CategoryEditor.loadCategories]'); call.setHandler(Ext.bind(this.reloadPart, this)); call.doCall(); - } }, /** * Reloads the current part diff --git a/frontend/js/Components/Part/PartStockWindow.js b/frontend/js/Components/Part/PartStockWindow.js @@ -0,0 +1,147 @@ +/** + * This class defines a window which is used to in- or decrease the stock level + * for a specific part. Logic and service calls are not contained in this window, + * and need to be implemented from the caller. + */ +Ext.define('PartDB2.PartStockWindow', { + extend: 'Ext.window.Window', + + // Configurations + constrainHeader: true, + width: 300, + height: 150, + + resizable: false, + layout: 'fit', + + // We set the title later + title: "", + + // Window title texts + removePartText: i18n("Remove Part(s)"), + addPartText: i18n("Add Part(s)"), + + layout: 'anchor', + bodyStyle: { + padding: "5px" + }, + + /* + * Initializes the window with the quantity and price fields. + * The price field is hidden when a stock decrease happens. + */ + initComponent: function () { + + this.quantityField = Ext.create("Ext.form.field.Number", { + value: 0, // The initial value is 0, to indicate that this is a number field + minValue: 1, // The minimum value is 1. That way we force the user to enter a value + anchor: '100%', + fieldLabel: i18n("Quantity"), + listeners: { + specialkey: { + fn: function(field, e){ + if (e.getKey() == e.ENTER) { + this.onOKClick(); + } + }, + scope: this + } + } + }); + + this.priceField = Ext.create("Ext.form.field.Number", { + hideTrigger: true, + keyNavEnabled: false, + mouseWheelEnabled: false, + anchor: '100%', + value: 0, + fieldLabel: i18n("Price"), + listeners: { + specialkey: { + fn: function(field, e){ + if (e.getKey() == e.ENTER) { + this.onOKClick(); + } + }, + scope: this + } + } + }); + + this.priceCheckbox = Ext.create("Ext.form.field.Checkbox", { + boxLabel: i18n("Price per item"), + checked: true + }); + + this.form = Ext.create("Ext.form.Panel", { + bodyStyle: 'background:#DFE8F6;', + border: false, + items: [ this.quantityField, this.priceField, this.priceCheckbox ] + }); + + this.items = this.form; + + this.buttons = [ + { + text: i18n("Close"), + handler: this.onCloseClick, + scope: this + },{ + text: i18n("OK"), + handler: this.onOKClick, + scope: this + }]; + this.on("show", function () { this.quantityField.focus(); }, this); + this.callParent(); + }, + /** + * Closes the window + */ + onCloseClick: function () { + this.close(); + }, + /** + * Checks if the form is valid. If yes, execute the callback. + */ + onOKClick: function () { + if (this.form.getForm().isValid()) { + var price; + if (this.priceCheckbox.getValue()) { + price = this.priceField.getValue(); + } else { + price = this.priceField.getValue() / this.quantityField.getValue(); + } + + Ext.callback(this.callbackFn, this.callbackScope, [ this.quantityField.getValue(), price ]); + this.close(); + } + }, + /** + * Opens the window in "add stock" mode. The target callback receives two parameters: + * the value of the quantity field and the value of the price field. + * + * @param fn The callback + * @param scope The scope in which to execute the callback + */ + addStock: function (fn, scope) { + this.callbackFn = fn; + this.callbackScope = scope; + this.setTitle(this.addPartText); + this.show(); + }, + /** + * Opens the window in "remove stock" mode. The target callback receives one parameters: + * the value of the quantity field + * + * @param fn The callback + * @param scope The scope in which to execute the callback + */ + removeStock: function (fn, scope) { + this.callbackFn = fn; + this.callbackScope = scope; + this.setTitle(this.removePartText); + this.priceField.hide(); + this.priceCheckbox.hide(); + this.show(); + } +});+ \ No newline at end of file diff --git a/src/de/RaumZeitLabor/PartDB2/Part/PartService.php b/src/de/RaumZeitLabor/PartDB2/Part/PartService.php @@ -71,6 +71,12 @@ class PartService extends Service implements RestfulService { $stock = new StockEntry($part, intval($this->getParameter("stock")), $user); + $price = floatval($this->getParameter("price")); + + if ($price != 0) { + $stock->setPrice($price); + } + PartDB2::getEM()->persist($stock); PartDB2::getEM()->flush(); diff --git a/src/de/RaumZeitLabor/PartDB2/Stock/StockEntry.php b/src/de/RaumZeitLabor/PartDB2/Stock/StockEntry.php @@ -31,25 +31,91 @@ class StockEntry { */ private $user; + /** + * @Column(type="decimal",precision=5, scale=2,nullable=true) + * @var float + */ + private $price; + + /** + * Creates a new stock entry. A stock entry tracks how many parts + * were the stockLevel is the amount of items added/removed, + * by which user and how much the user paid for it (for adding parts only!) + * + * @param Part $part The part which was added/removed + * @param int $stockLevel The stock level. Positive value means added parts, negative values means removed parts. + * @param User $user The user who removed/added parts + */ public function __construct (Part $part, $stockLevel, User $user = null) { $this->setPart($part); $this->setStockLevel($stockLevel); $this->setUser($user); } + /** + * Sets the price for the item stored. + * + * Please note that the price is for a single item only, and can be null. + * @param float $price The price to set + */ + public function setPrice ($price) { + $this->price = $price; + } + + /** + * Returns the price for this entry. The price is for a single item only. + * + * @return float The price for this entry. + */ + public function getPrice () { + return $this->price; + } + + /** + * Sets the stock level for this entry. + * + * Negative values means part removal, positive values means part adding. + * @param int $stockLevel The stock level + */ public function setStockLevel($stockLevel) { $this->stockLevel = $stockLevel; } + /** + * Returns the stock level for this entry. + * @return int The stock level + */ + public function getStockLevel () { + return $this->stockLevel; + } + + /** + * Sets the part assigned to this entry. + * @param Part $part The part to set + */ public function setPart (Part $part) { $this->part = $part; } + /** + * Sets the user assigned to this entry. + * @param User $user The user The user to set + */ public function setUser (User $user = null) { $this->user = $user; } /** + * If the stock level is negative, we can't have a price. + * @PrePersist + */ + public function checkPrice () { + if ($this->getStockLevel() < 0 && $this->getPrice() !== null) { + $this->setPrice(null); + } + } + + /** * @PostPersist */ public function updateStockLevel () { diff --git a/testing/SetupDatabase.php b/testing/SetupDatabase.php @@ -203,10 +203,22 @@ while ($part = mysql_fetch_assoc($r)) { $randomDistributor = rand(0, count($aDistributors)-1); $oPart->getDistributors()->add(new PartDistributor($oPart, $aDistributors[$randomDistributor])); } - echo "Migrating part ".sprintf("%-40s", $part["name"])."\r"; + //echo "Migrating part ".sprintf("%-40s", $part["name"])."\r"; PartDB2::getEM()->persist($oPart); $oStock = new StockEntry($oPart, $part["instock"]); + + $priceQuery = "SELECT AVG(preis) AS preis FROM preise WHERE part_id = ".$part["id"]; + + $r2 = mysql_query($priceQuery); + $res = mysql_fetch_assoc($r2); + + if ($res) { + if ($res["preis"] !== null) { + $oStock->setPrice(floatval($res["preis"])); + } + } + PartDB2::getEM()->persist($oStock); }