From 7a536d5fe90a955c33b1c95aa54929b551793558 Mon Sep 17 00:00:00 2001 From: Piotr Kreft <49146985+piotrkreft@users.noreply.github.com> Date: Tue, 28 Dec 2021 12:42:00 +0100 Subject: [PATCH] bugfix(product) fix audit information generation for product (#1820) --- CHANGELOG.md | 3 + composer.json | 2 +- composer.lock | 16 ++- .../migrations/Version20211219110000.php | 115 ++++++++++++++++++ .../Handler/AbstractAuditEventHandler.php | 38 ++++++ .../AuditProductCreatedEventHandler.php | 38 ++++++ .../AuditProductDeletedEventHandler.php | 34 ++++++ .../AuditProductUpdatedEventHandler.php | 37 ++++++ .../src/Domain/Factory/ProductFactory.php | 29 +---- ...edAtSystemAttributeDataSetQueryBuilder.php | 12 +- ...edBySystemAttributeDataSetQueryBuilder.php | 26 ++-- ...edAtSystemAttributeDataSetQueryBuilder.php | 12 +- ...edBySystemAttributeDataSetQueryBuilder.php | 22 ++-- .../Handler/AbstractUpdateProductHandler.php | 64 ---------- .../Attribute/AbstractValueCommandHandler.php | 18 --- .../ChangeProductAttributeCommandHandler.php | 10 -- .../ChangeProductAttributesCommandHandler.php | 10 -- .../RemoveProductAttributeCommandHandler.php | 12 +- .../RemoveProductAttributesCommandHandler.php | 10 -- .../UpdateGroupingProductCommandHandler.php | 12 +- .../UpdateSimpleProductCommandHandler.php | 12 +- .../UpdateVariableProductCommandHandler.php | 12 +- .../UpdateProductCategoriesCommandHandler.php | 11 +- .../Projector/AbstractProductProjector.php | 17 --- .../DbalBindAddedToProductEventProjector.php | 2 - ...alBindRemovedFromProductEventProjector.php | 2 - .../DbalChildAddedToProductEventProjector.php | 2 - ...lChildRemovedFromProductEventProjector.php | 2 - ...alProductAddedToCategoryEventProjector.php | 2 - .../DbalProductCreatedEventProjector.php | 3 - ...oductRemovedFromCategoryEventProjector.php | 2 - ...alProductTemplateChangedEventProjector.php | 2 - .../DbalProductValueAddedEventProjector.php | 1 - .../DbalProductValueChangedEventProjector.php | 1 - .../DbalProductValueRemovedEventProjector.php | 1 - .../Persistence/Query/DbalProductQuery.php | 10 +- .../product/src/Resources/config/services.yml | 4 + 37 files changed, 345 insertions(+), 261 deletions(-) create mode 100644 module/product/migrations/Version20211219110000.php create mode 100644 module/product/src/Application/Handler/AbstractAuditEventHandler.php create mode 100644 module/product/src/Application/Handler/AuditProductCreatedEventHandler.php create mode 100644 module/product/src/Application/Handler/AuditProductDeletedEventHandler.php create mode 100644 module/product/src/Application/Handler/AuditProductUpdatedEventHandler.php delete mode 100644 module/product/src/Infrastructure/Handler/AbstractUpdateProductHandler.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 130b7f23c..7ac8dab5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ ## CHANGELOG FOR 1.1.x +#### 1.1.7 +- bugfix [#1816](https://github.com/ergonode/backend/issues/1816) Fixed product audits (rprzedzik) + #### 1.1.6 - bugfix [#1776](https://github.com/ergonode/backend/issues/1776) Fixed not recalculating segment for product on completeness update (piotrkreft) diff --git a/composer.json b/composer.json index 99d801bfb..c7cf9ad9a 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "doctrine/doctrine-bundle": "^2.3", "doctrine/migrations": "2.2.x", "egulias/email-validator": "^2.1", - "ergonode/exporter-shopware-6": "dev-main", + "ergonode/exporter-shopware-6": "~1.0", "ergonode/importer-magento-1": "^1.0", "gesdinet/jwt-refresh-token-bundle": "^0.11.1|^0.12", "guzzlehttp/guzzle": "^6.3", diff --git a/composer.lock b/composer.lock index 02a554ec7..c7840b160 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b685720ae428655eacfc555452139005", + "content-hash": "8e2befd3a2e7347353ba17b8e7d170a3", "packages": [ { "name": "beberlei/assert", @@ -1193,16 +1193,16 @@ }, { "name": "ergonode/exporter-shopware-6", - "version": "dev-main", + "version": "1.0.2", "source": { "type": "git", "url": "https://github.com/ergonode/exporter-shopware-6-backend.git", - "reference": "7345e435cc11d9c08c16ed5c59a94361c3a9fcbd" + "reference": "b3b6a79b44861e62d8c515212f038997e9df1591" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergonode/exporter-shopware-6-backend/zipball/7345e435cc11d9c08c16ed5c59a94361c3a9fcbd", - "reference": "7345e435cc11d9c08c16ed5c59a94361c3a9fcbd", + "url": "https://api.github.com/repos/ergonode/exporter-shopware-6-backend/zipball/b3b6a79b44861e62d8c515212f038997e9df1591", + "reference": "b3b6a79b44861e62d8c515212f038997e9df1591", "shasum": "" }, "require": { @@ -1230,7 +1230,6 @@ "symfony/monolog-bundle": "^3.5", "symfony/phpunit-bridge": "^4.4" }, - "default-branch": true, "type": "ergonode-module", "autoload": { "psr-4": { @@ -1245,9 +1244,9 @@ "homepage": "https://ergonode.com", "support": { "issues": "https://github.com/ergonode/exporter-shopware-6-backend/issues", - "source": "https://github.com/ergonode/exporter-shopware-6-backend/tree/main" + "source": "https://github.com/ergonode/exporter-shopware-6-backend/tree/1.0.2" }, - "time": "2021-04-30T09:14:27+00:00" + "time": "2021-11-15T14:01:41+00:00" }, { "name": "ergonode/importer-magento-1", @@ -13141,7 +13140,6 @@ "aliases": [], "minimum-stability": "stable", "stability-flags": { - "ergonode/exporter-shopware-6": 20, "roave/security-advisories": 20 }, "prefer-stable": true, diff --git a/module/product/migrations/Version20211219110000.php b/module/product/migrations/Version20211219110000.php new file mode 100644 index 000000000..e6785df8c --- /dev/null +++ b/module/product/migrations/Version20211219110000.php @@ -0,0 +1,115 @@ +addSql(' + CREATE TABLE IF NOT EXISTS audit ( + id uuid NOT NULL, + created_at TIMESTAMP WITH TIME ZONE NOT NULL, + created_by UUID DEFAULT NULL, + edited_at TIMESTAMP WITH TIME ZONE NOT NULL, + edited_by UUID DEFAULT NULL, + PRIMARY KEY(id) + ) + '); + + $this->updateAudit(); + $eventId = $this->getEventId(ProductValueAddedEvent::class); + $this->removeEvents($eventId, 'esa_created_at'); + $this->removeEvents($eventId, 'esa_created_by'); + $this->removeEvents($eventId, 'esa_edited_at'); + $this->removeEvents($eventId, 'esa_edited_by'); + $eventId = $this->getEventId(ProductValueChangedEvent::class); + $this->removeEvents($eventId, 'esa_edited_at'); + $this->removeEvents($eventId, 'esa_edited_by'); + + $this->removeValues('esa_created_at'); + $this->removeValues('esa_created_by'); + $this->removeValues('esa_edited_at'); + $this->removeValues('esa_edited_by'); + + $this->addSql('ALTER TABLE product DROP column created_at'); + $this->addSql('ALTER TABLE product DROP column updated_at'); + + $this->addSql('DELETE FROM event_store_snapshot WHERE aggregate_id in (SELECT id FROM product)'); + } + + private function getEventId(string $event): string + { + return $this->connection->executeQuery( + 'SELECT id FROM event_store_event WHERE event_class = :class', + [ + ':class' => $event, + ] + )->fetchOne(); + } + + private function removeEvents(string $eventId, string $code): void + { + $this->connection->executeQuery( + 'DELETE FROM event_store WHERE event_id = ? and payload::TEXT ilike \'%'.$code.'%\'', + [$eventId] + ); + } + + private function removeValues(string $code): void + { + $attributeId = $this->connection->executeQuery( + 'SELECT id FROM attribute WHERE code = :code', + [ + ':code' => $code, + ] + )->fetchOne(); + + if ($attributeId) { + $this->addSql( + 'DELETE FROM value_translation WHERE value_id IN + (SELECT value_id FROM product_value WHERE attribute_id = ?)', + [$attributeId] + ); + + $this->addSql( + 'DELETE FROM product_value WHERE attribute_id = ?', + [$attributeId] + ); + } + } + + private function updateAudit(): void + { + $this->addSql('INSERT INTO audit (id, created_at, edited_at) + SELECT id, created_at, updated_at FROM product'); + + $this->addSql('UPDATE audit + SET created_by = t.recorded_by + FROM (SELECT aggregate_id, recorded_by FROM event_store + WHERE id IN (SELECT min(id) FROM event_store group by aggregate_id)) AS t + WHERE audit.id = t.aggregate_id'); + + $this->addSql('UPDATE audit + SET edited_by = t.recorded_by + FROM (SELECT aggregate_id, recorded_by FROM event_store + WHERE id IN (SELECT max(id) FROM event_store group by aggregate_id)) AS t + WHERE audit.id = t.aggregate_id'); + } +} diff --git a/module/product/src/Application/Handler/AbstractAuditEventHandler.php b/module/product/src/Application/Handler/AbstractAuditEventHandler.php new file mode 100644 index 000000000..1f63ecb5a --- /dev/null +++ b/module/product/src/Application/Handler/AbstractAuditEventHandler.php @@ -0,0 +1,38 @@ +connection = $connection; + $this->security = $security; + } + + protected function getUser(): ?UserId + { + $user = $this->security->getUser(); + + if ($user instanceof UserInterface) { + return $user->getId(); + } + + return null; + } +} diff --git a/module/product/src/Application/Handler/AuditProductCreatedEventHandler.php b/module/product/src/Application/Handler/AuditProductCreatedEventHandler.php new file mode 100644 index 000000000..7ab40e6a0 --- /dev/null +++ b/module/product/src/Application/Handler/AuditProductCreatedEventHandler.php @@ -0,0 +1,38 @@ +getUser(); + + $this->connection->insert( + self::TABLE, + [ + 'id' => $event->getProduct()->getId()->getValue(), + 'created_at' => $date, + 'edited_at' => $date, + 'created_by' => $user, + 'edited_by' => $user, + ], + [ + 'created_at' => Types::DATETIMETZ_MUTABLE, + 'edited_at' => Types::DATETIMETZ_MUTABLE, + ], + ); + } +} diff --git a/module/product/src/Application/Handler/AuditProductDeletedEventHandler.php b/module/product/src/Application/Handler/AuditProductDeletedEventHandler.php new file mode 100644 index 000000000..e40070e58 --- /dev/null +++ b/module/product/src/Application/Handler/AuditProductDeletedEventHandler.php @@ -0,0 +1,34 @@ +connection = $connection; + } + + public function __invoke(ProductDeletedEvent $event): void + { + $this->connection->delete( + self::TABLE, + [ + 'id' => $event->getProduct()->getId()->getValue(), + ] + ); + } +} diff --git a/module/product/src/Application/Handler/AuditProductUpdatedEventHandler.php b/module/product/src/Application/Handler/AuditProductUpdatedEventHandler.php new file mode 100644 index 000000000..65b852134 --- /dev/null +++ b/module/product/src/Application/Handler/AuditProductUpdatedEventHandler.php @@ -0,0 +1,37 @@ +getUser(); + + $this->connection->update( + self::TABLE, + [ + 'edited_at' => $createdAt, + 'edited_by' => $createdBy, + ], + [ + 'id' => $event->getProduct()->getId()->getValue(), + ], + [ + 'edited_at' => Types::DATETIMETZ_MUTABLE, + ], + ); + } +} diff --git a/module/product/src/Domain/Factory/ProductFactory.php b/module/product/src/Domain/Factory/ProductFactory.php index 7d9790535..2b57301fc 100644 --- a/module/product/src/Domain/Factory/ProductFactory.php +++ b/module/product/src/Domain/Factory/ProductFactory.php @@ -9,26 +9,19 @@ namespace Ergonode\Product\Domain\Factory; -use Ergonode\Core\Application\Security\Security; use Ergonode\Product\Domain\Entity\AbstractProduct; -use Ergonode\Product\Domain\Entity\Attribute\CreatedAtSystemAttribute; -use Ergonode\Product\Domain\Entity\Attribute\CreatedBySystemAttribute; use Ergonode\Product\Domain\ValueObject\Sku; use Ergonode\Product\Infrastructure\Provider\ProductStrategyProvider; use Ergonode\SharedKernel\Domain\Aggregate\ProductId; use Ergonode\SharedKernel\Domain\Aggregate\TemplateId; -use Ergonode\Value\Domain\ValueObject\StringValue; class ProductFactory implements ProductFactoryInterface { private ProductStrategyProvider $productProvider; - private Security $security; - - public function __construct(ProductStrategyProvider $productProvider, Security $security) + public function __construct(ProductStrategyProvider $productProvider) { $this->productProvider = $productProvider; - $this->security = $security; } public function create( @@ -39,26 +32,6 @@ public function create( array $categories = [], array $attributes = [] ): AbstractProduct { - $attributes = $this->addAudit($attributes); - return $this->productProvider->provide($type)->build($id, $sku, $templateId, $categories, $attributes); } - - /** - * @param array $attributes - * - * @return array - */ - private function addAudit(array $attributes): array - { - $user = $this->security->getUser(); - if ($user) { - $value = new StringValue(sprintf('%s %s', $user->getFirstName(), $user->getLastName())); - $attributes[CreatedBySystemAttribute::CODE] = $value; - } - - $attributes[CreatedAtSystemAttribute::CODE] = new StringValue((new \DateTime())->format(\DateTime::W3C)); - - return $attributes; - } } diff --git a/module/product/src/Infrastructure/Grid/Builder/Query/CreatedAtSystemAttributeDataSetQueryBuilder.php b/module/product/src/Infrastructure/Grid/Builder/Query/CreatedAtSystemAttributeDataSetQueryBuilder.php index 04b8ea192..1a2d33e7f 100644 --- a/module/product/src/Infrastructure/Grid/Builder/Query/CreatedAtSystemAttributeDataSetQueryBuilder.php +++ b/module/product/src/Infrastructure/Grid/Builder/Query/CreatedAtSystemAttributeDataSetQueryBuilder.php @@ -15,21 +15,15 @@ class CreatedAtSystemAttributeDataSetQueryBuilder extends AbstractAttributeDataSetBuilder { - /** - * {@inheritDoc} - */ public function supports(AbstractAttribute $attribute): bool { return $attribute instanceof CreatedAtSystemAttribute; } - /** - * {@inheritDoc} - */ public function addSelect(QueryBuilder $query, string $key, AbstractAttribute $attribute, Language $language): void { - $sql = sprintf('p.created_at AS "%s"', $key); - - $query->addSelect($sql); + $sql = sprintf('(SELECT id, created_at AS "%s" FROM audit)', $key); + $query->addSelect(sprintf('"%s"', $key)); + $query->join('p', $sql, sprintf('"%s_JT"', $key), sprintf('"%s_JT".id = p.id', $key)); } } diff --git a/module/product/src/Infrastructure/Grid/Builder/Query/CreatedBySystemAttributeDataSetQueryBuilder.php b/module/product/src/Infrastructure/Grid/Builder/Query/CreatedBySystemAttributeDataSetQueryBuilder.php index 15560c91f..de3fe9ad7 100644 --- a/module/product/src/Infrastructure/Grid/Builder/Query/CreatedBySystemAttributeDataSetQueryBuilder.php +++ b/module/product/src/Infrastructure/Grid/Builder/Query/CreatedBySystemAttributeDataSetQueryBuilder.php @@ -15,31 +15,23 @@ class CreatedBySystemAttributeDataSetQueryBuilder extends AbstractAttributeDataSetBuilder { - /** - * {@inheritDoc} - */ public function supports(AbstractAttribute $attribute): bool { return $attribute instanceof CreatedBySystemAttribute; } - /** - * {@inheritDoc} - */ public function addSelect(QueryBuilder $query, string $key, AbstractAttribute $attribute, Language $language): void { - $query->addSelect(sprintf( + $sql = sprintf( '( - SELECT value - FROM product_value pv - JOIN value_translation vt ON vt.value_id = pv.value_id - WHERE pv.attribute_id = \'%s\' - AND pv.product_id = p.id - AND vt."language" IS NULL - LIMIT 1 - ) AS "%s"', - $attribute->getId()->getValue(), + SELECT + a.id, + COALESCE(u.first_name || \' \' || u.last_name, \'System\') AS "%s" + FROM audit a + LEFT JOIN users u ON u.id = a.created_by)', $key - )); + ); + $query->addSelect(sprintf('"%s"', $key)); + $query->leftJoin('p', $sql, sprintf('"%s_JT"', $key), sprintf('"%s_JT".id = p.id', $key)); } } diff --git a/module/product/src/Infrastructure/Grid/Builder/Query/EditedAtSystemAttributeDataSetQueryBuilder.php b/module/product/src/Infrastructure/Grid/Builder/Query/EditedAtSystemAttributeDataSetQueryBuilder.php index f5b31a284..eb4dcd7dc 100644 --- a/module/product/src/Infrastructure/Grid/Builder/Query/EditedAtSystemAttributeDataSetQueryBuilder.php +++ b/module/product/src/Infrastructure/Grid/Builder/Query/EditedAtSystemAttributeDataSetQueryBuilder.php @@ -15,21 +15,15 @@ class EditedAtSystemAttributeDataSetQueryBuilder extends AbstractAttributeDataSetBuilder { - /** - * {@inheritDoc} - */ public function supports(AbstractAttribute $attribute): bool { return $attribute instanceof EditedAtSystemAttribute; } - /** - * {@inheritDoc} - */ public function addSelect(QueryBuilder $query, string $key, AbstractAttribute $attribute, Language $language): void { - $sql = sprintf('p.created_at AS "%s"', $key); - - $query->addSelect($sql); + $sql = sprintf('(SELECT id, edited_at AS "%s" FROM audit)', $key); + $query->addSelect(sprintf('"%s"', $key)); + $query->join('p', $sql, sprintf('"%s_JT"', $key), sprintf('"%s_JT".id = p.id', $key)); } } diff --git a/module/product/src/Infrastructure/Grid/Builder/Query/EditedBySystemAttributeDataSetQueryBuilder.php b/module/product/src/Infrastructure/Grid/Builder/Query/EditedBySystemAttributeDataSetQueryBuilder.php index 5ca1d1f26..d42793458 100644 --- a/module/product/src/Infrastructure/Grid/Builder/Query/EditedBySystemAttributeDataSetQueryBuilder.php +++ b/module/product/src/Infrastructure/Grid/Builder/Query/EditedBySystemAttributeDataSetQueryBuilder.php @@ -15,9 +15,6 @@ class EditedBySystemAttributeDataSetQueryBuilder extends AbstractAttributeDataSetBuilder { - /** - * {@inheritDoc} - */ public function supports(AbstractAttribute $attribute): bool { return $attribute instanceof EditedBySystemAttribute; @@ -25,17 +22,16 @@ public function supports(AbstractAttribute $attribute): bool public function addSelect(QueryBuilder $query, string $key, AbstractAttribute $attribute, Language $language): void { - $query->addSelect(sprintf( + $sql = sprintf( '( - SELECT value FROM product_value pv - JOIN value_translation vt ON vt.value_id = pv.value_id - WHERE pv.attribute_id = \'%s\' - AND pv.product_id = p.id - AND vt."language" IS NULL - LIMIT 1 - ) AS "%s"', - $attribute->getId()->getValue(), + SELECT + a.id, + COALESCE(u.first_name || \' \' || u.last_name, \'System\') AS "%s" + FROM audit a + LEFT JOIN users u ON u.id = a.edited_by)', $key - )); + ); + $query->addSelect(sprintf('"%s"', $key)); + $query->leftJoin('p', $sql, sprintf('"%s_JT"', $key), sprintf('"%s_JT".id = p.id', $key)); } } diff --git a/module/product/src/Infrastructure/Handler/AbstractUpdateProductHandler.php b/module/product/src/Infrastructure/Handler/AbstractUpdateProductHandler.php deleted file mode 100644 index 7658be48d..000000000 --- a/module/product/src/Infrastructure/Handler/AbstractUpdateProductHandler.php +++ /dev/null @@ -1,64 +0,0 @@ -productRepository = $productRepository; - $this->attributeRepository = $attributeRepository; - $this->security = $security; - } - - /** - * @throws \Exception - */ - public function updateAudit(AbstractProduct $product): AbstractProduct - { - $user = $this->security->getUser(); - if ($user) { - $editedByCode = new AttributeCode(EditedBySystemAttribute::CODE); - $editedByValue = new StringValue(sprintf('%s %s', $user->getFirstName(), $user->getLastName())); - $this->attributeUpdate($product, $editedByCode, $editedByValue); - } - - return $product; - } - - /** - * @throws \Exception - */ - protected function attributeUpdate(AbstractProduct $product, AttributeCode $code, ValueInterface $value): void - { - if (!$product->hasAttribute($code)) { - $product->addAttribute($code, $value); - } else { - $product->changeAttribute($code, $value); - } - } -} diff --git a/module/product/src/Infrastructure/Handler/Attribute/AbstractValueCommandHandler.php b/module/product/src/Infrastructure/Handler/Attribute/AbstractValueCommandHandler.php index 8517fdb3a..5018ebe48 100644 --- a/module/product/src/Infrastructure/Handler/Attribute/AbstractValueCommandHandler.php +++ b/module/product/src/Infrastructure/Handler/Attribute/AbstractValueCommandHandler.php @@ -9,10 +9,6 @@ namespace Ergonode\Product\Infrastructure\Handler\Attribute; use Ergonode\Attribute\Domain\ValueObject\AttributeCode; -use Ergonode\Core\Domain\User\UserInterface; -use Ergonode\Value\Domain\ValueObject\StringValue; -use Ergonode\Product\Domain\Entity\Attribute\EditedBySystemAttribute; -use Ergonode\Product\Domain\Entity\Attribute\EditedAtSystemAttribute; use Ergonode\Value\Domain\ValueObject\ValueInterface; use Ergonode\Product\Domain\Entity\AbstractProduct; @@ -29,18 +25,4 @@ protected function attributeUpdate(AbstractProduct $product, AttributeCode $code $product->changeAttribute($code, $value); } } - - /** - * @throws \Exception - */ - protected function updateAudit(UserInterface $user, AbstractProduct $product): void - { - $updatedAt = new \DateTime(); - $editedByCode = new AttributeCode(EditedBySystemAttribute::CODE); - $editedAtCode = new AttributeCode(EditedAtSystemAttribute::CODE); - $editedByValue = new StringValue(sprintf('%s %s', $user->getFirstName(), $user->getLastName())); - $editedAtValue = new StringValue($updatedAt->format('Y-m-d H:i:sO')); - $this->attributeUpdate($product, $editedByCode, $editedByValue); - $this->attributeUpdate($product, $editedAtCode, $editedAtValue); - } } diff --git a/module/product/src/Infrastructure/Handler/Attribute/ChangeProductAttributeCommandHandler.php b/module/product/src/Infrastructure/Handler/Attribute/ChangeProductAttributeCommandHandler.php index 302e20baa..3ff3c6ba3 100644 --- a/module/product/src/Infrastructure/Handler/Attribute/ChangeProductAttributeCommandHandler.php +++ b/module/product/src/Infrastructure/Handler/Attribute/ChangeProductAttributeCommandHandler.php @@ -10,7 +10,6 @@ namespace Ergonode\Product\Infrastructure\Handler\Attribute; use Ergonode\Attribute\Domain\Repository\AttributeRepositoryInterface; -use Ergonode\Core\Application\Security\Security; use Webmozart\Assert\Assert; use Ergonode\Product\Domain\Repository\ProductRepositoryInterface; use Ergonode\Product\Domain\Updater\ProductAttributeUpdater; @@ -22,19 +21,15 @@ class ChangeProductAttributeCommandHandler extends AbstractValueCommandHandler private AttributeRepositoryInterface $attributeRepository; - private Security $security; - private ProductAttributeUpdater $updater; public function __construct( ProductRepositoryInterface $repository, AttributeRepositoryInterface $attributeRepository, - Security $security, ProductAttributeUpdater $updater ) { $this->repository = $repository; $this->attributeRepository = $attributeRepository; - $this->security = $security; $this->updater = $updater; } @@ -53,11 +48,6 @@ public function __invoke(ChangeProductAttributeCommand $command): void $this->updater->update($product, $attribute, [$language->getCode() => $command->getValue()]); - $user = $this->security->getUser(); - if ($user) { - $this->updateAudit($user, $product); - } - $this->repository->save($product); } } diff --git a/module/product/src/Infrastructure/Handler/Attribute/ChangeProductAttributesCommandHandler.php b/module/product/src/Infrastructure/Handler/Attribute/ChangeProductAttributesCommandHandler.php index 1784e9d15..1809f9b08 100644 --- a/module/product/src/Infrastructure/Handler/Attribute/ChangeProductAttributesCommandHandler.php +++ b/module/product/src/Infrastructure/Handler/Attribute/ChangeProductAttributesCommandHandler.php @@ -10,7 +10,6 @@ namespace Ergonode\Product\Infrastructure\Handler\Attribute; use Ergonode\Attribute\Domain\Repository\AttributeRepositoryInterface; -use Ergonode\Core\Application\Security\Security; use Webmozart\Assert\Assert; use Ergonode\Product\Domain\Repository\ProductRepositoryInterface; use Ergonode\Product\Domain\Command\Attribute\ChangeProductAttributesCommand; @@ -23,19 +22,15 @@ class ChangeProductAttributesCommandHandler extends AbstractValueCommandHandler private AttributeRepositoryInterface $attributeRepository; - private Security $security; - private ProductAttributeUpdater $updater; public function __construct( ProductRepositoryInterface $repository, AttributeRepositoryInterface $attributeRepository, - Security $security, ProductAttributeUpdater $updater ) { $this->repository = $repository; $this->attributeRepository = $attributeRepository; - $this->security = $security; $this->updater = $updater; } @@ -53,11 +48,6 @@ public function __invoke(ChangeProductAttributesCommand $command): void $product = $this->updater->update($product, $attribute, $value); } - $user = $this->security->getUser(); - if ($user) { - $this->updateAudit($user, $product); - } - $this->repository->save($product); } } diff --git a/module/product/src/Infrastructure/Handler/Attribute/RemoveProductAttributeCommandHandler.php b/module/product/src/Infrastructure/Handler/Attribute/RemoveProductAttributeCommandHandler.php index b6200c8aa..dcc1290e5 100644 --- a/module/product/src/Infrastructure/Handler/Attribute/RemoveProductAttributeCommandHandler.php +++ b/module/product/src/Infrastructure/Handler/Attribute/RemoveProductAttributeCommandHandler.php @@ -10,7 +10,6 @@ namespace Ergonode\Product\Infrastructure\Handler\Attribute; use Ergonode\Attribute\Domain\Repository\AttributeRepositoryInterface; -use Ergonode\Core\Application\Security\Security; use Webmozart\Assert\Assert; use Ergonode\Product\Domain\Repository\ProductRepositoryInterface; use Ergonode\Product\Domain\Command\Attribute\RemoveProductAttributeCommand; @@ -24,18 +23,14 @@ class RemoveProductAttributeCommandHandler extends AbstractValueCommandHandler private ProductAttributeUpdater $updater; - private Security $security; - public function __construct( ProductRepositoryInterface $repository, AttributeRepositoryInterface $attributeRepository, - ProductAttributeUpdater $updater, - Security $security + ProductAttributeUpdater $updater ) { $this->repository = $repository; $this->attributeRepository = $attributeRepository; $this->updater = $updater; - $this->security = $security; } /** @@ -59,11 +54,6 @@ public function __invoke(RemoveProductAttributeCommand $command): void $this->updater->remove($product, $attribute, $value); - $user = $this->security->getUser(); - if ($user) { - $this->updateAudit($user, $product); - } - $this->repository->save($product); } } diff --git a/module/product/src/Infrastructure/Handler/Attribute/RemoveProductAttributesCommandHandler.php b/module/product/src/Infrastructure/Handler/Attribute/RemoveProductAttributesCommandHandler.php index bdb6ce6d2..8042ad3df 100644 --- a/module/product/src/Infrastructure/Handler/Attribute/RemoveProductAttributesCommandHandler.php +++ b/module/product/src/Infrastructure/Handler/Attribute/RemoveProductAttributesCommandHandler.php @@ -10,7 +10,6 @@ namespace Ergonode\Product\Infrastructure\Handler\Attribute; use Ergonode\Attribute\Domain\Repository\AttributeRepositoryInterface; -use Ergonode\Core\Application\Security\Security; use Webmozart\Assert\Assert; use Ergonode\Product\Domain\Repository\ProductRepositoryInterface; use Ergonode\SharedKernel\Domain\Aggregate\AttributeId; @@ -24,19 +23,15 @@ class RemoveProductAttributesCommandHandler extends AbstractValueCommandHandler private AttributeRepositoryInterface $attributeRepository; - private Security $security; - private ProductAttributeUpdater $updater; public function __construct( ProductRepositoryInterface $repository, AttributeRepositoryInterface $attributeRepository, - Security $security, ProductAttributeUpdater $updater ) { $this->repository = $repository; $this->attributeRepository = $attributeRepository; - $this->security = $security; $this->updater = $updater; } @@ -60,11 +55,6 @@ public function __invoke(RemoveProductAttributesCommand $command): void $product = $this->updater->remove($product, $attribute, $value); } - $user = $this->security->getUser(); - if ($user) { - $this->updateAudit($user, $product); - } - $this->repository->save($product); } } diff --git a/module/product/src/Infrastructure/Handler/Update/UpdateGroupingProductCommandHandler.php b/module/product/src/Infrastructure/Handler/Update/UpdateGroupingProductCommandHandler.php index 0fd93ce25..5bc1325af 100644 --- a/module/product/src/Infrastructure/Handler/Update/UpdateGroupingProductCommandHandler.php +++ b/module/product/src/Infrastructure/Handler/Update/UpdateGroupingProductCommandHandler.php @@ -9,12 +9,19 @@ namespace Ergonode\Product\Infrastructure\Handler\Update; +use Ergonode\Product\Domain\Repository\ProductRepositoryInterface; use Webmozart\Assert\Assert; use Ergonode\Product\Domain\Command\Update\UpdateGroupingProductCommand; -use Ergonode\Product\Infrastructure\Handler\AbstractUpdateProductHandler; -class UpdateGroupingProductCommandHandler extends AbstractUpdateProductHandler +class UpdateGroupingProductCommandHandler { + private ProductRepositoryInterface $productRepository; + + public function __construct(ProductRepositoryInterface $productRepository) + { + $this->productRepository = $productRepository; + } + /** * @throws \Exception */ @@ -25,7 +32,6 @@ public function __invoke(UpdateGroupingProductCommand $command): void $product->changeTemplate($command->getTemplateId()); $product->changeCategories($command->getCategories()); - $product = $this->updateAudit($product); $this->productRepository->save($product); } diff --git a/module/product/src/Infrastructure/Handler/Update/UpdateSimpleProductCommandHandler.php b/module/product/src/Infrastructure/Handler/Update/UpdateSimpleProductCommandHandler.php index b382e982d..0481cfdba 100644 --- a/module/product/src/Infrastructure/Handler/Update/UpdateSimpleProductCommandHandler.php +++ b/module/product/src/Infrastructure/Handler/Update/UpdateSimpleProductCommandHandler.php @@ -9,12 +9,19 @@ namespace Ergonode\Product\Infrastructure\Handler\Update; +use Ergonode\Product\Domain\Repository\ProductRepositoryInterface; use Webmozart\Assert\Assert; use Ergonode\Product\Domain\Command\Update\UpdateSimpleProductCommand; -use Ergonode\Product\Infrastructure\Handler\AbstractUpdateProductHandler; -class UpdateSimpleProductCommandHandler extends AbstractUpdateProductHandler +class UpdateSimpleProductCommandHandler { + private ProductRepositoryInterface $productRepository; + + public function __construct(ProductRepositoryInterface $productRepository) + { + $this->productRepository = $productRepository; + } + /** * @throws \Exception */ @@ -25,7 +32,6 @@ public function __invoke(UpdateSimpleProductCommand $command): void $product->changeTemplate($command->getTemplateId()); $product->changeCategories($command->getCategories()); - $product = $this->updateAudit($product); $this->productRepository->save($product); } diff --git a/module/product/src/Infrastructure/Handler/Update/UpdateVariableProductCommandHandler.php b/module/product/src/Infrastructure/Handler/Update/UpdateVariableProductCommandHandler.php index 400b71a44..f7a58cb50 100644 --- a/module/product/src/Infrastructure/Handler/Update/UpdateVariableProductCommandHandler.php +++ b/module/product/src/Infrastructure/Handler/Update/UpdateVariableProductCommandHandler.php @@ -9,13 +9,20 @@ namespace Ergonode\Product\Infrastructure\Handler\Update; +use Ergonode\Product\Domain\Repository\ProductRepositoryInterface; use Webmozart\Assert\Assert; use Ergonode\Product\Domain\Command\Update\UpdateVariableProductCommand; -use Ergonode\Product\Infrastructure\Handler\AbstractUpdateProductHandler; use Ergonode\Product\Domain\Entity\VariableProduct; -class UpdateVariableProductCommandHandler extends AbstractUpdateProductHandler +class UpdateVariableProductCommandHandler { + private ProductRepositoryInterface $productRepository; + + public function __construct(ProductRepositoryInterface $productRepository) + { + $this->productRepository = $productRepository; + } + /** * @throws \Exception */ @@ -27,7 +34,6 @@ public function __invoke(UpdateVariableProductCommand $command): void $product->changeTemplate($command->getTemplateId()); $product->changeCategories($command->getCategories()); - $product = $this->updateAudit($product); $this->productRepository->save($product); } diff --git a/module/product/src/Infrastructure/Handler/UpdateProductCategoriesCommandHandler.php b/module/product/src/Infrastructure/Handler/UpdateProductCategoriesCommandHandler.php index 8d478c26d..f863d6d73 100644 --- a/module/product/src/Infrastructure/Handler/UpdateProductCategoriesCommandHandler.php +++ b/module/product/src/Infrastructure/Handler/UpdateProductCategoriesCommandHandler.php @@ -9,11 +9,19 @@ namespace Ergonode\Product\Infrastructure\Handler; +use Ergonode\Product\Domain\Repository\ProductRepositoryInterface; use Webmozart\Assert\Assert; use Ergonode\Product\Domain\Command\UpdateProductCategoriesCommand; -class UpdateProductCategoriesCommandHandler extends AbstractUpdateProductHandler +class UpdateProductCategoriesCommandHandler { + private ProductRepositoryInterface $productRepository; + + public function __construct(ProductRepositoryInterface $productRepository) + { + $this->productRepository = $productRepository; + } + /** * @throws \Exception */ @@ -23,7 +31,6 @@ public function __invoke(UpdateProductCategoriesCommand $command): void Assert::notNull($product); $product->changeCategories($command->getCategories()); - $product = $this->updateAudit($product); $this->productRepository->save($product); } diff --git a/module/product/src/Infrastructure/Persistence/Projector/AbstractProductProjector.php b/module/product/src/Infrastructure/Persistence/Projector/AbstractProductProjector.php index 18a34c798..8d503134f 100644 --- a/module/product/src/Infrastructure/Persistence/Projector/AbstractProductProjector.php +++ b/module/product/src/Infrastructure/Persistence/Projector/AbstractProductProjector.php @@ -9,30 +9,13 @@ namespace Ergonode\Product\Infrastructure\Persistence\Projector; use Doctrine\DBAL\Connection; -use Ergonode\SharedKernel\Domain\AggregateId; abstract class AbstractProductProjector { - private const TABLE_PRODUCT = 'product'; - protected Connection $connection; public function __construct(Connection $connection) { $this->connection = $connection; } - - protected function updateAudit(AggregateId $id): void - { - $editedAt = (new \DateTime())->format(\DateTime::W3C); - $this->connection->update( - self::TABLE_PRODUCT, - [ - 'updated_at' => $editedAt, - ], - [ - 'id' => $id->getValue(), - ] - ); - } } diff --git a/module/product/src/Infrastructure/Persistence/Projector/Binding/DbalBindAddedToProductEventProjector.php b/module/product/src/Infrastructure/Persistence/Projector/Binding/DbalBindAddedToProductEventProjector.php index b3be96ebb..f5b07de71 100644 --- a/module/product/src/Infrastructure/Persistence/Projector/Binding/DbalBindAddedToProductEventProjector.php +++ b/module/product/src/Infrastructure/Persistence/Projector/Binding/DbalBindAddedToProductEventProjector.php @@ -29,7 +29,5 @@ public function __invoke(BindAddedToProductEvent $event): void 'attribute_id' => $event->getAttributeId()->getValue(), ] ); - - $this->updateAudit($event->getAggregateId()); } } diff --git a/module/product/src/Infrastructure/Persistence/Projector/Binding/DbalBindRemovedFromProductEventProjector.php b/module/product/src/Infrastructure/Persistence/Projector/Binding/DbalBindRemovedFromProductEventProjector.php index 90d3f5d1e..c542c5aaf 100644 --- a/module/product/src/Infrastructure/Persistence/Projector/Binding/DbalBindRemovedFromProductEventProjector.php +++ b/module/product/src/Infrastructure/Persistence/Projector/Binding/DbalBindRemovedFromProductEventProjector.php @@ -29,7 +29,5 @@ public function __invoke(BindRemovedFromProductEvent $event): void 'attribute_id' => $event->getAttributeId()->getValue(), ] ); - - $this->updateAudit($event->getAggregateId()); } } diff --git a/module/product/src/Infrastructure/Persistence/Projector/Child/DbalChildAddedToProductEventProjector.php b/module/product/src/Infrastructure/Persistence/Projector/Child/DbalChildAddedToProductEventProjector.php index 2020770a8..6a7ba0ae2 100644 --- a/module/product/src/Infrastructure/Persistence/Projector/Child/DbalChildAddedToProductEventProjector.php +++ b/module/product/src/Infrastructure/Persistence/Projector/Child/DbalChildAddedToProductEventProjector.php @@ -29,7 +29,5 @@ public function __invoke(ChildAddedToProductEvent $event): void 'child_id' => $event->getChildId()->getValue(), ] ); - - $this->updateAudit($event->getAggregateId()); } } diff --git a/module/product/src/Infrastructure/Persistence/Projector/Child/DbalChildRemovedFromProductEventProjector.php b/module/product/src/Infrastructure/Persistence/Projector/Child/DbalChildRemovedFromProductEventProjector.php index 82e02eb74..12ceb6cbf 100644 --- a/module/product/src/Infrastructure/Persistence/Projector/Child/DbalChildRemovedFromProductEventProjector.php +++ b/module/product/src/Infrastructure/Persistence/Projector/Child/DbalChildRemovedFromProductEventProjector.php @@ -29,7 +29,5 @@ public function __invoke(ChildRemovedFromProductEvent $event): void 'child_id' => $event->getChildId()->getValue(), ] ); - - $this->updateAudit($event->getAggregateId()); } } diff --git a/module/product/src/Infrastructure/Persistence/Projector/DbalProductAddedToCategoryEventProjector.php b/module/product/src/Infrastructure/Persistence/Projector/DbalProductAddedToCategoryEventProjector.php index 1765d6dbc..73c9f367c 100644 --- a/module/product/src/Infrastructure/Persistence/Projector/DbalProductAddedToCategoryEventProjector.php +++ b/module/product/src/Infrastructure/Persistence/Projector/DbalProductAddedToCategoryEventProjector.php @@ -28,7 +28,5 @@ public function __invoke(ProductAddedToCategoryEvent $event): void 'category_id' => $event->getCategoryId()->getValue(), ] ); - - $this->updateAudit($event->getAggregateId()); } } diff --git a/module/product/src/Infrastructure/Persistence/Projector/DbalProductCreatedEventProjector.php b/module/product/src/Infrastructure/Persistence/Projector/DbalProductCreatedEventProjector.php index a5068d345..93bddea74 100644 --- a/module/product/src/Infrastructure/Persistence/Projector/DbalProductCreatedEventProjector.php +++ b/module/product/src/Infrastructure/Persistence/Projector/DbalProductCreatedEventProjector.php @@ -29,15 +29,12 @@ public function __construct(Connection $connection) */ public function __invoke(ProductCreatedEvent $event): void { - $createdAt = (new \DateTime())->format(\DateTime::W3C); $this->connection->insert( self::TABLE_PRODUCT, [ 'id' => $event->getAggregateId()->getValue(), 'sku' => $event->getSku()->getValue(), 'template_id' => $event->getTemplateId()->getValue(), - 'created_at' => $createdAt, - 'updated_at' => $createdAt, 'type' => $event->getType(), ] ); diff --git a/module/product/src/Infrastructure/Persistence/Projector/DbalProductRemovedFromCategoryEventProjector.php b/module/product/src/Infrastructure/Persistence/Projector/DbalProductRemovedFromCategoryEventProjector.php index 235804478..ff1aa7d38 100644 --- a/module/product/src/Infrastructure/Persistence/Projector/DbalProductRemovedFromCategoryEventProjector.php +++ b/module/product/src/Infrastructure/Persistence/Projector/DbalProductRemovedFromCategoryEventProjector.php @@ -28,7 +28,5 @@ public function __invoke(ProductRemovedFromCategoryEvent $event): void 'category_id' => $event->getCategoryId()->getValue(), ] ); - - $this->updateAudit($event->getAggregateId()); } } diff --git a/module/product/src/Infrastructure/Persistence/Projector/DbalProductTemplateChangedEventProjector.php b/module/product/src/Infrastructure/Persistence/Projector/DbalProductTemplateChangedEventProjector.php index e0dd2380a..87d44d38c 100644 --- a/module/product/src/Infrastructure/Persistence/Projector/DbalProductTemplateChangedEventProjector.php +++ b/module/product/src/Infrastructure/Persistence/Projector/DbalProductTemplateChangedEventProjector.php @@ -30,7 +30,5 @@ public function __invoke(ProductTemplateChangedEvent $event): void 'id' => $event->getAggregateId(), ] ); - - $this->updateAudit($event->getAggregateId()); } } diff --git a/module/product/src/Infrastructure/Persistence/Projector/DbalProductValueAddedEventProjector.php b/module/product/src/Infrastructure/Persistence/Projector/DbalProductValueAddedEventProjector.php index 6adb2cd57..7f038be2e 100644 --- a/module/product/src/Infrastructure/Persistence/Projector/DbalProductValueAddedEventProjector.php +++ b/module/product/src/Infrastructure/Persistence/Projector/DbalProductValueAddedEventProjector.php @@ -28,6 +28,5 @@ public function __invoke(ProductValueAddedEvent $event): void if (StatusSystemAttribute::CODE !== $code) { $this->insertValue($productId, $attributeId, $event->getValue()); } - $this->updateAudit($event->getAggregateId()); } } diff --git a/module/product/src/Infrastructure/Persistence/Projector/DbalProductValueChangedEventProjector.php b/module/product/src/Infrastructure/Persistence/Projector/DbalProductValueChangedEventProjector.php index cb1eb52cd..8827d600b 100644 --- a/module/product/src/Infrastructure/Persistence/Projector/DbalProductValueChangedEventProjector.php +++ b/module/product/src/Infrastructure/Persistence/Projector/DbalProductValueChangedEventProjector.php @@ -25,6 +25,5 @@ public function __invoke(ProductValueChangedEvent $event): void $this->delete($productId, $attributeId); $this->insertValue($productId, $attributeId, $event->getTo()); - $this->updateAudit($event->getAggregateId()); } } diff --git a/module/product/src/Infrastructure/Persistence/Projector/DbalProductValueRemovedEventProjector.php b/module/product/src/Infrastructure/Persistence/Projector/DbalProductValueRemovedEventProjector.php index e3fc20b1d..ddd50e078 100644 --- a/module/product/src/Infrastructure/Persistence/Projector/DbalProductValueRemovedEventProjector.php +++ b/module/product/src/Infrastructure/Persistence/Projector/DbalProductValueRemovedEventProjector.php @@ -24,6 +24,5 @@ public function __invoke(ProductValueRemovedEvent $event): void $attributeId = AttributeId::fromKey($event->getAttributeCode()->getValue())->getValue(); $this->delete($productId, $attributeId); - $this->updateAudit($event->getAggregateId()); } } diff --git a/module/product/src/Infrastructure/Persistence/Query/DbalProductQuery.php b/module/product/src/Infrastructure/Persistence/Query/DbalProductQuery.php index 902a8093f..d1b7988d0 100644 --- a/module/product/src/Infrastructure/Persistence/Query/DbalProductQuery.php +++ b/module/product/src/Infrastructure/Persistence/Query/DbalProductQuery.php @@ -27,6 +27,7 @@ class DbalProductQuery implements ProductQueryInterface private const PRODUCT_TABLE = 'public.product'; private const VALUE_TRANSLATION_TABLE = 'public.value_translation'; private const VALUE_TABLE = 'public.product_value'; + private const AUDIT_TABLE = 'audit'; private const SEGMENT_PRODUCT_TABLE = 'public.segment_product'; private Connection $connection; @@ -93,12 +94,13 @@ public function getAllEditedIds(?\DateTime $dateTime = null): array { $qb = $this->connection->createQueryBuilder(); $qb - ->select('id') - ->from(self::PRODUCT_TABLE); + ->select('p.id') + ->from(self::PRODUCT_TABLE, 'p') + ->join('p', self::AUDIT_TABLE, 'a', 'a.id = p.id'); if ($dateTime) { $qb - ->where($qb->expr()->gte('updated_at', ':updatedAt')) - ->setParameter(':updatedAt', $dateTime, Types::DATETIMETZ_MUTABLE); + ->where($qb->expr()->gte('edited_at', ':editedAt')) + ->setParameter(':editedAt', $dateTime, Types::DATETIMETZ_MUTABLE); } $result = $qb diff --git a/module/product/src/Resources/config/services.yml b/module/product/src/Resources/config/services.yml index dba258964..8af826931 100644 --- a/module/product/src/Resources/config/services.yml +++ b/module/product/src/Resources/config/services.yml @@ -28,6 +28,10 @@ services: resource: '../../Infrastructure/Handler/*' tags: ['messenger.message_handler'] + Ergonode\Product\Application\Handler\: + resource: '../../Application/Handler/*' + tags: ['messenger.message_handler'] + Ergonode\Product\Infrastructure\Persistence\Projector\: resource: '../../Infrastructure/Persistence/Projector/*' tags: ['ergonode.event_sourcing.projector']