Skip to content
This repository was archived by the owner on Feb 13, 2023. It is now read-only.

Commit 7a536d5

Browse files
authored
bugfix(product) fix audit information generation for product (#1820)
1 parent 51770a2 commit 7a536d5

File tree

37 files changed

+345
-261
lines changed

37 files changed

+345
-261
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
## CHANGELOG FOR 1.1.x
2+
#### 1.1.7
3+
- bugfix [#1816](https://github.com/ergonode/backend/issues/1816) Fixed product audits (rprzedzik)
4+
25
#### 1.1.6
36
- bugfix [#1776](https://github.com/ergonode/backend/issues/1776) Fixed not recalculating segment for product on completeness update (piotrkreft)
47

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"doctrine/doctrine-bundle": "^2.3",
2121
"doctrine/migrations": "2.2.x",
2222
"egulias/email-validator": "^2.1",
23-
"ergonode/exporter-shopware-6": "dev-main",
23+
"ergonode/exporter-shopware-6": "~1.0",
2424
"ergonode/importer-magento-1": "^1.0",
2525
"gesdinet/jwt-refresh-token-bundle": "^0.11.1|^0.12",
2626
"guzzlehttp/guzzle": "^6.3",

composer.lock

Lines changed: 7 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
<?php
2+
/**
3+
* Copyright © Bold Brand Commerce Sp. z o.o. All rights reserved.
4+
* See LICENSE.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Ergonode\Migration;
10+
11+
use Doctrine\DBAL\Schema\Schema;
12+
use Ergonode\Product\Domain\Event\ProductValueChangedEvent;
13+
use Ergonode\Product\Domain\Event\ProductValueAddedEvent;
14+
15+
/**
16+
* Auto-generated Ergonode Migration Class:
17+
*/
18+
final class Version20211219110000 extends AbstractErgonodeMigration
19+
{
20+
/**
21+
* @throws \Exception
22+
*/
23+
public function up(Schema $schema): void
24+
{
25+
$this->addSql('
26+
CREATE TABLE IF NOT EXISTS audit (
27+
id uuid NOT NULL,
28+
created_at TIMESTAMP WITH TIME ZONE NOT NULL,
29+
created_by UUID DEFAULT NULL,
30+
edited_at TIMESTAMP WITH TIME ZONE NOT NULL,
31+
edited_by UUID DEFAULT NULL,
32+
PRIMARY KEY(id)
33+
)
34+
');
35+
36+
$this->updateAudit();
37+
$eventId = $this->getEventId(ProductValueAddedEvent::class);
38+
$this->removeEvents($eventId, 'esa_created_at');
39+
$this->removeEvents($eventId, 'esa_created_by');
40+
$this->removeEvents($eventId, 'esa_edited_at');
41+
$this->removeEvents($eventId, 'esa_edited_by');
42+
$eventId = $this->getEventId(ProductValueChangedEvent::class);
43+
$this->removeEvents($eventId, 'esa_edited_at');
44+
$this->removeEvents($eventId, 'esa_edited_by');
45+
46+
$this->removeValues('esa_created_at');
47+
$this->removeValues('esa_created_by');
48+
$this->removeValues('esa_edited_at');
49+
$this->removeValues('esa_edited_by');
50+
51+
$this->addSql('ALTER TABLE product DROP column created_at');
52+
$this->addSql('ALTER TABLE product DROP column updated_at');
53+
54+
$this->addSql('DELETE FROM event_store_snapshot WHERE aggregate_id in (SELECT id FROM product)');
55+
}
56+
57+
private function getEventId(string $event): string
58+
{
59+
return $this->connection->executeQuery(
60+
'SELECT id FROM event_store_event WHERE event_class = :class',
61+
[
62+
':class' => $event,
63+
]
64+
)->fetchOne();
65+
}
66+
67+
private function removeEvents(string $eventId, string $code): void
68+
{
69+
$this->connection->executeQuery(
70+
'DELETE FROM event_store WHERE event_id = ? and payload::TEXT ilike \'%'.$code.'%\'',
71+
[$eventId]
72+
);
73+
}
74+
75+
private function removeValues(string $code): void
76+
{
77+
$attributeId = $this->connection->executeQuery(
78+
'SELECT id FROM attribute WHERE code = :code',
79+
[
80+
':code' => $code,
81+
]
82+
)->fetchOne();
83+
84+
if ($attributeId) {
85+
$this->addSql(
86+
'DELETE FROM value_translation WHERE value_id IN
87+
(SELECT value_id FROM product_value WHERE attribute_id = ?)',
88+
[$attributeId]
89+
);
90+
91+
$this->addSql(
92+
'DELETE FROM product_value WHERE attribute_id = ?',
93+
[$attributeId]
94+
);
95+
}
96+
}
97+
98+
private function updateAudit(): void
99+
{
100+
$this->addSql('INSERT INTO audit (id, created_at, edited_at)
101+
SELECT id, created_at, updated_at FROM product');
102+
103+
$this->addSql('UPDATE audit
104+
SET created_by = t.recorded_by
105+
FROM (SELECT aggregate_id, recorded_by FROM event_store
106+
WHERE id IN (SELECT min(id) FROM event_store group by aggregate_id)) AS t
107+
WHERE audit.id = t.aggregate_id');
108+
109+
$this->addSql('UPDATE audit
110+
SET edited_by = t.recorded_by
111+
FROM (SELECT aggregate_id, recorded_by FROM event_store
112+
WHERE id IN (SELECT max(id) FROM event_store group by aggregate_id)) AS t
113+
WHERE audit.id = t.aggregate_id');
114+
}
115+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
/**
3+
* Copyright © Bold Brand Commerce Sp. z o.o. All rights reserved.
4+
* See LICENSE.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Ergonode\Product\Application\Handler;
10+
11+
use Ergonode\SharedKernel\Domain\Aggregate\UserId;
12+
use Ergonode\SharedKernel\Domain\User\UserInterface;
13+
use Doctrine\DBAL\Connection;
14+
use Symfony\Component\Security\Core\Security;
15+
16+
abstract class AbstractAuditEventHandler
17+
{
18+
protected Connection $connection;
19+
20+
protected Security $security;
21+
22+
public function __construct(Connection $connection, Security $security)
23+
{
24+
$this->connection = $connection;
25+
$this->security = $security;
26+
}
27+
28+
protected function getUser(): ?UserId
29+
{
30+
$user = $this->security->getUser();
31+
32+
if ($user instanceof UserInterface) {
33+
return $user->getId();
34+
}
35+
36+
return null;
37+
}
38+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
/**
3+
* Copyright © Bold Brand Commerce Sp. z o.o. All rights reserved.
4+
* See LICENSE.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Ergonode\Product\Application\Handler;
10+
11+
use Ergonode\Product\Application\Event\ProductCreatedEvent;
12+
use Doctrine\DBAL\Types\Types;
13+
14+
class AuditProductCreatedEventHandler extends AbstractAuditEventHandler
15+
{
16+
private const TABLE = 'audit';
17+
18+
public function __invoke(ProductCreatedEvent $event): void
19+
{
20+
$date = new \DateTime();
21+
$user = $this->getUser();
22+
23+
$this->connection->insert(
24+
self::TABLE,
25+
[
26+
'id' => $event->getProduct()->getId()->getValue(),
27+
'created_at' => $date,
28+
'edited_at' => $date,
29+
'created_by' => $user,
30+
'edited_by' => $user,
31+
],
32+
[
33+
'created_at' => Types::DATETIMETZ_MUTABLE,
34+
'edited_at' => Types::DATETIMETZ_MUTABLE,
35+
],
36+
);
37+
}
38+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
/**
3+
* Copyright © Bold Brand Commerce Sp. z o.o. All rights reserved.
4+
* See LICENSE.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Ergonode\Product\Application\Handler;
10+
11+
use Doctrine\DBAL\Connection;
12+
use Ergonode\Product\Application\Event\ProductDeletedEvent;
13+
14+
class AuditProductDeletedEventHandler
15+
{
16+
private const TABLE = 'audit';
17+
18+
private Connection $connection;
19+
20+
public function __construct(Connection $connection)
21+
{
22+
$this->connection = $connection;
23+
}
24+
25+
public function __invoke(ProductDeletedEvent $event): void
26+
{
27+
$this->connection->delete(
28+
self::TABLE,
29+
[
30+
'id' => $event->getProduct()->getId()->getValue(),
31+
]
32+
);
33+
}
34+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
/**
3+
* Copyright © Bold Brand Commerce Sp. z o.o. All rights reserved.
4+
* See LICENSE.txt for license details.
5+
*/
6+
7+
declare(strict_types=1);
8+
9+
namespace Ergonode\Product\Application\Handler;
10+
11+
use Doctrine\DBAL\Types\Types;
12+
use Ergonode\Product\Application\Event\ProductUpdatedEvent;
13+
14+
class AuditProductUpdatedEventHandler extends AbstractAuditEventHandler
15+
{
16+
private const TABLE = 'audit';
17+
18+
public function __invoke(ProductUpdatedEvent $event): void
19+
{
20+
$createdAt = new \DateTime();
21+
$createdBy = $this->getUser();
22+
23+
$this->connection->update(
24+
self::TABLE,
25+
[
26+
'edited_at' => $createdAt,
27+
'edited_by' => $createdBy,
28+
],
29+
[
30+
'id' => $event->getProduct()->getId()->getValue(),
31+
],
32+
[
33+
'edited_at' => Types::DATETIMETZ_MUTABLE,
34+
],
35+
);
36+
}
37+
}

module/product/src/Domain/Factory/ProductFactory.php

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,19 @@
99

1010
namespace Ergonode\Product\Domain\Factory;
1111

12-
use Ergonode\Core\Application\Security\Security;
1312
use Ergonode\Product\Domain\Entity\AbstractProduct;
14-
use Ergonode\Product\Domain\Entity\Attribute\CreatedAtSystemAttribute;
15-
use Ergonode\Product\Domain\Entity\Attribute\CreatedBySystemAttribute;
1613
use Ergonode\Product\Domain\ValueObject\Sku;
1714
use Ergonode\Product\Infrastructure\Provider\ProductStrategyProvider;
1815
use Ergonode\SharedKernel\Domain\Aggregate\ProductId;
1916
use Ergonode\SharedKernel\Domain\Aggregate\TemplateId;
20-
use Ergonode\Value\Domain\ValueObject\StringValue;
2117

2218
class ProductFactory implements ProductFactoryInterface
2319
{
2420
private ProductStrategyProvider $productProvider;
2521

26-
private Security $security;
27-
28-
public function __construct(ProductStrategyProvider $productProvider, Security $security)
22+
public function __construct(ProductStrategyProvider $productProvider)
2923
{
3024
$this->productProvider = $productProvider;
31-
$this->security = $security;
3225
}
3326

3427
public function create(
@@ -39,26 +32,6 @@ public function create(
3932
array $categories = [],
4033
array $attributes = []
4134
): AbstractProduct {
42-
$attributes = $this->addAudit($attributes);
43-
4435
return $this->productProvider->provide($type)->build($id, $sku, $templateId, $categories, $attributes);
4536
}
46-
47-
/**
48-
* @param array $attributes
49-
*
50-
* @return array
51-
*/
52-
private function addAudit(array $attributes): array
53-
{
54-
$user = $this->security->getUser();
55-
if ($user) {
56-
$value = new StringValue(sprintf('%s %s', $user->getFirstName(), $user->getLastName()));
57-
$attributes[CreatedBySystemAttribute::CODE] = $value;
58-
}
59-
60-
$attributes[CreatedAtSystemAttribute::CODE] = new StringValue((new \DateTime())->format(\DateTime::W3C));
61-
62-
return $attributes;
63-
}
6437
}

0 commit comments

Comments
 (0)