Manager class used to create appropriate stock history entries for the various stock actions.
The following stock actions are supported:
1) PURCHASE New items of an article are purchased for a given purchase price and stored within the warehouse.
2) STOCKTAKE All available items of an article within the warehouse are counted and the article's instock quantity is updated accordingly.
3) SALE A given amount of items of an article has been sold and is removed from the warehouse.
4) RETURN A given amount of items of an article has been returned by the customer and is added to the warehouse.
5) MANUAL The instock quantity of an article is changed manually.
6) INCOMING An arbitrary incoming amount is added to the stock.
7) OUTGOING An arbitrary outgoing amount is removed from the stock.
These actions can be roughly divided into two groups: "incoming" and "outgoing", whereas "incoming" refers to all history entries, which are related to the storage of items within the warehouse and "outgoing" refers to all entries, which are concerned with the removal of items from the warehouse:
a) "incoming":
manual entry with positive change amount
b) "outgoing"
History entries for "neutral" stocktake actions (change amount is zero) play a minor role and therefore are not listed above, since they "have no effect" and are created only for informational purposes.
To enable the computation of the inventory value (Bewerteter Warenbestand) for a given reference date, we need to link "outgoing" and "incoming" entries in a suitable way. If possible, each "outgoing" entry is therefore related to an "incoming" entry, which is called it's source lot entry. "Incoming" entries are assigned to "outgoing" entries based on their "free capacity" and in accordance with the LIFO (Last In First Out) principle, meaning "incoming" entries are assigned in their reversed creation order. The assignment process is (roughly) as follows:
1) get a list of all "incoming" entries for the given article in their reversed creation order 2) compute the "free capacity" for each "incoming" entry in the list, whereas the "free capacity" is calculated as follows: change amount of "incoming" entry minus the sum of the change amounts of all already assigned "outgoing" entries 3) Remove all entries from the list, whose "free capacity" = 0 4) Check "free capacity" of the first list entry: a) "free capacity" >= change amount of "outgoing" entry? Create a new "outgoing" entry for the given change amount and assign it to the "incoming" entry b) "free capacity" < change amount of "outgoing" entry? Create a new "outgoing" entry with change amount = "free capacity" and assign the "incoming" entry to the newly created "outgoing" entry. Remove the "incoming" entry from the list and repeat step 4) until no unprocessed change amount remains or the list is empty 5) If some unprocessed change amount remains, create a new unassigned "outgoing" entry for the remaining change amount (purchase price = default purchase price)
"Outgoing" entries created in step 4) are called assigned, whereas those created in step 5) are called unassigned. If the assignment process results in a single "outgoing" entry, this entry is called a singlepart entry otherwise the set of newly created entries is called a multipart entry.
The instock quantity of each article, which is tracked within the stock history and the one maintained by Shopware (within the article details) may differ, since Shopware updates his counter as soon as a new order has been created, whereas the one maintained within the stock history is intended to track the physical item movements and is therefore (usually) not updated before the order is completely fulfilled and all items have been shipped. To keep these counters in sync the manager class takes care of updating the Shopware counter, when creating new history entries.
Remark: The purchase price of the default customer group of the active shop is used as default purchase price.
package |
Default |
---|
__construct(\Shopware\Components\Model\ModelManager $entityManager, \Shopware_Components_Snippet_Manager $snippetManager, \Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\StockChangeListFactory $stockChangeListFactory, \Shopware\Plugins\ViisonPickwareERP\Components\DerivedPropertyUpdater\DerivedPropertyUpdater $derivedPropertyUpdater, \Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\ArticleDetailStockInfoProvider $articleDetailStockInfoProvider, \Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\ArticleDetailConcurrencyCoordinator $articleDetailConcurrencyCoordinator, \Psr\Log\LoggerInterface $logger)
\Shopware\Components\Model\ModelManager
\Shopware_Components_Snippet_Manager
\Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\StockChangeListFactory
\Shopware\Plugins\ViisonPickwareERP\Components\DerivedPropertyUpdater\DerivedPropertyUpdater
\Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\ArticleDetailStockInfoProvider
\Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\ArticleDetailConcurrencyCoordinator
\Psr\Log\LoggerInterface
calculateChangedBinLocations(integer $stockLedgerEntryId) : array
Tries to find the stock entry with the given $stockLedgerEntryId as well as the entry directly preceding that stock entry to calculate the difference between their snapshots, which is then returned.
integer
array
discardStock(\Shopware\Models\Article\Detail $articleDetail, \Shopware\CustomModels\ViisonPickwareERP\Warehouse\Warehouse $warehouse, string|null $comment = null, \Shopware\Models\User\User|null $user = null)
\Shopware\Models\Article\Detail
string|null
\Shopware\Models\User\User|null
getTransactionId() : string
string
initializeStockOfArticleDetail(\Shopware\Models\Article\Detail $articleDetail, \Shopware\CustomModels\ViisonPickwareERP\Warehouse\BinLocation $binLocation, integer $actualStock, string $comment = '', \Shopware\Models\User\User|null $user = null) : array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
Throws |
|
---|
\Shopware\Models\Article\Detail
\Shopware\CustomModels\ViisonPickwareERP\Warehouse\BinLocation
The bin location that should be changed when adjusting the stock.
integer
The actual, physical stock across all warehouses.
string
\Shopware\Models\User\User|null
array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
performWithLockForArticleDetail(\Shopware\Models\Article\Detail $articleDetail, \Closure $closure) : mixed
Throws |
|
---|
\Shopware\Models\Article\Detail
\Closure
mixed
recordIncomingStock(\Shopware\Models\Article\Detail $articleDetail, \Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\PositiveStockChangeList $stockChanges, float|null $purchasePrice = null, string $comment = '', \Shopware\Models\User\User|null $user = null) : array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
This happens when the stock amount for an individual article is increased through the app.
\Shopware\Models\Article\Detail
\Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\PositiveStockChangeList
float|null
The price the incoming quantity was purchased for
string
An optional comment
\Shopware\Models\User\User|null
array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
recordOutgoingStock(\Shopware\Models\Article\Detail $articleDetail, \Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\NegativeStockChangeList $stockChanges, string $comment = '', \Shopware\Models\User\User|null $user = null) : array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
This happens when the stock amount for an individual article is decreased through the app.
\Shopware\Models\Article\Detail
\Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\NegativeStockChangeList
string
An optional comment
\Shopware\Models\User\User|null
array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
recordPurchasedStock(\Shopware\Models\Article\Detail $articleDetail, \Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\PositiveStockChangeList $stockChanges, float|null $purchasePrice = null, string $comment = '', \Shopware\CustomModels\ViisonPickwareERP\SupplierOrder\SupplierOrderItem|null $supplierOrderItem = null, \Shopware\Models\User\User|null $user = null) : array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
This happens when a supplier order is received and processed in the warehouse.
\Shopware\Models\Article\Detail
\Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\PositiveStockChangeList
float|null
The price the quantity was purchased for
string
An optional comment
\Shopware\CustomModels\ViisonPickwareERP\SupplierOrder\SupplierOrderItem|null
An optional supplier order article to be associated with the purchase
\Shopware\Models\User\User|null
array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
recordRelocatedStock(\Shopware\Models\Article\Detail $articleDetail, \Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\RelocationStockChangeList $stockChanges, string $comment = '', \Shopware\Models\User\User|null $user = null) : array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
Those validations apply to all source bin locations, except for the warehouse's null bin location, if present. We allow this exception, because we have to acknowledge that stocks might be corrupt in a way, that in the real world stock exists, but that stock is not reflected in the database, which results in zero or negative stock on the null bin location (see \self::updateBinLocationMappings()). In that case, relocating that stock in the real world must still be possible (see https://github.com/VIISON/ShopwarePickwareMobile/issues/163). Once validated, depending on the warehouses of the source and destination bin locations, the relocation is performed by either logging a 'relocation' in the managed warehouse or by logging a sequence of stock entries for a relocation to a different warehouse than the one managed by this stock manager.
Throws |
|
---|
\Shopware\Models\Article\Detail
\Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\RelocationStockChangeList
string
\Shopware\Models\User\User|null
array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
recordReturnedStock(\Shopware\Models\Article\Detail $articleDetail, \Shopware\CustomModels\ViisonPickwareERP\ReturnShipment\ReturnShipmentItem $returnShipmentItem, \Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\PositiveStockChangeList $stockChanges, string $comment = '', \Shopware\Models\User\User|null $user = null) : array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
This happens when a return shipment is received from a customer and unpacked in the warehouse.
\Shopware\Models\Article\Detail
\Shopware\CustomModels\ViisonPickwareERP\ReturnShipment\ReturnShipmentItem
An optional reshipment item to be associated with the return
\Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\PositiveStockChangeList
string
An optional comment
\Shopware\Models\User\User|null
array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
recordReturnedStockCorrection(\Shopware\Models\Article\Detail $articleDetail, \Shopware\CustomModels\ViisonPickwareERP\ReturnShipment\ReturnShipmentItem $returnShipmentItem, \Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\NegativeStockChangeList $stockChanges, string $comment = '', \Shopware\Models\User\User|null $user = null) : array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
Correction for \self::recordReturnedStock()
\Shopware\Models\Article\Detail
\Shopware\CustomModels\ViisonPickwareERP\ReturnShipment\ReturnShipmentItem
An optional reshipment item to be associated with the return
\Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\NegativeStockChangeList
string
An optional comment
\Shopware\Models\User\User|null
array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
recordReturnedStockWithoutReturnShipment(\Shopware\Models\Article\Detail $articleDetail, \Shopware\Models\Order\Detail $orderDetail, \Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\PositiveStockChangeList $stockChanges, string $comment = '', \Shopware\Models\User\User|null $user = null) : array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
A special function made exclusively for POS, because POS does not create ReturnShipments.
\Shopware\Models\Article\Detail
\Shopware\Models\Order\Detail
\Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\PositiveStockChangeList
string
\Shopware\Models\User\User|null
array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
recordSoldStock(\Shopware\Models\Article\Detail $articleDetail, \Shopware\Models\Order\Detail $orderDetail, \Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\NegativeStockChangeList $stockChanges, string $comment = '', \Shopware\Models\User\User|null $user = null) : array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
This happens when a customer order is shipped.
\Shopware\Models\Article\Detail
\Shopware\Models\Order\Detail
The order detail, which was sold
\Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\NegativeStockChangeList
string
An optional comment
\Shopware\Models\User\User|null
array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
recordSoldStockCorrection(\Shopware\Models\Article\Detail $articleDetail, \Shopware\Models\Order\Detail $orderDetail, \Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\PositiveStockChangeList $stockChanges, string $comment = '', \Shopware\Models\User\User|null $user = null) : array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
Correction for \self::recordSoldStock()
\Shopware\Models\Article\Detail
\Shopware\Models\Order\Detail
\Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\PositiveStockChangeList
string
\Shopware\Models\User\User|null
array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
recordStocktake(\Shopware\Models\Article\Detail $articleDetail, \Shopware\CustomModels\ViisonPickwareERP\Warehouse\BinLocation $binLocation, integer $actualStock, string $comment = '', \Shopware\Models\User\User|null $user = null) : array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
Happens when a stocktake is performed using the app.
Throws |
|
---|
\Shopware\Models\Article\Detail
\Shopware\CustomModels\ViisonPickwareERP\Warehouse\BinLocation
The bin location, whose actual stock shall be logged
integer
The actual physical stock quantity
string
An optional comment
\Shopware\Models\User\User|null
array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
recordWriteOff(\Shopware\Models\Article\Detail $articleDetail, \Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\NegativeStockChangeList $stockChanges, \Shopware\CustomModels\ViisonPickwareERP\ReturnShipment\ReturnShipmentItem|null $returnShipmentItem = null, string $comment = '', \Shopware\Models\User\User|null $user = null) : array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
That is when an item from a return must be written-off or an item in the warehouse must be written-off.
\Shopware\Models\Article\Detail
\Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\NegativeStockChangeList
\Shopware\CustomModels\ViisonPickwareERP\ReturnShipment\ReturnShipmentItem|null
string
\Shopware\Models\User\User|null
array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
recordWriteOffCorrection(\Shopware\Models\Article\Detail $articleDetail, \Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\PositiveStockChangeList $stockChanges, \Shopware\CustomModels\ViisonPickwareERP\ReturnShipment\ReturnShipmentItem|null $returnShipmentItem = null, string $comment = '', \Shopware\Models\User\User|null $user = null) : array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
Correction for \self::recordSoldStock()
\Shopware\Models\Article\Detail
\Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\PositiveStockChangeList
\Shopware\CustomModels\ViisonPickwareERP\ReturnShipment\ReturnShipmentItem|null
string
\Shopware\Models\User\User|null
array<mixed,\Shopware\CustomModels\ViisonPickwareERP\StockLedger\StockLedgerEntry>
reinstateStock(\Shopware\Models\Article\Detail $articleDetail, $comment = null, \Shopware\Models\User\User|null $user = null) : void
Throws |
|
---|
\Shopware\Models\Article\Detail
\Shopware\Models\User\User|null
selectDefaultBinLocation(\Shopware\Models\Article\Detail $articleDetail, \Shopware\CustomModels\ViisonPickwareERP\Warehouse\Warehouse $warehouse, \Shopware\CustomModels\ViisonPickwareERP\Warehouse\BinLocation|null $newDefaultBinLocation = null)
Uses the given $newDefaultBinLocation to either create or update a mapping from the managed article detail to that bin location and mark it as the default mapping in the managed warehouse. If any other bin location is currently mapped as the default location, the respective mapping is updated and removed, if it does not contain any stock. Passing null as the new default bin location causes the current default bin location mapping to be deselected as the default, effectively leaving the managed article detail without a default bin location mapping. In any case, the bin location mappings of the managed article detail are updated to ensure that any obsolete bin location mappings are removed or new mappings are created as necessary.
\Shopware\Models\Article\Detail
\Shopware\CustomModels\ViisonPickwareERP\Warehouse\BinLocation|null
startRecordingStockChangesForArticleDetail(\Shopware\Models\Article\Detail $articleDetail)
\Shopware\Models\Article\Detail
stopRecordingStockChangesForArticleDetail(\Shopware\Models\Article\Detail $articleDetail)
\Shopware\Models\Article\Detail
updateBinLocationMappings(\Shopware\Models\Article\Detail $articleDetail, \Shopware\Plugins\ViisonPickwareERP\Components\StockLedger\StockChangeList\AbstractStockChangeList $stockChanges)
For all bin locations affected by the given $stockChanges either an existing mapping is found and updated/removed or a new mapping is created. Then it is asserted that at least one bin location mapping exists and all negative stock resulting from the $stockChanges is moved to the null bin location mapping.
\Shopware\Models\Article\Detail
ENTRIES
POSTFIXES