Skip to content

Commit

Permalink
Create more inventory handling
Browse files Browse the repository at this point in the history
  • Loading branch information
loevgaard committed Jun 28, 2024
1 parent 1c5aac6 commit ce33d1c
Show file tree
Hide file tree
Showing 24 changed files with 756 additions and 46 deletions.
32 changes: 32 additions & 0 deletions src/Command/UpdateInventoryCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace Setono\SyliusPeakPlugin\Command;

use Setono\SyliusPeakPlugin\Updater\InventoryUpdaterInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

#[AsCommand(
name: 'setono:sylius-peak-wms:update-inventory',
description: 'This will update the inventory for all product variants',
)]
final class UpdateInventoryCommand extends Command
{
public function __construct(private readonly InventoryUpdaterInterface $inventoryUpdater)

Check warning on line 19 in src/Command/UpdateInventoryCommand.php

View check run for this annotation

Codecov / codecov/patch

src/Command/UpdateInventoryCommand.php#L19

Added line #L19 was not covered by tests
{
parent::__construct();

Check warning on line 21 in src/Command/UpdateInventoryCommand.php

View check run for this annotation

Codecov / codecov/patch

src/Command/UpdateInventoryCommand.php#L21

Added line #L21 was not covered by tests
}

protected function execute(InputInterface $input, OutputInterface $output): int

Check warning on line 24 in src/Command/UpdateInventoryCommand.php

View check run for this annotation

Codecov / codecov/patch

src/Command/UpdateInventoryCommand.php#L24

Added line #L24 was not covered by tests
{
// todo allow the user to specify a product variant id to update
// todo allow the user to force the update of _ALL_ product variants regardless of the last update time
$this->inventoryUpdater->updateAll();

Check warning on line 28 in src/Command/UpdateInventoryCommand.php

View check run for this annotation

Codecov / codecov/patch

src/Command/UpdateInventoryCommand.php#L28

Added line #L28 was not covered by tests

return 0;

Check warning on line 30 in src/Command/UpdateInventoryCommand.php

View check run for this annotation

Codecov / codecov/patch

src/Command/UpdateInventoryCommand.php#L30

Added line #L30 was not covered by tests
}
}
15 changes: 15 additions & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Setono\SyliusPeakPlugin\DependencyInjection;

use Setono\SyliusPeakPlugin\Model\InventoryUpdate;
use Setono\SyliusPeakPlugin\Model\RegisteredWebhooks;
use Setono\SyliusPeakPlugin\Model\UploadOrderRequest;
use Sylius\Component\Resource\Factory\Factory;
Expand Down Expand Up @@ -42,6 +43,20 @@ private function addResourcesSection(ArrayNodeDefinition $node): void
->arrayNode('resources')
->addDefaultsIfNotSet()
->children()
->arrayNode('inventory_update')
->addDefaultsIfNotSet()
->children()
->variableNode('options')->end()
->arrayNode('classes')
->addDefaultsIfNotSet()
->children()
->scalarNode('model')->defaultValue(InventoryUpdate::class)->cannotBeEmpty()->end()
->scalarNode('repository')->cannotBeEmpty()->end()
->scalarNode('factory')->defaultValue(Factory::class)->end()
->end()
->end()
->end()
->end()
->arrayNode('registered_webhooks')
->addDefaultsIfNotSet()
->children()
Expand Down
3 changes: 2 additions & 1 deletion src/DependencyInjection/SetonoSyliusPeakExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Setono\SyliusPeakPlugin\DataMapper\SalesOrderDataMapperInterface;
use Setono\SyliusPeakPlugin\WebhookHandler\WebhookHandlerInterface;
use Setono\SyliusPeakPlugin\Workflow\InventoryUpdateWorkflow;
use Setono\SyliusPeakPlugin\Workflow\UploadOrderRequestWorkflow;
use Sylius\Bundle\ResourceBundle\DependencyInjection\Extension\AbstractResourceExtension;
use Sylius\Bundle\ResourceBundle\SyliusResourceBundle;
Expand Down Expand Up @@ -58,7 +59,7 @@ public function prepend(ContainerBuilder $container): void
],
],
],
'workflows' => UploadOrderRequestWorkflow::getConfig(),
'workflows' => UploadOrderRequestWorkflow::getConfig() + InventoryUpdateWorkflow::getConfig(),
]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace Setono\SyliusPeakPlugin\EventSubscriber\Workflow\InventoryUpdate;

use Setono\SyliusPeakPlugin\Model\InventoryUpdateInterface;
use Setono\SyliusPeakPlugin\Workflow\InventoryUpdateWorkflow;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Workflow\Event\CompletedEvent;
use Webmozart\Assert\Assert;

final class CompleteSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array

Check warning on line 15 in src/EventSubscriber/Workflow/InventoryUpdate/CompleteSubscriber.php

View check run for this annotation

Codecov / codecov/patch

src/EventSubscriber/Workflow/InventoryUpdate/CompleteSubscriber.php#L15

Added line #L15 was not covered by tests
{
return [
sprintf('workflow.%s.completed.%s', InventoryUpdateWorkflow::NAME, InventoryUpdateWorkflow::TRANSITION_COMPLETE) => 'set',
];

Check warning on line 19 in src/EventSubscriber/Workflow/InventoryUpdate/CompleteSubscriber.php

View check run for this annotation

Codecov / codecov/patch

src/EventSubscriber/Workflow/InventoryUpdate/CompleteSubscriber.php#L17-L19

Added lines #L17 - L19 were not covered by tests
}

public function set(CompletedEvent $event): void

Check warning on line 22 in src/EventSubscriber/Workflow/InventoryUpdate/CompleteSubscriber.php

View check run for this annotation

Codecov / codecov/patch

src/EventSubscriber/Workflow/InventoryUpdate/CompleteSubscriber.php#L22

Added line #L22 was not covered by tests
{
/** @var InventoryUpdateInterface|object $inventoryUpdate */
$inventoryUpdate = $event->getSubject();
Assert::isInstanceOf($inventoryUpdate, InventoryUpdateInterface::class);

Check warning on line 26 in src/EventSubscriber/Workflow/InventoryUpdate/CompleteSubscriber.php

View check run for this annotation

Codecov / codecov/patch

src/EventSubscriber/Workflow/InventoryUpdate/CompleteSubscriber.php#L25-L26

Added lines #L25 - L26 were not covered by tests

$inventoryUpdate->setCompletedAt(new \DateTimeImmutable());

Check warning on line 28 in src/EventSubscriber/Workflow/InventoryUpdate/CompleteSubscriber.php

View check run for this annotation

Codecov / codecov/patch

src/EventSubscriber/Workflow/InventoryUpdate/CompleteSubscriber.php#L28

Added line #L28 was not covered by tests

if (!$inventoryUpdate->hasErrors()) {
$inventoryUpdate->setNextUpdateThreshold($inventoryUpdate->getProcessingStartedAt());

Check warning on line 31 in src/EventSubscriber/Workflow/InventoryUpdate/CompleteSubscriber.php

View check run for this annotation

Codecov / codecov/patch

src/EventSubscriber/Workflow/InventoryUpdate/CompleteSubscriber.php#L30-L31

Added lines #L30 - L31 were not covered by tests
}
}
}
30 changes: 30 additions & 0 deletions src/EventSubscriber/Workflow/InventoryUpdate/ProcessSubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Setono\SyliusPeakPlugin\EventSubscriber\Workflow\InventoryUpdate;

use Setono\SyliusPeakPlugin\Model\InventoryUpdateInterface;
use Setono\SyliusPeakPlugin\Workflow\InventoryUpdateWorkflow;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Workflow\Event\CompletedEvent;
use Webmozart\Assert\Assert;

final class ProcessSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array

Check warning on line 15 in src/EventSubscriber/Workflow/InventoryUpdate/ProcessSubscriber.php

View check run for this annotation

Codecov / codecov/patch

src/EventSubscriber/Workflow/InventoryUpdate/ProcessSubscriber.php#L15

Added line #L15 was not covered by tests
{
return [
sprintf('workflow.%s.completed.%s', InventoryUpdateWorkflow::NAME, InventoryUpdateWorkflow::TRANSITION_PROCESS) => 'set',
];

Check warning on line 19 in src/EventSubscriber/Workflow/InventoryUpdate/ProcessSubscriber.php

View check run for this annotation

Codecov / codecov/patch

src/EventSubscriber/Workflow/InventoryUpdate/ProcessSubscriber.php#L17-L19

Added lines #L17 - L19 were not covered by tests
}

public function set(CompletedEvent $event): void

Check warning on line 22 in src/EventSubscriber/Workflow/InventoryUpdate/ProcessSubscriber.php

View check run for this annotation

Codecov / codecov/patch

src/EventSubscriber/Workflow/InventoryUpdate/ProcessSubscriber.php#L22

Added line #L22 was not covered by tests
{
/** @var InventoryUpdateInterface|object $inventoryUpdate */
$inventoryUpdate = $event->getSubject();
Assert::isInstanceOf($inventoryUpdate, InventoryUpdateInterface::class);

Check warning on line 26 in src/EventSubscriber/Workflow/InventoryUpdate/ProcessSubscriber.php

View check run for this annotation

Codecov / codecov/patch

src/EventSubscriber/Workflow/InventoryUpdate/ProcessSubscriber.php#L25-L26

Added lines #L25 - L26 were not covered by tests

$inventoryUpdate->setProcessingStartedAt(new \DateTimeImmutable());

Check warning on line 28 in src/EventSubscriber/Workflow/InventoryUpdate/ProcessSubscriber.php

View check run for this annotation

Codecov / codecov/patch

src/EventSubscriber/Workflow/InventoryUpdate/ProcessSubscriber.php#L28

Added line #L28 was not covered by tests
}
}
33 changes: 33 additions & 0 deletions src/EventSubscriber/Workflow/InventoryUpdate/ResetSubscriber.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace Setono\SyliusPeakPlugin\EventSubscriber\Workflow\InventoryUpdate;

use Setono\SyliusPeakPlugin\Model\InventoryUpdateInterface;
use Setono\SyliusPeakPlugin\Workflow\InventoryUpdateWorkflow;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\Workflow\Event\CompletedEvent;
use Webmozart\Assert\Assert;

final class ResetSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array

Check warning on line 15 in src/EventSubscriber/Workflow/InventoryUpdate/ResetSubscriber.php

View check run for this annotation

Codecov / codecov/patch

src/EventSubscriber/Workflow/InventoryUpdate/ResetSubscriber.php#L15

Added line #L15 was not covered by tests
{
return [
sprintf('workflow.%s.completed.%s', InventoryUpdateWorkflow::NAME, InventoryUpdateWorkflow::TRANSITION_RESET) => 'reset',
];

Check warning on line 19 in src/EventSubscriber/Workflow/InventoryUpdate/ResetSubscriber.php

View check run for this annotation

Codecov / codecov/patch

src/EventSubscriber/Workflow/InventoryUpdate/ResetSubscriber.php#L17-L19

Added lines #L17 - L19 were not covered by tests
}

public function reset(CompletedEvent $event): void

Check warning on line 22 in src/EventSubscriber/Workflow/InventoryUpdate/ResetSubscriber.php

View check run for this annotation

Codecov / codecov/patch

src/EventSubscriber/Workflow/InventoryUpdate/ResetSubscriber.php#L22

Added line #L22 was not covered by tests
{
/** @var InventoryUpdateInterface|object $inventoryUpdate */
$inventoryUpdate = $event->getSubject();
Assert::isInstanceOf($inventoryUpdate, InventoryUpdateInterface::class);

Check warning on line 26 in src/EventSubscriber/Workflow/InventoryUpdate/ResetSubscriber.php

View check run for this annotation

Codecov / codecov/patch

src/EventSubscriber/Workflow/InventoryUpdate/ResetSubscriber.php#L25-L26

Added lines #L25 - L26 were not covered by tests

$inventoryUpdate->setCompletedAt(null);
$inventoryUpdate->setProcessingStartedAt(null);
$inventoryUpdate->setWarnings(null);
$inventoryUpdate->setErrors(null);

Check warning on line 31 in src/EventSubscriber/Workflow/InventoryUpdate/ResetSubscriber.php

View check run for this annotation

Codecov / codecov/patch

src/EventSubscriber/Workflow/InventoryUpdate/ResetSubscriber.php#L28-L31

Added lines #L28 - L31 were not covered by tests
}
}
21 changes: 15 additions & 6 deletions src/Message/Command/UpdateInventory.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,28 @@

use Sylius\Component\Core\Model\ProductVariantInterface;

/**
* Will update the inventory for a product variant
*/
final class UpdateInventory implements CommandInterface
{
public int $productVariant;
public ?int $productVariant = null;

public function __construct(int|ProductVariantInterface $productVariant)
private function __construct()

Check warning on line 13 in src/Message/Command/UpdateInventory.php

View check run for this annotation

Codecov / codecov/patch

src/Message/Command/UpdateInventory.php#L13

Added line #L13 was not covered by tests
{
}

public static function for(int|ProductVariantInterface $productVariant): self

Check warning on line 17 in src/Message/Command/UpdateInventory.php

View check run for this annotation

Codecov / codecov/patch

src/Message/Command/UpdateInventory.php#L17

Added line #L17 was not covered by tests
{
if ($productVariant instanceof ProductVariantInterface) {
$productVariant = (int) $productVariant->getId();
}

$this->productVariant = $productVariant;
$command = new self();
$command->productVariant = $productVariant;

Check warning on line 24 in src/Message/Command/UpdateInventory.php

View check run for this annotation

Codecov / codecov/patch

src/Message/Command/UpdateInventory.php#L23-L24

Added lines #L23 - L24 were not covered by tests

return $command;

Check warning on line 26 in src/Message/Command/UpdateInventory.php

View check run for this annotation

Codecov / codecov/patch

src/Message/Command/UpdateInventory.php#L26

Added line #L26 was not covered by tests
}

public static function forAll(): self

Check warning on line 29 in src/Message/Command/UpdateInventory.php

View check run for this annotation

Codecov / codecov/patch

src/Message/Command/UpdateInventory.php#L29

Added line #L29 was not covered by tests
{
return new self();

Check warning on line 31 in src/Message/Command/UpdateInventory.php

View check run for this annotation

Codecov / codecov/patch

src/Message/Command/UpdateInventory.php#L31

Added line #L31 was not covered by tests
}
}
43 changes: 9 additions & 34 deletions src/Message/CommandHandler/UpdateInventoryHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,58 +4,33 @@

namespace Setono\SyliusPeakPlugin\Message\CommandHandler;

use Setono\PeakWMS\Client\ClientInterface;
use Setono\PeakWMS\DataTransferObject\Product\Product;
use Setono\SyliusPeakPlugin\Message\Command\UpdateInventory;
use Setono\SyliusPeakPlugin\Updater\InventoryUpdaterInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Sylius\Component\Core\Repository\ProductVariantRepositoryInterface;
use Symfony\Component\Messenger\Exception\UnrecoverableMessageHandlingException;

final class UpdateInventoryHandler
{
public function __construct(
private readonly ClientInterface $client,
private readonly ProductVariantRepositoryInterface $productVariantRepository,
private readonly InventoryUpdaterInterface $inventoryUpdater,
) {
}

public function __invoke(UpdateInventory $message): void
{
$productVariant = $this->productVariantRepository->find($message->productVariant);
if (!$productVariant instanceof ProductVariantInterface) {
throw new UnrecoverableMessageHandlingException(sprintf('Product variant with id %d not found', $message->productVariant));
}

$productCode = $productVariant->getProduct()?->getCode();
$variantCode = $productVariant->getCode();

if (null === $productCode || null === $variantCode) {
throw new UnrecoverableMessageHandlingException(sprintf('Product variant with id %d does not have a product code or variant code', $message->productVariant));
}

$collection = $this
->client
->product()
->getByProductId($productCode)
->filter(fn (Product $product) => $product->variantId === $variantCode)
;
if (null === $message->productVariant) {
$this->inventoryUpdater->updateAll();

Check warning on line 24 in src/Message/CommandHandler/UpdateInventoryHandler.php

View check run for this annotation

Codecov / codecov/patch

src/Message/CommandHandler/UpdateInventoryHandler.php#L23-L24

Added lines #L23 - L24 were not covered by tests

if (count($collection) === 0) {
throw new UnrecoverableMessageHandlingException(sprintf('The product with id %s does not have a variant with id/code %s', $productCode, $variantCode));
return;

Check warning on line 26 in src/Message/CommandHandler/UpdateInventoryHandler.php

View check run for this annotation

Codecov / codecov/patch

src/Message/CommandHandler/UpdateInventoryHandler.php#L26

Added line #L26 was not covered by tests
}

if (count($collection) > 1) {
throw new UnrecoverableMessageHandlingException(sprintf('The product with id %s has multiple products with the same variant id/code', $productCode));
}

$peakProduct = $collection[0];

if (null === $peakProduct->availableToSell) {
throw new UnrecoverableMessageHandlingException(sprintf('The product with id %s and variant id/code %s does not have an availableToSell value', $productCode, $variantCode));
$productVariant = $this->productVariantRepository->find($message->productVariant);
if (!$productVariant instanceof ProductVariantInterface) {
throw new UnrecoverableMessageHandlingException(sprintf('Product variant with id %d does not exist', $message->productVariant));

Check warning on line 31 in src/Message/CommandHandler/UpdateInventoryHandler.php

View check run for this annotation

Codecov / codecov/patch

src/Message/CommandHandler/UpdateInventoryHandler.php#L29-L31

Added lines #L29 - L31 were not covered by tests
}

$productVariant->setOnHand($peakProduct->availableToSell + (int) $productVariant->getOnHold());

$this->productVariantRepository->add($productVariant);
$this->inventoryUpdater->update($productVariant);

Check warning on line 34 in src/Message/CommandHandler/UpdateInventoryHandler.php

View check run for this annotation

Codecov / codecov/patch

src/Message/CommandHandler/UpdateInventoryHandler.php#L34

Added line #L34 was not covered by tests
}
}
Loading

0 comments on commit ce33d1c

Please sign in to comment.