Skip to content

Commit

Permalink
PISHPS-391: SWAG Commercial returns are synced with mollie (#919)
Browse files Browse the repository at this point in the history
* NTR: PISHPS-391: SWAG Commercial returns are synced with mollie

* NTR: fix installation

* NTR: fix pipeline

* NTR: revert generics

---------

Co-authored-by: Vitalij Mik <[email protected]>
  • Loading branch information
BlackScorp and Vitalij Mik authored Dec 19, 2024
1 parent 3b47072 commit 2100a9e
Show file tree
Hide file tree
Showing 22 changed files with 582 additions and 19 deletions.
3 changes: 3 additions & 0 deletions .phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
parameters:
level: 8
checkGenericClassInNonGenericObjectType: false
paths:
- ./src
excludePaths:
Expand All @@ -21,6 +22,8 @@ parameters:
message: 'might overwrite existing variables'
scanDirectories:
- polyfill/Shopware
ignoreErrors:
- '#.*Shopware\\Commercial\\ReturnManagement\\Entity\\OrderReturn.*#'

services:
- class: MolliePayments\PHPStan\Rules\NoManufacturerRule
Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Change Log
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]


### Features
- Return over Shopware Commercial plugins is now transfered to Mollie when the Return status is set to "Done" and can be cancelled with the "Cancelled" status. Please note that the refund cannot be cancelled after two hours.

Original file line number Diff line number Diff line change
@@ -0,0 +1,316 @@
<?php declare(strict_types=1);

namespace Shopware\Core\Framework\DataAbstractionLayer;

use Shopware\Core\Framework\Adapter\Database\ReplicaConnection;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityAggregationResultLoadedEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityIdSearchResultLoadedEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityLoadedEventFactory;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntitySearchedEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntitySearchResultLoadedEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenContainerEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Read\EntityReaderInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\AggregationResult\AggregationResultCollection;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\EntityAggregatorInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearcherInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearchResult;
use Shopware\Core\Framework\DataAbstractionLayer\Search\IdSearchResult;
use Shopware\Core\Framework\DataAbstractionLayer\Write\CloneBehavior;
use Shopware\Core\Framework\DataAbstractionLayer\Write\WriteContext;
use Shopware\Core\Framework\Log\Package;
use Shopware\Core\Framework\Struct\ArrayEntity;
use Shopware\Core\Framework\Uuid\Exception\InvalidUuidException;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Core\Profiling\Profiler;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

/**
* @final
*
*
*/
#[Package('core')]
class EntityRepository implements EntityRepositoryInterface
{
private EntityDefinition $definition;
private EntityReaderInterface $reader;
private VersionManager $versionManager;
private EntitySearcherInterface $searcher;
private EntityAggregatorInterface $aggregator;
private EventDispatcherInterface $eventDispatcher;
private EntityLoadedEventFactory $eventFactory;

/**
* @internal
*/
public function __construct(
EntityDefinition $definition,
EntityReaderInterface $reader,
VersionManager $versionManager,
EntitySearcherInterface $searcher,
EntityAggregatorInterface $aggregator,
EventDispatcherInterface $eventDispatcher,
EntityLoadedEventFactory $eventFactory
) {
$this->definition = $definition;
$this->reader = $reader;
$this->versionManager = $versionManager;
$this->searcher = $searcher;
$this->aggregator = $aggregator;
$this->eventDispatcher = $eventDispatcher;
$this->eventFactory = $eventFactory;
}

public function getDefinition(): EntityDefinition
{
return $this->definition;
}

/**
* @return EntitySearchResult<TEntityCollection>
*/
public function search(Criteria $criteria, Context $context): EntitySearchResult
{
if (!$criteria->getTitle()) {
return $this->_search($criteria, $context);
}

return Profiler::trace($criteria->getTitle(), fn () => $this->_search($criteria, $context), 'repository');
}

public function aggregate(Criteria $criteria, Context $context): AggregationResultCollection
{
if (!$criteria->getTitle()) {
return $this->_aggregate($criteria, $context);
}

return Profiler::trace($criteria->getTitle(), fn () => $this->_aggregate($criteria, $context), 'repository');
}

public function searchIds(Criteria $criteria, Context $context): IdSearchResult
{
if (!$criteria->getTitle()) {
return $this->_searchIds($criteria, $context);
}

return Profiler::trace($criteria->getTitle(), fn () => $this->_searchIds($criteria, $context), 'repository');
}

/**
* @param array<array<string, mixed|null>> $data
*/
public function update(array $data, Context $context): EntityWrittenContainerEvent
{
ReplicaConnection::ensurePrimary();

$affected = $this->versionManager->update($this->definition, $data, WriteContext::createFromContext($context));
$event = EntityWrittenContainerEvent::createWithWrittenEvents($affected, $context, []);
$this->eventDispatcher->dispatch($event);

return $event;
}

/**
* @param array<array<string, mixed|null>> $data
*/
public function upsert(array $data, Context $context): EntityWrittenContainerEvent
{
ReplicaConnection::ensurePrimary();

$affected = $this->versionManager->upsert($this->definition, $data, WriteContext::createFromContext($context));
$event = EntityWrittenContainerEvent::createWithWrittenEvents($affected, $context, []);
$this->eventDispatcher->dispatch($event);

return $event;
}

/**
* @param array<array<string, mixed|null>> $data
*/
public function create(array $data, Context $context): EntityWrittenContainerEvent
{
ReplicaConnection::ensurePrimary();

$affected = $this->versionManager->insert($this->definition, $data, WriteContext::createFromContext($context));
$event = EntityWrittenContainerEvent::createWithWrittenEvents($affected, $context, []);
$this->eventDispatcher->dispatch($event);

return $event;
}

/**
* @param array<array<string, mixed|null>> $ids
*/
public function delete(array $ids, Context $context): EntityWrittenContainerEvent
{
ReplicaConnection::ensurePrimary();

$affected = $this->versionManager->delete($this->definition, $ids, WriteContext::createFromContext($context));
$event = EntityWrittenContainerEvent::createWithDeletedEvents($affected->getDeleted(), $context, $affected->getNotFound());

if ($affected->getWritten()) {
$updates = EntityWrittenContainerEvent::createWithWrittenEvents($affected->getWritten(), $context, []);

if ($updates->getEvents() !== null) {
$event->addEvent(...$updates->getEvents());
}
}

$this->eventDispatcher->dispatch($event);

return $event;
}

public function createVersion(string $id, Context $context, ?string $name = null, ?string $versionId = null): string
{
ReplicaConnection::ensurePrimary();

if (!$this->definition->isVersionAware()) {
throw new \RuntimeException(\sprintf('Entity %s is not version aware', $this->definition->getEntityName()));
}

return $this->versionManager->createVersion($this->definition, $id, WriteContext::createFromContext($context), $name, $versionId);
}

public function merge(string $versionId, Context $context): void
{
ReplicaConnection::ensurePrimary();

if (!$this->definition->isVersionAware()) {
throw new \RuntimeException(\sprintf('Entity %s is not version aware', $this->definition->getEntityName()));
}
$this->versionManager->merge($versionId, WriteContext::createFromContext($context));
}

public function clone(string $id, Context $context, ?string $newId = null, ?CloneBehavior $behavior = null): EntityWrittenContainerEvent
{
ReplicaConnection::ensurePrimary();

$newId ??= Uuid::randomHex();
if (!Uuid::isValid($newId)) {
throw new InvalidUuidException($newId);
}

$affected = $this->versionManager->clone(
$this->definition,
$id,
$newId,
$context->getVersionId(),
WriteContext::createFromContext($context),
$behavior ?? new CloneBehavior()
);

$event = EntityWrittenContainerEvent::createWithWrittenEvents($affected, $context, [], true);
$this->eventDispatcher->dispatch($event);

return $event;
}

/**
* @return TEntityCollection
*/
private function read(Criteria $criteria, Context $context): EntityCollection
{
$criteria = clone $criteria;

/** @var TEntityCollection $entities */
$entities = $this->reader->read($this->definition, $criteria, $context);

if ($criteria->getFields() === []) {
$event = $this->eventFactory->create($entities->getElements(), $context);
} else {
$event = $this->eventFactory->createPartial($entities->getElements(), $context);
}

$this->eventDispatcher->dispatch($event);

return $entities;
}

/**
* @return EntitySearchResult<TEntityCollection>
*/
private function _search(Criteria $criteria, Context $context): EntitySearchResult
{
$criteria = clone $criteria;
$aggregations = null;
if ($criteria->getAggregations()) {
$aggregations = $this->aggregate($criteria, $context);
}

if (!RepositorySearchDetector::isSearchRequired($this->definition, $criteria)) {
$this->eventDispatcher->dispatch(
new EntitySearchedEvent($criteria, $this->definition, $context)
);
$entities = $this->read($criteria, $context);

return new EntitySearchResult($this->definition->getEntityName(), $entities->count(), $entities, $aggregations, $criteria, $context);
}

$ids = $this->searchIds($criteria, $context);

if (empty($ids->getIds())) {
/** @var TEntityCollection $collection */
$collection = $this->definition->getCollectionClass();

return new EntitySearchResult($this->definition->getEntityName(), $ids->getTotal(), new $collection(), $aggregations, $criteria, $context);
}

$readCriteria = $criteria->cloneForRead($ids->getIds());

$entities = $this->read($readCriteria, $context);

$search = $ids->getData();

foreach ($entities as $element) {
if (!\array_key_exists($element->getUniqueIdentifier(), $search)) {
continue;
}

$data = $search[$element->getUniqueIdentifier()];
unset($data['id']);

if (empty($data)) {
continue;
}

$element->addExtension('search', new ArrayEntity($data));
}

$result = new EntitySearchResult($this->definition->getEntityName(), $ids->getTotal(), $entities, $aggregations, $criteria, $context);
$result->addState(...$ids->getStates());

$event = new EntitySearchResultLoadedEvent($this->definition, $result);
$this->eventDispatcher->dispatch($event, $event->getName());

return $result;
}

private function _aggregate(Criteria $criteria, Context $context): AggregationResultCollection
{
$criteria = clone $criteria;

$result = $this->aggregator->aggregate($this->definition, $criteria, $context);

$event = new EntityAggregationResultLoadedEvent($this->definition, $result, $context);
$this->eventDispatcher->dispatch($event, $event->getName());

return $result;
}

private function _searchIds(Criteria $criteria, Context $context): IdSearchResult
{
$criteria = clone $criteria;

$this->eventDispatcher->dispatch(new EntitySearchedEvent($criteria, $this->definition, $context));

$result = $this->searcher->search($this->definition, $criteria, $context);

$event = new EntityIdSearchResultLoadedEvent($this->definition, $result);
$this->eventDispatcher->dispatch($event, $event->getName());

return $result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ class RefundAdminSearchIndexer extends AbstractAdminIndexer
{
private Connection $connection;
private IteratorFactory $factory;
/**
* @var EntityRepository
*/
private EntityRepository $repository;
private int $indexingBatchSize;

Expand All @@ -30,7 +33,10 @@ class RefundAdminSearchIndexer extends AbstractAdminIndexer
private const TYPE_BINARY = ParameterType::BINARY + Connection::ARRAY_PARAM_OFFSET;

/**
* @internal
* @param Connection $connection
* @param IteratorFactory $factory
* @param EntityRepository $repository
* @param int $indexingBatchSize
*/
public function __construct(
Connection $connection,
Expand Down
Loading

0 comments on commit 2100a9e

Please sign in to comment.