partkeepr

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

commit ff29041ab5acdb241745dc6fb67a246a01a384bf
parent 79f1d1fe04b69523a393d349effdbd3c2213cfb8
Author: Felicitus <felicitus@felicitus.org>
Date:   Mon, 31 Aug 2015 16:48:17 +0200

Added service calls for adding, removing and setting stock. Fixed stock level change from the parts grid.

Diffstat:
Mapp/config/config.yml | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dcronjobs/UpdatePartCacheData.php | 29-----------------------------
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/PartsGrid.js | 108++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Msrc/PartKeepr/FrontendBundle/Resources/public/js/Dialogs/RememberChoiceMessageBox.js | 23+++++++++++++++++++++++
Asrc/PartKeepr/PartBundle/Controller/PartController.php | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/PartKeepr/PartBundle/Entity/Part.php | 106+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Asrc/PartKeepr/PartBundle/Listeners/StockLevelListener.php | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/backend/PartKeepr/Stock/StockEntry.php | 469++++++++++++++++++++++++++++++++++++++++---------------------------------------
8 files changed, 651 insertions(+), 351 deletions(-)

diff --git a/app/config/config.yml b/app/config/config.yml @@ -151,6 +151,14 @@ services: tags: - { name: doctrine.event_listener, event: onFlush } + part.stock_level_listener: + class: PartKeepr\PartBundle\Listeners\StockLevelListener + arguments: + - "@service_container" + tags: + - { name: doctrine.event_listener, event: onFlush } + + my_event_listener: class: PartKeepr\UploadedFileBundle\EventListener\TemporaryFileEventListener arguments: @@ -337,11 +345,76 @@ services: arguments: - { groups: [ "default" ] } + resource.part.item_operation.get: + class: "Dunglas\ApiBundle\Api\Operation\Operation" + public: false + factory: [ "@api.operation_factory", "createItemOperation" ] + arguments: [ "@resource.part", "GET" ] + + resource.part.item_operation.put: + class: "Dunglas\ApiBundle\Api\Operation\Operation" + public: false + factory: [ "@api.operation_factory", "createItemOperation" ] + arguments: [ "@resource.part", "PUT" ] + + resource.part.item_operation.delete: + class: "Dunglas\ApiBundle\Api\Operation\Operation" + public: false + factory: [ "@api.operation_factory", "createItemOperation" ] + arguments: [ "@resource.part", "DELETE" ] + + resource.part.item_operation.add_stock: + class: "Dunglas\ApiBundle\Api\Operation\Operation" + public: false + factory: [ "@api.operation_factory", "createItemOperation" ] + arguments: + - "@resource.part" # Resource + - [ "PUT" ] # Methods + - "/parts/{id}/addStock" # Path + - "PartKeeprPartBundle:Part:addStock" # Controller + - "PartAddStock" # Route name + - # Context (will be present in Hydra documentation) + "@type": "hydra:Operation" + "hydra:title": "A custom operation" + "returns": "xmls:string" + + resource.part.item_operation.remove_stock: + class: "Dunglas\ApiBundle\Api\Operation\Operation" + public: false + factory: [ "@api.operation_factory", "createItemOperation" ] + arguments: + - "@resource.part" # Resource + - [ "PUT" ] # Methods + - "/parts/{id}/removeStock" # Path + - "PartKeeprPartBundle:Part:removeStock" # Controller + - "PartRemoveStock" # Route name + - # Context (will be present in Hydra documentation) + "@type": "hydra:Operation" + "hydra:title": "A custom operation" + "returns": "xmls:string" + + resource.part.item_operation.set_stock: + class: "Dunglas\ApiBundle\Api\Operation\Operation" + public: false + factory: [ "@api.operation_factory", "createItemOperation" ] + arguments: + - "@resource.part" # Resource + - [ "PUT" ] # Methods + - "/parts/{id}/setStock" # Path + - "PartKeeprPartBundle:Part:setStock" # Controller + - "PartSetStock" # Route name + - # Context (will be present in Hydra documentation) + "@type": "hydra:Operation" + "hydra:title": "A custom operation" + "returns": "xmls:string" + resource.part: parent: "api.resource" arguments: [ "PartKeepr\\PartBundle\\Entity\\Part" ] tags: [ { name: "api.resource" } ] calls: + - method: "initItemOperations" + arguments: [ [ "@resource.part.item_operation.get", "@resource.part.item_operation.put", "@resource.part.item_operation.delete", "@resource.part.item_operation.add_stock", "@resource.part.item_operation.remove_stock", "@resource.part.item_operation.set_stock" ] ] - method: "initFilters" arguments: [ [ "@doctrine_reflection_service.search_filter" ] ] - method: "initNormalizationContext" diff --git a/cronjobs/UpdatePartCacheData.php b/cronjobs/UpdatePartCacheData.php @@ -1,28 +0,0 @@ -<?php -namespace PartKeepr\Cronjobs; - -include(__DIR__."/../src/backend/PartKeepr/PartKeepr.php"); - -use PartKeepr\PartKeepr, - PartKeepr\Statistic\StatisticSnapshotManager, - PartKeepr\CronLogger\CronLoggerManager; - -PartKeepr::initialize(); - -$query = PartKeepr::getEM()->createQuery("SELECT p FROM PartKeepr\PartBundle\Entity\Part p"); -$result = $query->getResult(); - -$fc = 0; - -foreach ($result as $part) { - $fc++; - if ($fc > 50) { - PartKeepr::getEM()->flush(); - $fc=0; - } - $part->updateCacheData(); -} - -PartKeepr::getEM()->flush(); - -CronLoggerManager::getInstance()->markCronRun(basename(__FILE__));- \ No newline at end of file diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/PartsGrid.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Components/Part/PartsGrid.js @@ -267,7 +267,7 @@ Ext.define('PartKeepr.PartsGrid', { header: i18n("Stock"), dataIndex: 'stockLevel', editor: { - xtype: 'numberfield', + xtype: 'textfield', allowBlank: false }, renderer: this.stockLevelRenderer @@ -403,6 +403,21 @@ Ext.define('PartKeepr.PartsGrid', { this.confirmStockChange(e); } }, + getStockChangeMode: function (value) { + var n = value.indexOf("+"); + + if (n !== -1) { + return "addition"; + } + + n = value.indexOf("-"); + + if (n !== -1) { + return "removal"; + } + + return "fixed"; + }, /** * Opens the confirm dialog * @@ -411,27 +426,46 @@ Ext.define('PartKeepr.PartsGrid', { */ confirmStockChange: function (e) { + var mode = this.getStockChangeMode(e.value); + var value = Math.abs(parseInt(e.value)); var confirmText = ""; var headerText = ""; - if (e.value < 0) { - confirmText = sprintf(i18n("You wish to remove <b>%s %s</b> of the part <b>%s</b>. Is this correct?"), - abs(e.value), e.record.get("partUnitName"), e.record.get("name")); + var n = e.value.indexOf("+"); - // Set the stock level to a temporary calculated value. - e.record.set("stockLevel", (e.originalValue - abs(e.value))); - headerText = i18n("Remove Part(s)"); - } else { - confirmText = sprintf( - i18n("You wish to set the stock level to <b>%s %s</b> of part <b>%s</b>. Is this correct?"), - abs(e.value), e.record.get("partUnitName"), e.record.get("name")); - headerText = i18n("Set Stock Level for Part(s)"); + switch (mode) { + case "removal": + confirmText = sprintf( + i18n("You wish to remove <b>%s %s</b> of the part <b>%s</b>. Is this correct?"), + value, e.record.getPartUnit().get("name"), e.record.get("name")); + + // Set the stock level to a temporary calculated value. + e.record.set("stockLevel", (e.originalValue - value)); + headerText = i18n("Remove Part(s)"); + break; + case "addition": + confirmText = sprintf( + i18n("You wish to add <b>%s %s</b> of part <b>%s</b>. Is this correct?"), + value, e.record.getPartUnit().get("name"), e.record.get("name")); + + e.record.set("stockLevel", (e.originalValue + value)); + headerText = i18n("Add Part(s)"); + break; + case "fixed": + confirmText = sprintf( + i18n("You wish to set the stock level to <b>%s %s</b> for part <b>%s</b>. Is this correct?"), + value, e.record.getPartUnit().get("name"), e.record.get("name")); + + e.record.set("stockLevel", value); + headerText = i18n("Set Stock Level for Part(s)"); + break; } - var j = new PartKeepr.RememberChoiceMessageBox({ + + var j = Ext.create("PartKeepr.RememberChoiceMessageBox", { escButtonAction: "cancel", - dontAskAgainProperty: "partkeepr.inlinestockremoval.ask", + dontAskAgainProperty: "partkeepr.inline-stock-change.confirm", dontAskAgainValue: false }); @@ -457,13 +491,7 @@ Ext.define('PartKeepr.PartsGrid', { opts.originalOnEdit.record.set("stockLevel", opts.originalOnEdit.originalValue); } - if (buttonId == "ok") { - if (opts.dialog.rememberChoiceCheckbox.getValue() === true) { - PartKeepr.getApplication().setUserPreference("partkeepr.inline-stock-change.confirm", false); - } - - this.handleStockChange(opts.originalOnEdit); - } + this.handleStockChange(opts.originalOnEdit); }, /** * Handles the stock change. Automatically figures out which method to call (deleteStock or addStock) and @@ -474,28 +502,28 @@ Ext.define('PartKeepr.PartsGrid', { */ handleStockChange: function (e) { - var mode, quantity = 0; + var mode = this.getStockChangeMode(e.value); + var value = Math.abs(parseInt(e.value)); - if (e.value < 0) { - mode = "deleteStock"; - quantity = abs(e.value); - } else { - if (e.originalValue <= e.value) { - mode = "deleteStock"; - quantity = e.originalValue - e.value; - } else { - mode = "addStock"; - quantity = e.value - e.originalValue; - } + if (e.value == 0) { + return; + } + + switch (mode) { + case "removal": + call = "removeStock"; + break; + case "addition": + call = "addStock"; + break; + case "fixed": + call = "setStock"; + break; } - var call = new PartKeepr.ServiceCall( - "Part", - mode); - call.setParameter("stock", quantity); - call.setParameter("part", e.record.getId()); - call.setHandler(Ext.bind(this.reloadPart, this, [e])); - call.doCall(); + e.record.callAction(call, { + quantity: e.value + }, Ext.bind(this.reloadPart, this, [e])); }, /** * Reloads the current part diff --git a/src/PartKeepr/FrontendBundle/Resources/public/js/Dialogs/RememberChoiceMessageBox.js b/src/PartKeepr/FrontendBundle/Resources/public/js/Dialogs/RememberChoiceMessageBox.js @@ -1,8 +1,22 @@ +/** + * Implementation of a message box which supports a "remember choice" checkbox. + */ Ext.define('PartKeepr.RememberChoiceMessageBox', { extend: 'Ext.window.MessageBox', escButtonAction: null, + /** + * The user preference to set when "remember choice" is selected + * @var string + */ + dontAskAgainProperty: null, + + /** + * The value to set the user preference to + */ + dontAskAgainValue: false, + initComponent: function () { this.callParent(); @@ -44,5 +58,14 @@ Ext.define('PartKeepr.RememberChoiceMessageBox', { } else { this.callParent(); } + }, + btnCallback: function (btn, event) + { + this.callParent(arguments); + + if (btn === "ok") { + PartKeepr.getApplication().setUserPreference(this.dontAskAgainProperty, this.dontAskAgainValue); + } + } }); \ No newline at end of file diff --git a/src/PartKeepr/PartBundle/Controller/PartController.php b/src/PartKeepr/PartBundle/Controller/PartController.php @@ -0,0 +1,119 @@ +<?php +namespace PartKeepr\PartBundle\Controller; + +use Dunglas\ApiBundle\Controller\ResourceController; +use Dunglas\ApiBundle\JsonLd\Response; +use FOS\RestBundle\Controller\Annotations\RequestParam; +use PartKeepr\PartBundle\Entity\Part; +use PartKeepr\Stock\StockEntry; +use Symfony\Component\HttpFoundation\Request; + +class PartController extends ResourceController +{ + /** + * Removes stock from a part + * + * @RequestParam(name="quantity",description="The quantity to be removed") + * @param Request $request The request object + * @param int $id The id of the part to operate on + * + * @return Response + */ + public function removeStockAction(Request $request, $id) + { + $resource = $this->getResource($request); + $part = $this->findOrThrowNotFound($resource, $id); + + /** + * @var $part Part + */ + $quantity = $request->request->get("quantity"); + $user = $this->get('security.token_storage')->getToken()->getUser(); + + $stock = new StockEntry(0 - intval($quantity), $user); + $part->addStockEntry($stock); + $this->getDoctrine()->getManager()->persist($stock); + $this->get("doctrine")->getManager()->flush(); + + + return $this->getSuccessResponse($resource, $part); + } + + /** + * Adds stock to a part + * + * @RequestParam(name="quantity",description="The quantity to be added") + * @RequestParam(name="price",description="The price for the addition",default=null,strict=false) + * @RequestParam(name="comment",description="The comment",default=null,strict=false) + * @param Request $request The request object + * @param int $id The id of the part to operate on + * + * @return Response + */ + public function addStockAction(Request $request, $id) + { + $resource = $this->getResource($request); + $part = $this->findOrThrowNotFound($resource, $id); + + /** + * @var $part Part + */ + $quantity = $request->request->get("quantity"); + $user = $this->get('security.token_storage')->getToken()->getUser(); + + $stock = new StockEntry(intval($quantity), $user); + + if ($request->request->has("price") && $request->request->get("price") !== null) { + $stock->setPrice(floatval($request->request->get("price"))); + } + + if ($request->request->has("comment") && $request->request->get("comment") !== null) { + $stock->setComment($request->request->get("comment")); + } + + $part->addStockEntry($stock); + $this->getDoctrine()->getManager()->persist($stock); + $this->get("doctrine")->getManager()->flush(); + + return $this->getSuccessResponse($resource, $part); + } + + /** + * Sets the stock level for a part + * + * @RequestParam(name="quantity",description="The quantity to be added") + * @RequestParam(name="comment",description="The comment",default=null,strict=false) + * @param Request $request The request object + * @param int $id The id of the part to operate on + * @return Response + */ + public function setStockAction(Request $request, $id) + { + $resource = $this->getResource($request); + $part = $this->findOrThrowNotFound($resource, $id); + + /** + * @var $part Part + */ + $quantity = $request->request->get("quantity"); + $user = $this->get('security.token_storage')->getToken()->getUser(); + + $oldQuantity = $part->getStockLevel(); + $correctionQuantity = $quantity - $oldQuantity; + + if ($correctionQuantity != 0) { + + $stock = new StockEntry($correctionQuantity, $user); + + if ($request->request->has("comment") && $request->request->get("comment") !== null) { + $stock->setComment($request->request->get("comment")); + } + + $part->addStockEntry($stock); + $this->getDoctrine()->getManager()->persist($stock); + $this->get("doctrine")->getManager()->flush(); + } + + return $this->getSuccessResponse($resource, $part); + } +} diff --git a/src/PartKeepr/PartBundle/Entity/Part.php b/src/PartKeepr/PartBundle/Entity/Part.php @@ -8,6 +8,7 @@ use PartKeepr\FootprintBundle\Entity\Footprint; use PartKeepr\Part\Exceptions\CategoryNotAssignedException; use PartKeepr\Part\Exceptions\StorageLocationNotAssignedException; use PartKeepr\PartKeepr; +use PartKeepr\Stock\StockEntry; use PartKeepr\StorageLocationBundle\Entity\StorageLocation; use PartKeepr\Util\BaseEntity; use PartKeepr\Util\Exceptions\OutOfRangeException; @@ -26,6 +27,7 @@ class Part extends BaseEntity * The category of the part * @ORM\ManyToOne(targetEntity="PartKeepr\PartBundle\Entity\PartCategory") * @Groups({"default"}) + * * @var PartCategory */ private $category; @@ -52,6 +54,7 @@ class Part extends BaseEntity * The footprint of this part * @ORM\ManyToOne(targetEntity="PartKeepr\FootprintBundle\Entity\Footprint") * @Groups({"default"}) + * * @var Footprint */ private $footprint; @@ -61,6 +64,7 @@ class Part extends BaseEntity * in "pieces", "meters" or "grams". * @ORM\ManyToOne(targetEntity="PartKeepr\PartBundle\Entity\PartMeasurementUnit", inversedBy="parts") * @Groups({"default"}) + * * @var PartMeasurementUnit */ private $partUnit; @@ -69,6 +73,7 @@ class Part extends BaseEntity * Defines the storage location of this part * @ORM\ManyToOne(targetEntity="PartKeepr\StorageLocationBundle\Entity\StorageLocation") * @Groups({"default"}) + * * @var StorageLocation */ private $storageLocation; @@ -163,6 +168,7 @@ class Part extends BaseEntity * The part status for this part * @ORM\Column(type="string",nullable=true) * @Groups({"default"}) + * * @var string */ private $status; @@ -171,6 +177,7 @@ class Part extends BaseEntity * Defines if the part needs review * @ORM\Column(type="boolean") * @Groups({"default"}) + * * @var boolean */ private $needsReview; @@ -179,6 +186,7 @@ class Part extends BaseEntity * Defines the condition of the part * @ORM\Column(type="string",nullable=true) * @Groups({"default"}) + * * @var string */ private $partCondition; @@ -187,12 +195,14 @@ class Part extends BaseEntity * The create date+time for this part * @ORM\Column(type="datetime",nullable=true) * @Groups({"default"}) + * * @var \DateTime */ private $createDate; /** * @ORM\OneToMany(targetEntity="PartKeepr\Project\ProjectPart", mappedBy="part") + * @var ArrayCollection **/ private $projectParts; @@ -200,6 +210,7 @@ class Part extends BaseEntity * The internal part number * @ORM\Column(type="string",nullable=true) * @Groups({"default"}) + * * @var string */ private $internalPartNumber; @@ -311,14 +322,6 @@ class Part extends BaseEntity } /** - * Updates the internal stock level from the stock history - */ - public function updateStockLevel() - { - $this->stockLevel = $this->getStockLevel(); - } - - /** * Sets the review flag * * @param boolean $bReview True if the part needs review, false otherwise @@ -524,25 +527,6 @@ class Part extends BaseEntity } /** - * Returns the stock level of this part. This is a real-time function which - * actually creates a query over the StockEntry table. - * - * @return int The stock level - */ - public function getStockLevel() - { - $query = PartKeepr::getEM()->createQuery("SELECT SUM(s.stockLevel) FROM PartKeepr\Stock\StockEntry s WHERE s.part = :part"); - $query->setParameter("part", $this); - - $count = $query->getSingleScalarResult(); - if ($count == null) { - $count = 0; - } - - return $count; - } - - /** * Sets the create date for this part * * @param \DateTime $dateTime The create date+time @@ -583,27 +567,6 @@ class Part extends BaseEntity return $this->status; } - public function updateCacheData() - { - $this->updateStockLevel(); - $this->updatePrice(); - } - - /** - * Updates the average price for a part - */ - public function updatePrice() - { - $query = PartKeepr::getEM()->createQuery("SELECT SUM(se.price*se.stockLevel) / SUM(se.stockLevel) FROM PartKeepr\Stock\StockEntry se WHERE se.part = :part AND se.stockLevel > 0"); - $query->setParameter("part", $this); - $val = $query->getSingleScalarResult(); - - $query = PartKeepr::getEM()->createQuery('UPDATE PartKeepr\PartBundle\Entity\Part p SET p.averagePrice = :val WHERE p = :part'); - $query->setParameter("val", $val); - $query->setParameter("part", $this); - $query->execute(); - } - /** * Checks if the part category is set. * @@ -659,6 +622,53 @@ class Part extends BaseEntity } /** + * Sets the stock level + * + * @param $stockLevel int The stock level to set + */ + public function setStockLevel($stockLevel) + { + $this->stockLevel = $stockLevel; + } + + /** + * Returns the stock level + * + * @return int The stock level + */ + public function getStockLevel() + { + return $this->stockLevel; + } + + /** + * Returns all stock entries + * + * @return ArrayCollection + */ + public function getStockLevels() + { + return $this->stockLevels; + } + + /** + * Adds a new stock entry to this part + * @param StockEntry $stockEntry + */ + public function addStockEntry (StockEntry $stockEntry) { + $stockEntry->setPart($this); + $this->getStockLevels()->add($stockEntry); + } + + /** + * Returns the project parts + * @return ArrayCollection + */ + public function getProjectParts () { + return $this->projectParts; + } + + /** * Returns a string representation of the part * * @param none diff --git a/src/PartKeepr/PartBundle/Listeners/StockLevelListener.php b/src/PartKeepr/PartBundle/Listeners/StockLevelListener.php @@ -0,0 +1,75 @@ +<?php +namespace PartKeepr\PartBundle\Listeners; + +use Doctrine\ORM\Event\OnFlushEventArgs; +use PartKeepr\PartBundle\Entity\Part; +use PartKeepr\Stock\StockEntry; +use Symfony\Component\DependencyInjection\ContainerAware; + +class StockLevelListener extends ContainerAware +{ + /** + * Updates the child category paths when their parent name has changed. + * + * @param OnFlushEventArgs $eventArgs The event arguments as given by Doctrine + */ + public function onFlush(OnFlushEventArgs $eventArgs) + { + $entityManager = $eventArgs->getEntityManager(); + $uow = $entityManager->getUnitOfWork(); + + $parts = array(); + + foreach ($uow->getScheduledEntityInsertions() as $updated) { + if ($updated instanceof StockEntry) { + if (!in_array($updated->getPart(), $parts)) { + $parts[] = $updated->getPart(); + } + } + } + + foreach ($uow->getScheduledEntityUpdates() as $updated) { + if ($updated instanceof StockEntry) { + if (!in_array($updated->getPart(), $parts)) { + $parts[] = $updated->getPart(); + } + } + } + + foreach ($uow->getScheduledEntityDeletions() as $updated) { + if ($updated instanceof StockEntry) { + if (!in_array($updated->getPart(), $parts)) { + $parts[] = $updated->getPart(); + } + } + } + + foreach ($parts as $part) { + $this->updateStockLevel($part, $eventArgs); + } + } + + /** + * Updates the stock level for a specific part + * + * @param Part $part The part to update + * @param OnFlushEventArgs $eventArgs The event arguments + */ + protected function updateStockLevel(Part $part, OnFlushEventArgs $eventArgs) + { + $entityManager = $eventArgs->getEntityManager(); + + $sum = 0; + + foreach ($part->getStockLevels() as $stockLevel) { + $sum += $stockLevel->getStockLevel(); + } + + $part->setStockLevel($sum); + + $entityManager->getUnitOfWork()->recomputeSingleEntityChangeSet( + $entityManager->getClassMetadata(get_class($part)), + $part + ); + } +} diff --git a/src/backend/PartKeepr/Stock/StockEntry.php b/src/backend/PartKeepr/Stock/StockEntry.php @@ -2,241 +2,242 @@ namespace PartKeepr\Stock; use Doctrine\ORM\Mapping as ORM; -use Doctrine\ORM\Mapping\HasLifecycleCallbacks; use PartKeepr\AuthBundle\Entity\User; use PartKeepr\PartBundle\Entity\Part; -use PartKeepr\PartKeepr; use PartKeepr\Util\BaseEntity; -use PartKeepr\Util\Serializable; - -/** @ORM\Entity @ORM\HasLifecycleCallbacks **/ -class StockEntry extends BaseEntity implements Serializable { - /** - * @ORM\Column(type="integer") - */ - private $stockLevel; - - /** - * @ORM\ManyToOne(targetEntity="PartKeepr\PartBundle\Entity\Part", inversedBy="stockLevels") - */ - private $part; - - /** - * @ORM\ManyToOne(targetEntity="PartKeepr\AuthBundle\Entity\User") - */ - private $user; - - /** - * @ORM\Column(type="decimal",precision=13,scale=4,nullable=true) - * @var float - */ - private $price; - - /** - * @ORM\Column(type="datetime") - * @var DateTime - */ - private $dateTime; - - /** - * Indicates if the stock level is a correction entry. - * - * @ORM\Column(type="boolean") - * @var boolean - */ - private $correction; - - /** - * @ORM\Column(type="string",nullable=true) - * @var string - */ - private $comment; - - - /** - * 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 \PartKeepr\PartBundle\Entity\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 \PartKeepr\AuthBundle\Entity\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); - $this->setDateTime(new \DateTime()); - $this->setCorrection(false); - } - - - /** - * Sets the date+time - * @param \DateTime $dateTime The date+time - */ - private function setDateTime (\DateTime $dateTime) { - $this->dateTime = $dateTime; - } - - /** - * Returns the date+time when the record was created. - * @return \DateTime The date+time when the record was created - */ - public function getDateTime () { - return $this->dateTime; - } - - /** - * Sets if the stock entry is a correction record. - * @param $bCorrection boolean True if the record is a correction record, false otherwise - */ - public function setCorrection ($bCorrection) { - $this->correction = $bCorrection; - } - - /** - * Returns if the entry is a correction entry. - * @return boolean True if the entry is a correction entry, false otherwise - */ - public function getCorrection () { - return $this->correction; - } - - /** - * 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; - } - - /** - * Returns the part assigned to this entry. - * @return Part $part The part - */ - public function getPart () { - return $this->part; - } - - /** - * Sets the user assigned to this entry. - * -*@param \PartKeepr\AuthBundle\Entity\User $user The user The user to set - */ - public function setUser (User $user = null) { - $this->user = $user; - } - - /** - * Returns the user for this entry - * @return User the user - */ - public function getUser () { - return $this->user; - } - - /** - * If the stock level is negative, we can't have a price. - * @ORM\PrePersist - */ - public function checkPrice () { - if ($this->getStockLevel() < 0 && $this->getPrice() !== null) { - $this->setPrice(null); - } - } - - /** - * Updates the stock leve for a part - * @ORM\PostPersist - */ - public function postPersist () { - $this->part->updateStockLevel(); - $this->part->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; - } - } - - /** - * Sets a comment - * @param string $comment - */ - public function setComment ($comment) { - $this->comment = $comment; - } - - /** - * Returns the comment - * @return string The comment - */ - public function getComment () { - return $this->comment; - } - - /** - * (non-PHPdoc) - * @see PartKeepr\Util.Serializable::serialize() - */ - public function serialize () { - return array( - "id" => $this->getId(), - "part_name" => $this->getPart()->getName(), - "part_id" => $this->getPart()->getId(), - "storageLocation_name" => $this->getPart()->getStorageLocation()->getName(), - "username" => is_object($this->getUser()) ? $this->getUser()->getUsername() : PartKeepr::i18n("Unknown User"), - "user_id" => is_object($this->getUser()) ? $this->getUser()->getId() : null, - "stockLevel" => abs($this->getStockLevel()), - "comment" => $this->getComment(), - "dateTime" => $this->getDateTime()->format("Y-m-d H:i:s"), - "direction" => ($this->getStockLevel() < 0) ? "out" : "in", - "price" => $this->getPrice() - ); - } + +/** + * @ORM\Entity + * @ORM\HasLifecycleCallbacks + */ +class StockEntry extends BaseEntity +{ + /** + * @ORM\Column(type="integer") + */ + private $stockLevel; + + /** + * @ORM\ManyToOne(targetEntity="PartKeepr\PartBundle\Entity\Part", inversedBy="stockLevels") + */ + private $part; + + /** + * @ORM\ManyToOne(targetEntity="PartKeepr\AuthBundle\Entity\User") + */ + private $user; + + /** + * @ORM\Column(type="decimal",precision=13,scale=4,nullable=true) + * @var float + */ + private $price; + + /** + * @ORM\Column(type="datetime") + * @var \DateTime + */ + private $dateTime; + + /** + * Indicates if the stock level is a correction entry. + * + * @ORM\Column(type="boolean") + * @var boolean + */ + private $correction; + + /** + * @ORM\Column(type="string",nullable=true) + * @var string + */ + private $comment; + + + /** + * 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 int $stockLevel The stock level. Positive value means added parts, negative values means removed parts. + * @param \PartKeepr\AuthBundle\Entity\User $user The user who removed/added parts + */ + public function __construct($stockLevel, User $user = null) + { + $this->setStockLevel($stockLevel); + $this->setUser($user); + $this->setDateTime(new \DateTime()); + $this->setCorrection(false); + } + + + /** + * Sets the date+time + * + * @param \DateTime $dateTime The date+time + */ + private function setDateTime(\DateTime $dateTime) + { + $this->dateTime = $dateTime; + } + + /** + * Returns the date+time when the record was created. + * + * @return \DateTime The date+time when the record was created + */ + public function getDateTime() + { + return $this->dateTime; + } + + /** + * Sets if the stock entry is a correction record. + * + * @param $bCorrection boolean True if the record is a correction record, false otherwise + */ + public function setCorrection($bCorrection) + { + $this->correction = $bCorrection; + } + + /** + * Returns if the entry is a correction entry. + * + * @return boolean True if the entry is a correction entry, false otherwise + */ + public function getCorrection() + { + return $this->correction; + } + + /** + * 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; + } + + /** + * Returns the part assigned to this entry. + * + * @return Part $part The part + */ + public function getPart() + { + return $this->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; + } + + /** + * Returns the user for this entry + * + * @return User the user + */ + public function getUser() + { + return $this->user; + } + + /** + * If the stock level is negative, we can't have a price. + * + * @ORM\PrePersist + */ + public function checkPrice() + { + if ($this->getStockLevel() < 0 && $this->getPrice() !== null) { + $this->setPrice(null); + } + } + + /** + * 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; + } + } + + /** + * Sets a comment + * + * @param string $comment + */ + public function setComment($comment) + { + $this->comment = $comment; + } + + /** + * Returns the comment + * + * @return string The comment + */ + public function getComment() + { + return $this->comment; + } }