diff --git a/src/Components/RefundManager/Builder/RefundDataBuilder.php b/src/Components/RefundManager/Builder/RefundDataBuilder.php
index fad077cef..2128e8a43 100644
--- a/src/Components/RefundManager/Builder/RefundDataBuilder.php
+++ b/src/Components/RefundManager/Builder/RefundDataBuilder.php
@@ -19,6 +19,7 @@
use Kiener\MolliePayments\Struct\OrderLineItemEntity\OrderLineItemEntityAttributes;
use Mollie\Api\Resources\OrderLine;
use Mollie\Api\Resources\Refund;
+use Shopware\Core\Checkout\Cart\LineItem\LineItem;
use Shopware\Core\Checkout\Cart\Price\Struct\CalculatedPrice;
use Shopware\Core\Checkout\Order\Aggregate\OrderDelivery\OrderDeliveryEntity;
use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity;
@@ -99,9 +100,14 @@ public function buildRefundData(OrderEntity $order, Context $context): RefundDat
$refundItems = [];
$refundPromotionItems = [];
$refundDeliveryItems = [];
+ $orderLineItems = $order->getLineItems();
- if ($order->getLineItems() !== null) {
- foreach ($order->getLineItems() as $item) {
+ if ($orderLineItems !== null) {
+ $orderLineItems = $orderLineItems->filter(function (OrderLineItemEntity $orderLineItemEntity) {
+ return $orderLineItemEntity->getType() !== LineItem::CREDIT_LINE_ITEM_TYPE;
+ });
+
+ foreach ($orderLineItems as $item) {
$lineItemAttribute = new OrderLineItemEntityAttributes($item);
$mollieOrderLineId = $lineItemAttribute->getMollieOrderLineID();
diff --git a/src/Components/RefundManager/RefundManager.php b/src/Components/RefundManager/RefundManager.php
index 1e6106bff..0ce4b3cf0 100644
--- a/src/Components/RefundManager/RefundManager.php
+++ b/src/Components/RefundManager/RefundManager.php
@@ -245,7 +245,7 @@ public function refund(OrderEntity $order, RefundRequest $request, Context $cont
);
}
- if (!$refund instanceof Refund) {
+ if (! $refund instanceof Refund) {
# a problem happened, lets finish with an exception
throw new CouldNotCreateMollieRefundException('', (string)$order->getOrderNumber());
}
@@ -324,7 +324,7 @@ public function cancelRefund(string $orderId, string $refundId, Context $context
# first try to cancel on the mollie side
$success = $this->refundService->cancel($order, $refundId);
- if (!$success) {
+ if (! $success) {
return false;
}
@@ -521,12 +521,13 @@ private function convertToRepositoryArray(array $serviceItems): array
if ($item->getQuantity() < 0) {
continue;
}
-
+ $quantity = max(1, $item->getQuantity());
+ $amount = round($item->getAmount() / $quantity, 2);
$row = RefundItemEntity::createArray(
$item->getMollieLineID(),
$item->getShopwareReference(),
- $item->getQuantity(),
- $item->getAmount(),
+ $quantity,
+ $amount,
$item->getShopwareLineID(),
$item->getShopwareLineVersionId(),
null
diff --git a/src/Controller/Api/Order/RefundControllerBase.php b/src/Controller/Api/Order/RefundControllerBase.php
index 77f9a8904..3ca39f33b 100644
--- a/src/Controller/Api/Order/RefundControllerBase.php
+++ b/src/Controller/Api/Order/RefundControllerBase.php
@@ -7,7 +7,6 @@
use Kiener\MolliePayments\Components\RefundManager\Request\RefundRequestItem;
use Kiener\MolliePayments\Exception\PaymentNotFoundException;
use Kiener\MolliePayments\Service\OrderService;
-use Kiener\MolliePayments\Service\Refund\Exceptions\CreditNoteException;
use Kiener\MolliePayments\Service\Refund\RefundCreditNoteService;
use Kiener\MolliePayments\Service\Refund\RefundService;
use Kiener\MolliePayments\Traits\Api\ApiTrait;
@@ -55,10 +54,10 @@ class RefundControllerBase extends AbstractController
* @param LoggerInterface $logger
*/
public function __construct(
- OrderService $orderService,
- RefundManagerInterface $refundManager,
- RefundService $refundService,
- LoggerInterface $logger,
+ OrderService $orderService,
+ RefundManagerInterface $refundManager,
+ RefundService $refundService,
+ LoggerInterface $logger,
RefundCreditNoteService $creditNoteService
) {
$this->orderService = $orderService;
@@ -181,7 +180,7 @@ public function refundOrderID(RequestDataBag $data, Context $context): JsonRespo
$items = $itemsBag->all();
}
- $response = $this->refundAction(
+ return $this->refundAction(
$orderId,
'',
$description,
@@ -190,32 +189,6 @@ public function refundOrderID(RequestDataBag $data, Context $context): JsonRespo
$items,
$context
);
-
- if ($response->getStatusCode() === 200 && $response->getContent() !== false && count($items) > 0) {
- $refundId = json_decode($response->getContent(), true)['refundId'];
- if ($this->creditNoteService->containsRefundedLineItems($items)) {
- try {
- $this->creditNoteService->addCreditNoteToOrder($orderId, $refundId, $items, $context);
- } catch (CreditNoteException $exception) {
- if ($exception->getCode() === CreditNoteException::CODE_ADDING_CREDIT_NOTE_LINE_ITEMS) {
- $this->logger->error($exception->getMessage(), ['code' => $exception->getCode(),]);
- return $this->buildErrorResponse($exception->getMessage());
- }
- if ($exception->getCode() === CreditNoteException::CODE_WARNING_LEVEL) {
- $this->logger->warning($exception->getMessage(), ['code' => $exception->getCode(),]);
- }
- }
- }
- if ($this->creditNoteService->hasCustomAmounts($items, (float) $amount)) {
- try {
- $this->creditNoteService->addCustomAmountsCreditNote($orderId, $refundId, $items, (float)$amount, $context);
- } catch (CreditNoteException $exception) {
- $this->logger->warning($exception->getMessage(), ['code' => $exception->getCode(),]);
- }
- }
- }
-
- return $response;
}
/**
@@ -228,23 +201,7 @@ public function cancel(RequestDataBag $data, Context $context): JsonResponse
{
$orderId = $data->getAlnum('orderId');
$refundId = $data->get('refundId');
- $response = $this->cancelRefundAction($orderId, $refundId, $context);
-
- if ($response->getStatusCode() === 200) {
- try {
- $this->creditNoteService->cancelCreditNoteToOrder($orderId, $refundId, $context);
- } catch (CreditNoteException $exception) {
- if ($exception->getCode() === CreditNoteException::CODE_REMOVING_CREDIT_NOTE_LINE_ITEMS) {
- $this->logger->error($exception->getMessage(), ['code' => $exception->getCode(),]);
- return $this->buildErrorResponse($exception->getMessage());
- }
- if ($exception->getCode() === CreditNoteException::CODE_WARNING_LEVEL) {
- $this->logger->warning($exception->getMessage(), ['code' => $exception->getCode(),]);
- }
- }
- }
-
- return $response;
+ return $this->cancelRefundAction($orderId, $refundId, $context);
}
/**
@@ -374,7 +331,7 @@ private function listTotalAction(string $orderId, Context $context): JsonRespons
private function refundAction(string $orderId, string $orderNumber, string $description, string $internalDescription, ?float $amount, array $items, Context $context): JsonResponse
{
try {
- if (!empty($orderId)) {
+ if (! empty($orderId)) {
$order = $this->orderService->getOrder($orderId, $context);
} else {
if (empty($orderNumber)) {
@@ -407,6 +364,8 @@ private function refundAction(string $orderId, string $orderNumber, string $desc
$context
);
+ $this->creditNoteService->createCreditNotes($order, $refund, $refundRequest, $context);
+
return $this->json([
'success' => true,
'refundId' => $refund->id
@@ -428,6 +387,9 @@ private function cancelRefundAction(string $orderId, string $refundId, Context $
{
try {
$success = $this->refundManager->cancelRefund($orderId, $refundId, $context);
+
+ $this->creditNoteService->cancelCreditNotes($orderId, $context);
+
return $this->json([
'success' => $success
]);
diff --git a/src/Resources/config/services/services.xml b/src/Resources/config/services/services.xml
index 3f9a508a2..fd0d003d2 100644
--- a/src/Resources/config/services/services.xml
+++ b/src/Resources/config/services/services.xml
@@ -63,14 +63,13 @@
-
+
-
diff --git a/src/Service/Refund/RefundCreditNoteService.php b/src/Service/Refund/RefundCreditNoteService.php
index d68a9a932..6a14fd880 100644
--- a/src/Service/Refund/RefundCreditNoteService.php
+++ b/src/Service/Refund/RefundCreditNoteService.php
@@ -3,19 +3,22 @@
namespace Kiener\MolliePayments\Service\Refund;
-use Kiener\MolliePayments\Service\Refund\Exceptions\CreditNoteException;
+use Kiener\MolliePayments\Components\RefundManager\Request\RefundRequest;
+use Kiener\MolliePayments\Service\CustomFieldsInterface;
use Kiener\MolliePayments\Service\SettingsService;
+use Mollie\Api\Resources\Refund;
use Psr\Log\LoggerInterface;
use Shopware\Core\Checkout\Cart\LineItem\LineItem;
use Shopware\Core\Checkout\Cart\Price\Struct\CalculatedPrice;
-use Shopware\Core\Checkout\Cart\Price\Struct\QuantityPriceDefinition;
use Shopware\Core\Checkout\Cart\Tax\Struct\CalculatedTaxCollection;
use Shopware\Core\Checkout\Cart\Tax\Struct\TaxRuleCollection;
+use Shopware\Core\Checkout\Order\Aggregate\OrderDelivery\OrderDeliveryEntity;
use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity;
use Shopware\Core\Checkout\Order\OrderEntity;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
+use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\Uuid\Uuid;
class RefundCreditNoteService
@@ -50,16 +53,11 @@ class RefundCreditNoteService
*/
private $logger;
- /**
- * @var RefundSummarizationService
- */
- private $refundSummarizationService;
public function __construct(
EntityRepository $orderRepository,
EntityRepository $orderLineItemRepository,
SettingsService $settingsService,
- RefundSummarizationService $refundSummarizationService,
LoggerInterface $logger
) {
$this->orderRepository = $orderRepository;
@@ -69,193 +67,158 @@ public function __construct(
$this->prefix = $settings->getRefundManagerCreateCreditNotesPrefix();
$this->suffix = $settings->getRefundManagerCreateCreditNotesSuffix();
$this->logger = $logger;
- $this->refundSummarizationService = $refundSummarizationService;
}
/**
- * @param array $lineItems
- * @throws CreditNoteException
+ * @param string $orderId
+ * @param string $refundId
+ * @param float $unitPrice
+ * @param int $quantity
+ * @param float $totalAmount
+ * @param null|OrderLineItemEntity $orderLineItemEntity
+ * @param null|OrderDeliveryEntity $orderDeliveryEntity
+ * @return array
*/
- public function addCreditNoteToOrder(string $orderId, string $refundId, array $lineItems, Context $context): void
+ private function getLineItemArray(string $orderId, string $refundId, float $unitPrice, int $quantity, float $totalAmount, ?OrderLineItemEntity $orderLineItemEntity = null, ?OrderDeliveryEntity $orderDeliveryEntity = null): array
{
- if (!$this->enabled) {
- $this->logger->debug('Credit note creation is disabled');
- return;
+ $id = $orderId . 'custom-amount';
+ $label = $totalAmount;
+
+ $taxCollection = new CalculatedTaxCollection();
+ $taxRuleCollection = new TaxRuleCollection();
+
+ if ($orderLineItemEntity !== null) {
+ $id = $orderLineItemEntity->getId();
+ $label = $orderLineItemEntity->getLabel();
+ $price = $orderLineItemEntity->getPrice();
+ if ($price !== null) {
+ $taxCollection = $price->getCalculatedTaxes();
+ $taxRuleCollection = $price->getTaxRules();
+ }
}
+ if ($orderDeliveryEntity !== null) {
+ $id = $orderDeliveryEntity->getId();
+ $shippingMethod = $orderDeliveryEntity->getShippingMethod();
+ $label = 'Shipping';
+ if ($shippingMethod !== null) {
+ $label = $shippingMethod->getName();
+ }
+ $price = $orderDeliveryEntity->getShippingCosts();
- if (empty($orderId) || empty($refundId)) {
- throw CreditNoteException::forAddingLineItems(sprintf('OrderId or RefundId is empty. OrderID: %s RefundID: %s', $orderId, $refundId));
+ $taxCollection = $price->getCalculatedTaxes();
+ $taxRuleCollection = $price->getTaxRules();
}
- if (empty($lineItems)) {
- throw CreditNoteException::forAddingLineItems(sprintf('No line items found for credit note. OrderID: %s RefundID: %s', $orderId, $refundId));
- }
+ $label = trim(sprintf('%s%s%s', $this->prefix, $label, $this->suffix));
- $data = ['id' => $orderId, 'lineItems' => []];
- foreach ($lineItems as ['id' => $lineItemId, 'amount' => $amount]) {
- if ($amount === 0) {
- // refund manager front end sends all line items, even if they are not going to be refunded
- continue;
- }
- $lineItem = $this->orderLineItemRepository->search(new Criteria([$lineItemId]), $context)->first();
- if (!$lineItem instanceof OrderLineItemEntity) {
- continue;
- }
- $price = $lineItem->getPrice();
- if (!$price instanceof CalculatedPrice) {
- continue;
- }
- $taxRules = $price->getTaxRules();
- $totalPrice = $lineItem->getTotalPrice();
- $quantity = $lineItem->getQuantity();
- if ($totalPrice <= 0 || $quantity <= 0) {
- continue;
- }
- $unitPrice = round($totalPrice / $quantity, 2);
- $totalPrice *= -1;
- $unitPrice *= -1;
- $data['lineItems'][] = [
- 'id' => Uuid::fromBytesToHex(md5($lineItemId, true)), #@todo remove once 6.4 reached end of life
- 'identifier' => Uuid::fromBytesToHex(md5($lineItem->getIdentifier(), true)),#@todo remove once 6.4 reached end of life
- 'quantity' => $quantity,
- 'label' => sprintf('%s%s%s', $this->prefix, $lineItem->getLabel(), $this->suffix),
- 'type' => LineItem::CREDIT_LINE_ITEM_TYPE,
- 'price' => new CalculatedPrice($unitPrice, $totalPrice, new CalculatedTaxCollection(), $taxRules),
- 'priceDefinition' => new QuantityPriceDefinition($totalPrice, $taxRules, $quantity),
- 'customFields' => [
- 'mollie_payments' => [
- 'type' => 'refund',
- 'refundId' => $refundId,
- 'lineItemId' => $lineItemId
- ],
+ return [
+ 'id' => Uuid::fromBytesToHex(md5($id, true)), #@todo remove once 6.4 reached end of life
+ 'identifier' => Uuid::fromBytesToHex(md5($id, true)), #@todo remove once 6.4 reached end of life
+ 'quantity' => $quantity,
+ 'label' => $label,
+ 'type' => LineItem::CREDIT_LINE_ITEM_TYPE,
+ 'price' => new CalculatedPrice($unitPrice, $totalAmount, $taxCollection, $taxRuleCollection),
+ 'customFields' => [
+ CustomFieldsInterface::MOLLIE_KEY => [
+ 'type' => 'refund',
+ 'refundId' => $refundId
],
- ];
- }
-
- if (empty($data['lineItems'])) {
- throw CreditNoteException::forAddingLineItems(sprintf('No credit note line items found for order. OrderID: %s RefundID: %s', $orderId, $refundId), CreditNoteException::CODE_WARNING_LEVEL);
- }
-
- $this->logger->debug('Adding credit note to order', ['orderId' => $orderId, 'refundId' => $refundId, 'lineItems' => $data['lineItems']]);
- $this->orderRepository->upsert([$data], $context);
+ ],
+ ];
}
- /**
- * @throws CreditNoteException
- */
- public function cancelCreditNoteToOrder(string $orderId, string $refundId, Context $context): void
+ public function createCreditNotes(OrderEntity $order, Refund $refund, RefundRequest $refundRequest, Context $context): void
{
- if (empty($orderId) || empty($refundId)) {
- throw CreditNoteException::forRemovingLineItems(sprintf('OrderId or RefundId is empty. OrderID: %s RefundID: %s', $orderId, $refundId));
- }
-
- $criteria = new Criteria([$orderId]);
- $criteria->addAssociation('lineItems');
- $searchResult = $this->orderRepository->search($criteria, $context);
- $order = $searchResult->first();
-
- if (!$order instanceof OrderEntity) {
- throw CreditNoteException::forRemovingLineItems(sprintf('Order not found. OrderID: %s RefundID: %s', $orderId, $refundId));
- }
-
- $lineItems = $order->getLineItems();
-
- if ($lineItems === null) {
- throw CreditNoteException::forRemovingLineItems(
- sprintf('No line items found for order. OrderID: %s RefundID: %s', $orderId, $refundId),
- CreditNoteException::CODE_WARNING_LEVEL
- );
+ if (! $this->enabled) {
+ $this->logger->debug('Credit note creation is disabled');
+ return;
}
-
- $ids = [];
- foreach ($lineItems as $lineItem) {
- /** @var OrderLineItemEntity $lineItem */
- $customFields = $lineItem->getCustomFields();
- if (!isset($customFields['mollie_payments'], $customFields['mollie_payments']['type']) || $customFields['mollie_payments']['type'] !== 'refund') {
- continue;
- }
-
- $lineItemRefundId = $customFields['mollie_payments']['refundId'];
- if ($lineItemRefundId !== $refundId) {
- continue;
+ $orderId = $order->getId();
+ $refundId = $refund->id;
+
+ $lineItems = [];
+
+
+ $orderLineItems = $order->getLineItems();
+ $orderDeliveries = $order->getDeliveries();
+ $refundAmount = $refundRequest->getAmount();
+
+ if (count($refundRequest->getItems()) > 0) {
+ foreach ($refundRequest->getItems() as $refundLineItem) {
+ $orderLineItemId = $refundLineItem->getLineId();
+ $totalAmount = $refundLineItem->getAmount();
+ $quantity = max(1, $refundLineItem->getQuantity());
+ if ($totalAmount <= 0.0) {
+ continue;
+ }
+ $unitPrice = $totalAmount / $quantity;
+
+ $refundAmount -= $totalAmount;
+ $refundAmount = round($refundAmount, 2);
+
+ if ($orderLineItems === null) {
+ continue;
+ }
+
+ $filteredOrderLineItems = $orderLineItems->filter(function (OrderLineItemEntity $item) use ($orderLineItemId) {
+ return $item->getId() === $orderLineItemId;
+ });
+
+ if ($filteredOrderLineItems->count() === 0) {
+ if ($orderDeliveries === null) {
+ continue;
+ }
+
+ $filteredOrderDeliveries = $orderDeliveries->filter(function (OrderDeliveryEntity $item) use ($orderLineItemId) {
+ return $item->getId() === $orderLineItemId;
+ });
+ if ($filteredOrderDeliveries->count() === 0) {
+ continue;
+ }
+
+ $orderDelivery = $filteredOrderDeliveries->first();
+ $lineItems[] = $this->getLineItemArray($orderId, $refundId, $unitPrice, $quantity, $totalAmount, null, $orderDelivery);
+ continue;
+ }
+ $orderLineItem = $filteredOrderLineItems->first();
+
+ $lineItems[] = $this->getLineItemArray($orderId, $refundId, $unitPrice, $quantity, $totalAmount, $orderLineItem);
}
-
- $ids[] = ['id' => $lineItem->getId()];
}
- if (empty($ids)) {
- throw CreditNoteException::forRemovingLineItems(
- sprintf('No credit note line items found for order. OrderID: %s RefundID: %s', $orderId, $refundId),
- CreditNoteException::CODE_WARNING_LEVEL
- );
+ if ($refundAmount > 0) {
+ $lineItems[] = $this->getLineItemArray($orderId, $refundId, $refundAmount, 1, $refundAmount);
}
- $this->orderLineItemRepository->delete($ids, $context);
+ $this->logger->debug('Adding credit note to order', ['orderId' => $orderId, 'refundId' => $refundId, 'lineItems' => $lineItems]);
+ $this->orderRepository->upsert([[
+ 'id' => $orderId,
+ 'lineItems' => $lineItems,
+ ]], $context);
}
- /**
- * Checks if the provided line items contain any refunded amounts.
- *
- * This method evaluates the total refund amount of the given line items by
- * using the `getLineItemsRefundSum` method from `RefundSummarizationService`.
- * If the summed refund amount is greater than zero, it indicates that
- * the items contain refunded line items.
- *
- * @param array $items Array of items, each potentially containing an 'amount' field.
- * @return bool True if the items contain refunded line items (sum of 'amount' > 0), false otherwise.
- */
- public function containsRefundedLineItems(array $items): bool
+ public function cancelCreditNotes(string $orderId, Context $context): void
{
- // Checks if the total refund sum of line items is greater than zero,
- // which indicates that there are refunded line items present.
- return $this->refundSummarizationService->getLineItemsRefundSum($items) > 0;
- }
- /**
- * @param array $items
- * @param float $refundAmount
- * @return bool
- */
- public function hasCustomAmounts(array $items, float $refundAmount): bool
- {
- return $this->refundSummarizationService->customAmountInLineItems($items, $refundAmount) !== 0.0;
- }
-
- /**
- * @param string $orderId
- * @param string $refundId
- * @param array $items
- * @param float $refundAmount
- * @param Context $context
- * @throws CreditNoteException
- */
- public function addCustomAmountsCreditNote(string $orderId, string $refundId, array $items, float $refundAmount, Context $context): void
- {
- $customAmount = $this->refundSummarizationService->customAmountInLineItems($items, $refundAmount);
+ //do not check for enabled, because credit notes could be created before and you still want to delete them, even if the feature is disabled now
- if (empty($orderId) || empty($refundId)) {
- throw CreditNoteException::forAddingLineItems(sprintf('OrderId or RefundId is empty. OrderID: %s RefundID: %s', $orderId, $refundId));
+ $criteria = new Criteria();
+ $criteria->addFilter(new EqualsFilter('orderId', $orderId));
+ $criteria->addFilter(new EqualsFilter('type', LineItem::CREDIT_LINE_ITEM_TYPE));
+ $this->logger->debug('Start cancel credit notes', ['orderId' => $orderId]);
+ $searchResult = $this->orderLineItemRepository->searchIds($criteria, $context);
+ if ($searchResult->getTotal() === 0) {
+ $this->logger->debug('No credit notes found', ['orderId' => $orderId]);
+ return;
}
+ $ids = $searchResult->getIds();
+ $toDelete = [];
+ foreach ($ids as $id) {
+ $toDelete[] = ['id' => $id];
+ }
+ $this->orderLineItemRepository->delete($toDelete, $context);
- $data = ['id' => $orderId, 'lineItems' => []];
-
- $data['lineItems'][] = [
- 'id' => Uuid::fromBytesToHex(md5($orderId . 'custom-amount', true)), #@todo remove once 6.4 reached end of life
- 'identifier' => Uuid::fromBytesToHex(md5($orderId . 'custom-amount', true)), #@todo remove once 6.4 reached end of life
- 'quantity' => 1,
- 'label' => sprintf('%s%s%s', $this->prefix, $customAmount, $this->suffix),
- 'type' => LineItem::CREDIT_LINE_ITEM_TYPE,
- 'price' => new CalculatedPrice($customAmount, $customAmount, new CalculatedTaxCollection(), new TaxRuleCollection()),
- 'customFields' => [
- 'mollie_payments' => [
- 'type' => 'refund',
- 'refundId' => $refundId
- ],
- ],
- ];
-
- $this->logger->debug('Adding credit note to order', ['orderId' => $orderId, 'refundId' => $refundId, 'lineItems' => $data['lineItems']]);
- $this->orderRepository->upsert([$data], $context);
+ $this->logger->debug('Deleted credit notes from order', ['orderId' => $orderId, 'total' => count($ids)]);
}
}
diff --git a/src/Service/Refund/RefundSummarizationService.php b/src/Service/Refund/RefundSummarizationService.php
deleted file mode 100644
index a53da9342..000000000
--- a/src/Service/Refund/RefundSummarizationService.php
+++ /dev/null
@@ -1,54 +0,0 @@
- $items Array of items, each containing an 'amount' field.
- * The 'amount' field should be convertible to a float.
- * @return float Total refund sum calculated from the 'amount' values in the provided items.
- */
- public function getLineItemsRefundSum(array $items): float
- {
- // Extracts the 'amount' values from each item in the array
- $amounts = array_column($items, 'amount');
-
- // Converts each extracted amount to a float to ensure accurate summation
- $amounts = array_map('floatval', $amounts);
-
- // Sums up all converted amounts and returns the result as the total refund amount
- return array_sum($amounts);
- }
-
- /**
- * @param array $items
- * @param float $refundAmounts
- * @return float
- */
- public function customAmountInLineItems(array $items, float $refundAmounts): float
- {
- // Extracts the 'amount' values from each item in the array
- $amounts = array_column($items, 'amount');
-
- // Converts each extracted amount to a float to ensure accurate summation
- $amounts = array_map('floatval', $amounts);
-
- foreach ($amounts as $amount) {
- $refundAmounts -= $amount;
- }
-
- return (float) $refundAmounts;
- }
-}
diff --git a/tests/PHPUnit/Components/RefundManager/RefundManagerTest.php b/tests/PHPUnit/Components/RefundManager/RefundManagerTest.php
index 08cf3e38c..85d2e7b44 100644
--- a/tests/PHPUnit/Components/RefundManager/RefundManagerTest.php
+++ b/tests/PHPUnit/Components/RefundManager/RefundManagerTest.php
@@ -210,7 +210,7 @@ public function testValidItemsAreAdded(int $qty, float $itemPrice): void
[
"mollieLineId" => "odl_123",
"label" => "product-id-1",
- "quantity" => $qty,
+ "quantity" => max($qty,1),
"amount" => $itemPrice,
"orderLineItemId" => "line-1",
'orderLineItemVersionId' => null,
diff --git a/tests/PHPUnit/Service/Refund/RefundCreditNoteServiceTest.php b/tests/PHPUnit/Service/Refund/RefundCreditNoteServiceTest.php
deleted file mode 100644
index 9d6c97561..000000000
--- a/tests/PHPUnit/Service/Refund/RefundCreditNoteServiceTest.php
+++ /dev/null
@@ -1,246 +0,0 @@
-enabled = true;
- $this->prefix = 'prefix';
- $this->suffix = 'suffix';
- $this->orderRepository = $this->createMock(EntityRepository::class);
- $this->orderLineRepository = $this->createMock(EntityRepository::class);
- $this->settingsService = $this->createMock(SettingsService::class);
- $this->logger = $this->createMock(LoggerInterface::class);
- $this->context = $this->createMock(Context::class);
- }
-
- public function testCreatesLogEntryWhenServiceIsDisabledInConfig(): void
- {
- $this->enabled = false;
- $this->logger->expects($this->once())->method('debug');
- $this->orderRepository->expects($this->never())->method('search');
- $this->orderRepository->expects($this->never())->method('upsert');
-
- $this->service()->addCreditNoteToOrder('orderId', 'refundId', [], $this->context);
- }
-
- public function testThrowsExceptionWhenOrderIdIsEmpty(): void
- {
- $this->expectException(CreditNoteException::class);
-
- $this->service()->addCreditNoteToOrder('', 'refundId', [], $this->context);
- }
-
- public function testThrowsExceptionWhenRefundIdIsEmpty(): void
- {
- $this->expectException(CreditNoteException::class);
-
- $this->service()->addCreditNoteToOrder('orderId', '', [], $this->context);
- }
-
- public function throwsExceptionWhenNoLineItemsAreProvided(): void
- {
- $this->expectException(CreditNoteException::class);
-
- $this->service()->addCreditNoteToOrder('orderId', 'refundId', [], $this->context);
- }
-
- /**
- * @throws CreditNoteException
- */
- public function testCanAddRefundLineItems(): void
- {
- $data = [
- ['id' => $lineItemId = Uuid::randomBytes(), 'amount' => 1]
- ];
-
- $price = $this->createConfiguredMock(CalculatedPrice::class, [
- 'getTaxRules' => $rules = $this->createMock(TaxRuleCollection::class)
- ]);
- $lineItemEntity = $this->createConfiguredMock(OrderLineItemEntity::class,
- [
- 'getId' => $lineItemId,
- 'getIdentifier' => 'lineItemIdentifier',
- 'getPrice' => $price,
- 'getQuantity' => 1,
- 'getTotalPrice' => 9.99,
- 'getLabel' => 'label'
- ]
- );
- $searchResult = $this->createConfiguredMock(EntitySearchResult::class, ['first' => $lineItemEntity]);
- $this->orderLineRepository->expects($this->once())->method('search')->willReturn($searchResult);
-
- $expectedDataArray = [
- 'id' => $orderId = 'orderId',
- 'lineItems' => [
- [
- 'id' => Uuid::fromStringToHex($lineItemId),
- 'identifier' => Uuid::fromStringToHex('lineItemIdentifier'),
- 'quantity' => 1,
- 'label' => sprintf('%s%s%s', $this->prefix, $lineItemEntity->getLabel(), $this->suffix),
- 'type' => LineItem::CREDIT_LINE_ITEM_TYPE,
- 'price' => new CalculatedPrice(-9.99, -9.99, new CalculatedTaxCollection(), $rules),
- 'priceDefinition' => new QuantityPriceDefinition(-9.99, $rules, 1),
- 'customFields' => [
- 'mollie_payments' => [
- 'type' => 'refund',
- 'refundId' => $refundId = 'refundId',
- 'lineItemId' => $lineItemId
- ],
- ],
- ]
- ]
- ];
-
- $this->logger->expects($this->once())->method('debug');
- $this->orderRepository->expects($this->once())->method('upsert')->with(
- $this->equalTo([$expectedDataArray]),
- $this->equalTo($this->context)
- );
-
- $this->service()->addCreditNoteToOrder($orderId, $refundId, $data, $this->context);
- }
-
- public function testThrowsExceptionWhenOrderIdIsEmptyWhenCanceling(): void
- {
- $this->expectException(CreditNoteException::class);
-
- $this->service()->cancelCreditNoteToOrder('', 'refundId', $this->context);
- }
-
- public function testThrowsExceptionWhenRefundIdIsEmptyWhenCanceling(): void
- {
- $this->expectException(CreditNoteException::class);
-
- $this->service()->cancelCreditNoteToOrder('orderId', '', $this->context);
- }
-
- public function testThrowsExceptionWhenNoCreditLineItemsWouldBeUpserted(): void
- {
- $this->expectException(CreditNoteException::class);
-
- $data = [
- ['id' => Uuid::randomBytes(), 'amount' => 1]
- ];
-
- $searchResult = $this->createConfiguredMock(EntitySearchResult::class, ['first' => null]);
- $this->orderLineRepository->expects($this->once())->method('search')->willReturn($searchResult);
-
- $this->service()->addCreditNoteToOrder('OrderId', 'RefundId', $data, $this->context);
- }
-
- /**
- * @throws CreditNoteException
- */
- public function testDeletesAssociatedLineItemsWhenCanceling(): void
- {
- $orderId = 'orderId';
- $refundId = 'refundId';
-
- $searchResult = $this->createConfiguredMock(EntitySearchResult::class, ['first' => $order = $this->createMock(OrderEntity::class)]);
- $this->orderRepository->expects($this->once())->method('search')->willReturn($searchResult);
-
- $lineItems = new OrderLineItemCollection([
- $lineItem = $this->createConfiguredMock(OrderLineItemEntity::class, [
- 'getId' => $expected = Uuid::randomHex(),
- 'getCustomFields' => ['mollie_payments' => ['type' => 'refund', 'refundId' => $refundId]]
- ])
- ]);
-
- $order->expects($this->once())->method('getLineItems')->willReturn($lineItems);
-
- $this->orderLineRepository->expects($this->once())->method('delete')
- ->with(
- $this->equalTo([['id' => $expected]]),
- $this->equalTo($this->context)
- );
-
- $this->service()->cancelCreditNoteToOrder($orderId, $refundId, $this->context);
- }
-
-
- private function service(?RefundSummarizationService $summarizationService = null): RefundCreditNoteService
- {
- $settingsStruct = new MollieSettingStruct();
- $settingsStruct->setRefundManagerCreateCreditNotesEnabled($this->enabled);
- $settingsStruct->setRefundManagerCreateCreditNotesPrefix($this->prefix);
- $settingsStruct->setRefundManagerCreateCreditNotesSuffix($this->suffix);
-
- $this->settingsService->method('getSettings')->willReturn($settingsStruct);
-
- return new RefundCreditNoteService(
- $this->orderRepository,
- $this->orderLineRepository,
- $this->settingsService,
- $summarizationService ?? new RefundSummarizationServiceFake(),
- $this->logger
- );
- }
-}
\ No newline at end of file
diff --git a/tests/PHPUnit/Service/Refund/RefundSummarizationServiceTest.php b/tests/PHPUnit/Service/Refund/RefundSummarizationServiceTest.php
deleted file mode 100644
index df51b390f..000000000
--- a/tests/PHPUnit/Service/Refund/RefundSummarizationServiceTest.php
+++ /dev/null
@@ -1,47 +0,0 @@
-service = new RefundSummarizationService();
- }
-
- /**
- * @dataProvider summarizeDataProvider
- */
- public function testCanSummarize(float ...$values): void
- {
- $expected = 0;
- $dataSet = [];
-
- foreach ($values as $value) {
- $dataSet[] = ['amount' => $value];
- $expected += $value;
- }
-
- $actual = $this->service->getLineItemsRefundSum($dataSet);
-
- static::assertEquals($expected, $actual);
- }
-
- public static function summarizeDataProvider(): array
- {
- return [
- 'single value' => [10.0],
- 'multiple values' => [10.0, 20.0, 30.0],
- ];
- }
-}
\ No newline at end of file