Skip to content

Commit

Permalink
Merge pull request #18 from webgriffe/issue-12
Browse files Browse the repository at this point in the history
Allow to enqueue all identifiers from specific importer(s)
  • Loading branch information
mmenozzi authored Nov 16, 2020
2 parents 5a2bc33 + d62064a commit 08ac69b
Show file tree
Hide file tree
Showing 15 changed files with 365 additions and 176 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,18 @@ When run with the since file, the enqueue command will write the current date/ti

This way the enqueue command is run repeatedly enqueing only producs modified since the last command execution.

You can also enqueue items only for specific importers:

```bash
bin/console webgriffe:akeneno:enqueue --importer="Product" --importer="MyImporter" --since="2020-01-30"
```

You can also enqueue items regardless their last update date:

```bash
bin/console webgriffe:akeneno:enqueue --all
```

### Consume command

To import the Akeneo entities that are in the queue you can use the `webgriffe:akeneo:consume` console command:
Expand Down
26 changes: 0 additions & 26 deletions features/enqueuing.feature

This file was deleted.

52 changes: 52 additions & 0 deletions features/enqueuing_generic_items.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
@enqueuing_generic_items
Feature: Enqueuing items
In order to import data from Akeneo
As a Store Owner
I want to add enqueue items to the Akeneo PIM queue

@cli
Scenario: Enqueueing items when no item is modified since the given date
When I enqueue items for all importers modified since date "2020-01-20 01:00:00"
Then there should be no item in the Akeneo queue

@cli
Scenario: Enqueueing items without a since date
When I enqueue items for all importers with no since date
Then I should be notified that a since date is required
And there should be no item in the Akeneo queue

@cli
Scenario: Enqueueing items with an invalid since date
When I enqueue items for all importers with invalid since date
Then I should be notified that the since date must be a valid date

@cli
Scenario: Enqueueing items with a since date specified from a not existent file
When I enqueue items with since date specified from a not existent file
Then I should be notified that the since date file does not exists

@cli
Scenario: Avoiding to enqueue two times the same item if it has not been imported yet
Given there is a product "product-1" updated at "2020-01-20 22:23:13" on Akeneo
And there is one item to import with identifier "product-1" for the "Product" importer in the Akeneo queue
When I enqueue items for all importers modified since date "2020-01-20 01:00:00"
Then there should be only one queue item with identifier "product-1" for the "Product" importer in the Akeneo queue

@cli
Scenario: Enqueuing all items regardless last modified date
Given there are 3 products on Akeneo
When I enqueue all items for all importers
Then there should be 3 items for the "Product" importer in the Akeneo queue
And there should be 3 items for the "ProductAssociations" importer in the Akeneo queue

@cli
Scenario: Enqueuing all items for one importer only
Given there are 3 products on Akeneo
When I enqueue all items for the "Product" importer
Then there should be 3 items for the "Product" importer in the Akeneo queue
And there should be items for the "Product" importer only in the Akeneo queue

@cli
Scenario: Enqueuing all items for a not existent importer
When I enqueue all items for a not existent importer
Then I should be notified that the importer does not exists
33 changes: 13 additions & 20 deletions features/enqueuing_products.feature
Original file line number Diff line number Diff line change
@@ -1,41 +1,34 @@
@enqueuing
@enqueuing_products
Feature: Enqueuing products
In order to import my products from Akeneo
As a Store Owner
I want to add them to the Akeneo PIM queue

@cli
Scenario: Enqueuing products modified since a given date
Given there is a product "product-1" updated at "2020-01-10 22:23:13" on Akeneo
And there is a product "product-2" updated at "2020-01-21 09:54:12" on Akeneo
And there is a product "product-3" updated at "2020-01-22 08:15:08" on Akeneo
When I run enqueue command with since date "2020-01-20 01:00:00"
Then the command should have run successfully
And the product "product-1" should not be in the Akeneo queue
And the product "product-2" should be in the Akeneo queue
And the product "product-3" should be in the Akeneo queue
When I enqueue items for all importers modified since date "2020-01-20 01:00:00"
Then the queue item with identifier "product-1" for the "Product" importer should not be in the Akeneo queue
And the queue item with identifier "product-2" for the "Product" importer should be in the Akeneo queue
And the queue item with identifier "product-3" for the "Product" importer should be in the Akeneo queue

@cli
Scenario: There are no products modified since datetime read in file
Given there is a file with name "last-date" and content "2020-01-20 01:00:00"
And current date time is "2020-01-25T12:00:00+01:00"
When I run enqueue command with since file "last-date"
Then the command should have run successfully
And there should be no product in the Akeneo queue
When I enqueue items for all importers modified since date specified from file "last-date"
Then there should be no item in the queue for the "Product" importer
And there is a file with name "last-date" that contains "2020-01-25T12:00:00+01:00"

@cli
Scenario: Enqueuing products modified since datetime read in file
Given there is a product "product-1" updated at "2020-01-10 22:23:13" on Akeneo
And there is a product "product-2" updated at "2020-01-21 09:54:12" on Akeneo
And there is a file with name "last-date" and content "2020-01-20 01:00:00"
And current date time is "2020-01-25T12:00:00+01:00"
When I run enqueue command with since file "last-date"
Then the command should have run successfully
And the product "product-1" should not be in the Akeneo queue
And the product "product-2" should be in the Akeneo queue
When I enqueue items for all importers modified since date specified from file "last-date"
Then the queue item with identifier "product-1" for the "Product" importer should not be in the Akeneo queue
And the queue item with identifier "product-2" for the "Product" importer should be in the Akeneo queue
And there is a file with name "last-date" that contains "2020-01-25T12:00:00+01:00"

# todo: this should be generalized and moved into enqueuing.feature
Scenario: Avoiding to enqueue two times the same product if it has not been imported yet
Given there is a product "product-1" updated at "2020-01-20 22:23:13" on Akeneo
And there is one product to import with identifier "product-1" in the Akeneo queue
When I run enqueue command with since date "2020-01-20 01:00:00"
Then there should be only one product queue item for "product-1" in the Akeneo queue
12 changes: 6 additions & 6 deletions features/enqueuing_products_associations.feature
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
@enqueuing
@enqueuing_products_associations
Feature: Enqueuing products associations
In order to import my products associations from Akeneo
As a Store Owner
I want to add them to the Akeneo PIM queue

@cli
Scenario: Enqueuing products associations for products modified since a given date
Given there is a product "product-1" updated at "2020-01-10 22:23:13" on Akeneo
And there is a product "product-2" updated at "2020-01-21 09:54:12" on Akeneo
And there is a product "product-3" updated at "2020-01-22 08:15:08" on Akeneo
When I run enqueue command with since date "2020-01-20 01:00:00"
Then the command should have run successfully
And the product associations for product "product-1" should not be in the Akeneo queue
And the product associations for product "product-2" should be in the Akeneo queue
And the product associations for product "product-3" should be in the Akeneo queue
When I enqueue items for all importers modified since date "2020-01-20 01:00:00"
Then the queue item with identifier "product-1" for the "ProductAssociations" importer should not be in the Akeneo queue
And the queue item with identifier "product-2" for the "ProductAssociations" importer should be in the Akeneo queue
And the queue item with identifier "product-3" for the "ProductAssociations" importer should be in the Akeneo queue
3 changes: 2 additions & 1 deletion features/importing_product_associations_from_queue.feature
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ Feature: Importing product associations from queue
As a Store Owner
I want to import product associations from Akeneo PIM queue

@cli
Scenario: Import product associations for already existent products
Given the store operates on a single channel
And the store has a product "10627329"
And the store has a product "upsell-product-1" with code "upsell-product-1"
And the store has a product "upsell-product-2" with code "upsell-product-2"
And there is one product associations to import with identifier "10627329" in the Akeneo queue
And the store has a product association type "Upsell" with a code "UPSELL"
When I run the Consume command
When I import all items in queue
Then the product "10627329" should be associated to product "upsell-product-1" for association with code "UPSELL"
And the product "10627329" should be associated to product "upsell-product-2" for association with code "UPSELL"
42 changes: 15 additions & 27 deletions features/importing_products_from_queue.feature
Original file line number Diff line number Diff line change
Expand Up @@ -4,47 +4,35 @@ Feature: Importing products from queue
As a Store Owner
I want to import products from Akeneo PIM queue

@cli
Scenario: Importing single product model and its variants from queue
Given the store operates on a single channel
And the store is also available in "it_IT"
And there is one product to import with identifier "braided-hat-m" in the Akeneo queue
And there is one product to import with identifier "Braided-hat-l" in the Akeneo queue
When I import products from queue
And there is one item to import with identifier "braided-hat-m" for the "Product" importer in the Akeneo queue
And there is one item to import with identifier "Braided-hat-l" for the "Product" importer in the Akeneo queue
When I import all items in queue
Then the product "model-braided-hat" should exists with the right data
And the product variant "braided-hat-m" of product "model-braided-hat" should exists with the right data
And the product variant "Braided-hat-l" of product "model-braided-hat" should exists with the right data

@cli
Scenario: Keeping the queue item as not imported while importing non existent product model from queue
Given the store operates on a single channel
And the store is also available in "it_IT"
And there is one product to import with identifier "NOT_EXISTS" in the Akeneo queue
When I import products from queue
And there is one item to import with identifier "NOT_EXISTS" for the "Product" importer in the Akeneo queue
When I import all items in queue
Then the product "NOT_EXISTS" should not exists
And the queue item for product with identifier "NOT_EXISTS" has not been marked as imported
And the queue item for product with identifier "NOT_EXISTS" has an error message
And the queue item with identifier "NOT_EXISTS" for the "Product" importer has not been marked as imported
And the queue item with identifier "NOT_EXISTS" for the "Product" importer has an error message

@cli
Scenario: Going on with subsequent product imports when any fail
Given the store operates on a single channel
And the store is also available in "it_IT"
And there is one product to import with identifier "NOT_EXISTS" in the Akeneo queue
And there is one product to import with identifier "braided-hat-m" in the Akeneo queue
When I import products from queue
And there is one item to import with identifier "NOT_EXISTS" for the "Product" importer in the Akeneo queue
And there is one item to import with identifier "braided-hat-m" for the "Product" importer in the Akeneo queue
When I import all items in queue
Then the product "NOT_EXISTS" should not exists
And the product variant "braided-hat-m" of product "model-braided-hat" should exists with the right data
And the queue item for product with identifier "braided-hat-m" has been marked as imported

# todo: this scenario seems to cover too many cases, it should be split in multiple scenarios
@todo
Scenario: Importing product with missing mandatory data should not mark them as imported and going on importing subsequent products
Given the store operates on a single channel
And the store is also available in "it_IT"
And there is one product to import with identifier "no-name-product" in the Akeneo queue
And there is one product to import with identifier "braided-hat-m" in the Akeneo queue
When I import products from queue
Then there should be only one product queue item for "no-name-product" in the Akeneo queue
And there should be only one product queue item for "braided-hat-m" in the Akeneo queue
And the queue item for product with identifier "no-name-product" has not been marked as imported
And the queue item for product with identifier "no-name-product" has an error message containing "NOT NULL constraint failed: sylius_product_translation.name"
And the queue item for product with identifier "braided-hat-m" has been marked as imported
And the product "no-name-product" should not exists
And the product variant "braided-hat-m" of product "model-braided-hat" should exists with the right data
And the queue item with identifier "braided-hat-m" for the "Product" importer has been marked as imported
And the queue item with identifier "NOT_EXISTS" for the "Product" importer has not been marked as imported
63 changes: 60 additions & 3 deletions src/Command/EnqueueCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Symfony\Component\Console\Output\OutputInterface;
use Webgriffe\SyliusAkeneoPlugin\DateTimeBuilderInterface;
use Webgriffe\SyliusAkeneoPlugin\Entity\QueueItemInterface;
use Webgriffe\SyliusAkeneoPlugin\ImporterInterface;
use Webgriffe\SyliusAkeneoPlugin\ImporterRegistryInterface;
use Webgriffe\SyliusAkeneoPlugin\Repository\QueueItemRepositoryInterface;
use Webmozart\Assert\Assert;
Expand All @@ -21,6 +22,10 @@ final class EnqueueCommand extends Command

public const SINCE_FILE_OPTION_NAME = 'since-file';

private const ALL_OPTION_NAME = 'all';

private const IMPORTER_OPTION_NAME = 'importer';

protected static $defaultName = 'webgriffe:akeneo:enqueue';

/** @var QueueItemRepositoryInterface */
Expand Down Expand Up @@ -65,6 +70,18 @@ protected function configure(): void
InputOption::VALUE_REQUIRED,
'Relative or absolute path to a file containing a datetime'
);
$this->addOption(
self::ALL_OPTION_NAME,
'a',
InputOption::VALUE_NONE,
'Enqueue all identifiers regardless their last modified date.'
);
$this->addOption(
self::IMPORTER_OPTION_NAME,
'i',
InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
'Enqueue items only for specified importers'
);
}

protected function execute(InputInterface $input, OutputInterface $output): int
Expand All @@ -84,18 +101,21 @@ protected function execute(InputInterface $input, OutputInterface $output): int
Assert::string($sinceFilePath);
/** @var string $sinceFilePath */
$sinceDate = $this->getSinceDateByFile($sinceFilePath);
} elseif ($input->getOption(self::ALL_OPTION_NAME) === true) {
$sinceDate = (new \DateTime())->setTimestamp(0);
} else {
throw new \InvalidArgumentException(
sprintf(
'One of "--%s" and "--%s" paramaters must be specified',
'One of "--%s", "--%s" or "--%s" option must be specified',
self::SINCE_OPTION_NAME,
self::SINCE_FILE_OPTION_NAME
self::SINCE_FILE_OPTION_NAME,
self::ALL_OPTION_NAME
)
);
}

$runDate = $this->dateTimeBuilder->build();
foreach ($this->importerRegistry->all() as $importer) {
foreach ($this->getImporters($input) as $importer) {
$identifiers = $importer->getIdentifiersModifiedSince($sinceDate);
if (count($identifiers) === 0) {
$output->writeln(
Expand Down Expand Up @@ -180,4 +200,41 @@ private function isEntityAlreadyQueuedToImport(string $akeneoEntity, string $ake

return false;
}

/**
* @return ImporterInterface[]
*/
private function getImporters(InputInterface $input): array
{
$allImporters = $this->importerRegistry->all();
if (count($allImporters) === 0) {
throw new \RuntimeException('There are no importers in registry.');
}
$importersCodes = array_map(
static function (ImporterInterface $importer) {
return $importer->getAkeneoEntity();
},
$allImporters
);

$importersToUse = $input->getOption(self::IMPORTER_OPTION_NAME);
Assert::isArray($importersToUse);

if (count($importersToUse) === 0) {
return $allImporters;
}

$allImporters = array_combine($importersCodes, $allImporters);
Assert::isArray($allImporters);

$importers = [];
foreach ($importersToUse as $importerToUse) {
if (!array_key_exists($importerToUse, $allImporters)) {
throw new \InvalidArgumentException(sprintf('Importer "%s" does not exists.', $importerToUse));
}
$importers[] = $allImporters[$importerToUse];
}

return $importers;
}
}
6 changes: 2 additions & 4 deletions tests/Behat/Context/Cli/ConsumeCommandContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,9 @@ public function __construct(
}

/**
* @todo replace "I import products from queue" with generic "I run the Consume command"
* @When /^I import products from queue$/
* @When /^I run the Consume command$/
* @When /^I import all items in queue$/
*/
public function iImportProductsFromQueue()
public function iImportAllItemsInQueue()
{
$application = new Application($this->kernel);
$application->add($this->consumeCommand);
Expand Down
Loading

0 comments on commit 08ac69b

Please sign in to comment.