justbetter / laravel-magento-stock
This packages facilitates a generic way to push stock to Magento.
Installs: 5 772
Dependents: 1
Suggesters: 0
Security: 0
Stars: 5
Watchers: 5
Forks: 0
Open Issues: 0
Type:package
Requires
- php: ^8.1
- justbetter/laravel-error-logger: ^2.3
- justbetter/laravel-magento-client: ^2.4
- justbetter/laravel-magento-products: ^1.4
- laravel/framework: ^10.0|^11.0
- spatie/laravel-activitylog: ^4.7
Requires (Dev)
- doctrine/dbal: ^3.4
- larastan/larastan: ^2.9
- laravel/pint: ^1.6
- orchestra/testbench: ^8.0|^9.0
- phpstan/phpstan-mockery: ^1.1
- phpunit/phpunit: ^10.0
README
Laravel Magento Stock
This packages facilitates a way to push stock to Magento from a configurable source. Both simple stock and MSI are supported.
Features
This package provides all the logic of synchronizing stock to Magento so that you only have to write the way stock is retrieved.
Features:
- Retrieve stock from any source using your own retriever class
- MSI support
- Only update stock when there are modifications
- Automatically stop syncing when there are too many errors (configurable)
- Compare stock between Magento and this package
- Logs activities using Spatie activitylog
- Logs errors using JustBetter Error Logger
- Checks if Magento products exist using JustBetter Magento Products
Also check out our other [Laravel Magento packages)(https://github.com/justbetter?q=laravel-magento)! We also have a Magento Client to easily connect Laravel to Magento!
Installation
Require this package: composer require justbetter/laravel-magento-stock
Publish the config
php artisan vendor:publish --provider="JustBetter\MagentoStock\ServiceProvider" --tag="config"
Publish the activity log's migrations:
php artisan vendor:publish --provider="Spatie\Activitylog\ActivitylogServiceProvider" --tag="activitylog-migrations"
Run migrations.
php artisan migrate
TIP: All actions in this package are run via jobs, we recommend Laravel Horizon or another queueing system to run these
Laravel Nova
We have a Laravel Nova integration for this package.
Setup
In order to sync stock you have to write a retriever class. This class is responsible for retrieving stock from your source for a single sku.
For example:
<?php namespace App\Integrations\Stock; class SomeStockRetriever implements \JustBetter\MagentoStock\Contracts\RetrievesStock { public function retrieve(string $sku): ?StockData { $quantity = 5; return StockData::make($sku, $quantity); } }
You also have to implement a class that retrieves skus.
For example:
<?php namespace App\Integrations\Stock; class SomeStockSkuRetriever implements \JustBetter\MagentoStock\Contracts\RetrievesStockSkus { public function retrieveAll(): Enumerable { return collect(['sku_1', 'sku_2', 'sku_3']); } public function retrieveUpdated(?Carbon $from = null): Enumerable { return collect(['sku_1']); } }
These should return a simple collection of skus:
['sku_1', 'sku_2', ...]
You can then register your retrievers in the config file:
<?php return [ 'retriever' => [ /* Class that is responsible for retrieving stock */ 'stock' => \App\Integrations\Stock\SomeStockRetriever::class, /* Class that is responsible for retrieving sku's */ 'sku' => \App\Integrations\Stock\SomeStockSkuRetriever::class, ], ];
Testing your retrievers
To test your retrievers you can use the following commands:
php artisan magento:stock:retrieve {sku}
php artisan magento:stock:retrieve-all
php artisan magento:stock:retrieve-updated {from?}
Magento MSI
If you have Magento MSI enabled you have to return the quantity of each source in our retriever.
NOTE: Be sure to set the
msi
config setting to true!
For example:
<?php namespace App\Integrations\Stock; class SomeStockRetriever implements \JustBetter\MagentoStock\Contracts\RetrievesStock { public function retrieve(string $sku): ?StockData { $data = StockData::make($sku); // You can set the quantity/status per source $data->setMsiQuantity('A', 10); $data->setMsiQuantity('B', 0); // Will also set the status to out of stock $data->setMsiQuantity('C', 0); $data->setMsiStatus('C', true); // Or you can set it in bulk $data->setMsiQuantities([ 'A' => 10, 'B' => 0, 'C' => 0, ]); $data->setMsiStatusses([ 'A' => true, 'B' => false, 'C' => true, ]); return $data; } }
Custom retrievers
If you cannot retrieve the sku's and stock data separately you can setup a custom retriever. For example if you have XML or CSV files with stock data that include the sku and a quantity.
The basic flow of your retriever should be:
- Read stock data your source per sku
- Build a
\JustBetter\MagentoStock\Data\StockData
object - Dispatch a
\JustBetter\MagentoStock\Jobs\ProcessStockJob
job
You can then never run the magento:stock:retrieve*
commands and schedule your own retriever. To be extra safe you can
still register your own retrieve and return null
and empty collections to be sure that the default dummy sku/stock
retrievers never execute.
Processing complex stock logic
If you need to apply complex stock logic you can implement a calculator. A calculator's goal is to modify
the \JustBetter\MagentoStock\Data\StockData
object. By default, this only sets the in/out of stock status based on the
quantity.
See the \JustBetter\MagentoStock\Calculators\SimpleStockCalculator
for an example.
If you want to use your own calculator you can set it in the config file:
<?php return [ /* Class to calculate stock */ 'calculator' => SimpleStockCalculator::class, ];
Schedule
<?php protected function schedule(Schedule $schedule): void { // Run every minute to dispatch retrieve & update jobs $schedule->command(\JustBetter\MagentoStock\Commands\SyncStockCommand::class)->everyMinute(); $schedule->command(\JustBetter\MagentoStock\Commands\RetrieveAllStockCommand::class)->dailyAt('05:00'); $schedule->command(\JustBetter\MagentoStock\Commands\RetrieveUpdatedStockCommand::class)->everyFiveMinutes(); // Compare all stocks in Magento $schedule->command(\JustBetter\MagentoStock\Commands\CompareStockCommand::class)->dailyAt('08:00'); }
Comparisons
This package provides a way to compare stock quantities in Magento with those in the Laravel database. If a difference is detected it will start an update for that product.
An event is dispatched when a difference is detected \JustBetter\MagentoStock\Events\DifferenceDetectedEvent
.
Handling failures
When an update fails it will try again. A fail counter is stored with the model which is increased at each failure.
In the config you can specify how many times the update may be attempted:
<?php return [ /* How many times can a stock update failed before being cancelled */ 'fail_count' => 5, ];
You can restart the updates for a product by setting the sync
field in the DB to true.
Long Waits
The sync limits the amount of products that are retrieved/updated each sync. This may result in long waits if not properly configured for the amount of updates you get.
To detect this you can add the \JustBetter\MagentoStock\Commands\MonitorWaitTimesCommand
to your schedule. This will
fire the \JustBetter\MagentoStock\Events\LongWaitDetectedEvent
event in which you can for example trigger more updates
or send a notification.
You can configure the limits of when the event will be fired in the config:
<?php return [ 'monitor' => [ /* Max wait time in minutes, if exceeded the LongWaitDetected event is dispatched */ 'retrieval_max_wait' => 30, /* Max wait time in minutes, if exceeded the LongWaitDetected event is dispatched */ 'update_max_wait' => 30, ] ];
Quality
To ensure the quality of this package, run the following command:
composer quality
This will execute three tasks:
- Makes sure all tests are passed
- Checks for any issues using static code analysis
- Checks if the code is correctly formatted
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.