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:
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);
}