Completed
Push — master ( e2eed5...73dfaa )
by Oleksandr
13s queued 10s
created

RefundItemsTransactionHandler   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 228
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 69
c 2
b 0
f 0
dl 0
loc 228
rs 10
wmc 23

11 Methods

Rating   Name   Duplication   Size   Complexity  
A createTransactionMetaTransfer() 0 8 1
A executeTransactionByItems() 0 14 3
A removeShipmentExpense() 0 13 3
A getRefundedUniqueItems() 0 15 3
A mapItemsAmount() 0 9 2
A findShipmentExpenseTransfer() 0 9 3
A getItemsForRefunding() 0 11 2
A refund() 0 15 2
A getOrderItemsGroupedByTransaction() 0 22 2
A getRefund() 0 3 1
A __construct() 0 10 1
1
<?php
2
3
/**
4
 * MIT License
5
 * For full license information, please view the LICENSE file that was distributed with this source code.
6
 */
7
8
namespace SprykerEco\Zed\Braintree\Business\Payment\Transaction\Handler;
9
10
use ArrayObject;
11
use Generated\Shared\Transfer\ExpenseTransfer;
0 ignored issues
show
Bug introduced by
The type Generated\Shared\Transfer\ExpenseTransfer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use Generated\Shared\Transfer\ItemTransfer;
0 ignored issues
show
Bug introduced by
The type Generated\Shared\Transfer\ItemTransfer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
13
use Generated\Shared\Transfer\RefundTransfer;
0 ignored issues
show
Bug introduced by
The type Generated\Shared\Transfer\RefundTransfer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
14
use Generated\Shared\Transfer\TransactionMetaTransfer;
0 ignored issues
show
Bug introduced by
The type Generated\Shared\Transfer\TransactionMetaTransfer was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
use Orm\Zed\Sales\Persistence\SpySalesOrder;
0 ignored issues
show
Bug introduced by
The type Orm\Zed\Sales\Persistence\SpySalesOrder was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
16
use Spryker\Shared\Shipment\ShipmentConstants;
17
use SprykerEco\Zed\Braintree\Business\Payment\Transaction\MetaVisitor\TransactionMetaVisitorInterface;
18
use SprykerEco\Zed\Braintree\Business\Payment\Transaction\TransactionInterface;
19
use SprykerEco\Zed\Braintree\Dependency\Facade\BraintreeToRefundFacadeInterface;
20
use SprykerEco\Zed\Braintree\Persistence\BraintreeRepositoryInterface;
21
22
class RefundItemsTransactionHandler extends AbstractTransactionHandler implements RefundItemsTransactionHandlerInterface
23
{
24
    protected const KEY_AMOUNT = 'amount';
25
    protected const KEY_PAYMENT_ID = 'payment_id';
26
27
    /**
28
     * @var \SprykerEco\Zed\Braintree\Dependency\Facade\BraintreeToRefundFacadeInterface
29
     */
30
    protected $refundFacade;
31
32
    /**
33
     * @var \SprykerEco\Zed\Braintree\Persistence\BraintreeRepositoryInterface
34
     */
35
    protected $braintreeRepository;
36
37
    /**
38
     * @param \SprykerEco\Zed\Braintree\Business\Payment\Transaction\TransactionInterface $refundItemsTranasction
39
     * @param \SprykerEco\Zed\Braintree\Business\Payment\Transaction\MetaVisitor\TransactionMetaVisitorInterface $transactionMetaVisitor
40
     * @param \SprykerEco\Zed\Braintree\Dependency\Facade\BraintreeToRefundFacadeInterface $refundFacade
41
     * @param \SprykerEco\Zed\Braintree\Persistence\BraintreeRepositoryInterface $braintreeRepository
42
     */
43
    public function __construct(
44
        TransactionInterface $refundItemsTranasction,
45
        TransactionMetaVisitorInterface $transactionMetaVisitor,
46
        BraintreeToRefundFacadeInterface $refundFacade,
47
        BraintreeRepositoryInterface $braintreeRepository
48
    ) {
49
        parent::__construct($refundItemsTranasction, $transactionMetaVisitor);
50
51
        $this->refundFacade = $refundFacade;
52
        $this->braintreeRepository = $braintreeRepository;
53
    }
54
55
    /**
56
     * @param \Orm\Zed\Sales\Persistence\SpySalesOrderItem[] $salesOrderItems
57
     * @param \Orm\Zed\Sales\Persistence\SpySalesOrder $salesOrderEntity
58
     *
59
     * @return void
60
     */
61
    public function refund(array $salesOrderItems, SpySalesOrder $salesOrderEntity): void
62
    {
63
        $refundTransfer = $this->getRefund($salesOrderItems, $salesOrderEntity);
64
        $transactionMetaTransfer = $this->createTransactionMetaTransfer($salesOrderItems, $salesOrderEntity, $refundTransfer);
65
66
        $orderItemsGroupedByTransaction = $this->getOrderItemsGroupedByTransaction($transactionMetaTransfer);
67
        $shipmentExpense = $this->findShipmentExpenseTransfer($refundTransfer);
68
69
        $this->executeTransactionByItems($orderItemsGroupedByTransaction, $transactionMetaTransfer, $refundTransfer);
70
71
        if ($shipmentExpense) {
72
            $refundTransfer->getExpenses()->append($shipmentExpense);
73
        }
74
75
        $this->refundFacade->saveRefund($refundTransfer);
76
    }
77
78
    /**
79
     * @param \Orm\Zed\Sales\Persistence\SpySalesOrderItem[] $salesOrderItems
80
     * @param \Orm\Zed\Sales\Persistence\SpySalesOrder $salesOrderEntity
81
     *
82
     * @return \Generated\Shared\Transfer\RefundTransfer
83
     */
84
    protected function getRefund(array $salesOrderItems, SpySalesOrder $salesOrderEntity): RefundTransfer
85
    {
86
        return $this->refundFacade->calculateRefund($salesOrderItems, $salesOrderEntity);
87
    }
88
89
    /**
90
     * @param \Orm\Zed\Sales\Persistence\SpySalesOrderItem[] $orderItems
91
     *
92
     * @return \ArrayObject
93
     */
94
    protected function getItemsForRefunding(array $orderItems): ArrayObject
95
    {
96
        $itemsForRefunding = [];
97
98
        foreach ($orderItems as $orderItem) {
99
            $itemTransfer = new ItemTransfer();
100
            $itemTransfer->fromArray($orderItem->toArray(), true);
101
            $itemsForRefunding[] = $itemTransfer;
102
        }
103
104
        return $this->getRefundedUniqueItems($itemsForRefunding);
105
    }
106
107
    /**
108
     * @param \Orm\Zed\Sales\Persistence\SpySalesOrderItem[] $salesOrderItems
109
     * @param \Orm\Zed\Sales\Persistence\SpySalesOrder $salesOrderEntity
110
     * @param \Generated\Shared\Transfer\RefundTransfer $refundTransfer
111
     *
112
     * @return \Generated\Shared\Transfer\TransactionMetaTransfer
113
     */
114
    protected function createTransactionMetaTransfer(array $salesOrderItems, SpySalesOrder $salesOrderEntity, RefundTransfer $refundTransfer): TransactionMetaTransfer
115
    {
116
        $transactionMetaTransfer = new TransactionMetaTransfer();
117
        $transactionMetaTransfer->setIdSalesOrder($salesOrderEntity->getIdSalesOrder());
118
        $transactionMetaTransfer->setRefund($refundTransfer);
119
        $transactionMetaTransfer->setItems($this->getItemsForRefunding($salesOrderItems));
120
121
        return $transactionMetaTransfer;
122
    }
123
124
    /**
125
     * @param \Generated\Shared\Transfer\ItemTransfer[] $itemTransfers
126
     *
127
     * @return \ArrayObject|\Generated\Shared\Transfer\ItemTransfer[]
128
     */
129
    protected function getRefundedUniqueItems(array $itemTransfers): ArrayObject
130
    {
131
        $uniqueItemTransfers = [];
132
        $uniqueItemIds = [];
133
134
        foreach ($itemTransfers as $itemTransfer) {
135
            if (!in_array($itemTransfer->getIdSalesOrderItem(), $uniqueItemIds)) {
136
                $uniqueItemTransfers[] = $itemTransfer;
137
                $uniqueItemIds[] = $itemTransfer->getIdSalesOrderItem();
138
            }
139
        }
140
141
        $uniqueItemTransfers = new ArrayObject($uniqueItemTransfers);
142
143
        return $uniqueItemTransfers;
144
    }
145
146
    /**
147
     * @param \Generated\Shared\Transfer\TransactionMetaTransfer $transactionMetaTransfer
148
     *
149
     * @return array
150
     */
151
    protected function getOrderItemsGroupedByTransaction(TransactionMetaTransfer $transactionMetaTransfer): array
152
    {
153
        $itemsByTransactions = [];
154
155
        $refundedItemMap = $this->mapItemsAmount($transactionMetaTransfer->getItems());
156
157
        $paymentBraintreeOrderItemTransfers = $this->braintreeRepository
158
            ->findPaymentBraintreeOrderItemsByIdsSalesOrderItem(array_keys($refundedItemMap));
159
160
        foreach ($paymentBraintreeOrderItemTransfers as $paymentBraintreeOrderItemTransfer) {
161
            $paymentBraintreeTransactionStatusLogTransfer = $this->braintreeRepository
162
                ->findPaymentBraintreeTransactionStatusLogQueryByPaymentBraintreeOrderItem($paymentBraintreeOrderItemTransfer->getIdPaymentBraintreeOrderItem());
163
164
            $amount = $itemsByTransactions[$paymentBraintreeTransactionStatusLogTransfer->getTransactionId()][static::KEY_AMOUNT] ?? 0;
165
166
            $itemsByTransactions[$paymentBraintreeTransactionStatusLogTransfer->getTransactionId()] = [
167
                static::KEY_PAYMENT_ID => $paymentBraintreeOrderItemTransfer->getFkPaymentBraintree(),
168
                static::KEY_AMOUNT => $amount + $refundedItemMap[$paymentBraintreeOrderItemTransfer->getFkSalesOrderItem()],
169
            ];
170
        }
171
172
        return $itemsByTransactions;
173
    }
174
175
    /**
176
     * @param \Generated\Shared\Transfer\RefundTransfer $refundTransfer
177
     *
178
     * @return \Generated\Shared\Transfer\RefundTransfer
179
     */
180
    protected function removeShipmentExpense(RefundTransfer $refundTransfer): RefundTransfer
181
    {
182
        $expenses = [];
183
184
        foreach ($refundTransfer->getExpenses() as $expenseTransfer) {
185
            if ($expenseTransfer->getType() !== ShipmentConstants::SHIPMENT_EXPENSE_TYPE) {
186
                $expenses[] = $expenseTransfer;
187
            }
188
        }
189
190
        $refundTransfer->setExpenses(new ArrayObject($expenses));
191
192
        return $refundTransfer;
193
    }
194
195
    /**
196
     * @param \Generated\Shared\Transfer\RefundTransfer $refundTransfer
197
     *
198
     * @return \Generated\Shared\Transfer\ExpenseTransfer|null
199
     */
200
    protected function findShipmentExpenseTransfer(RefundTransfer $refundTransfer): ?ExpenseTransfer
201
    {
202
        foreach ($refundTransfer->getExpenses() as $expenseTransfer) {
203
            if ($expenseTransfer->getType() === ShipmentConstants::SHIPMENT_EXPENSE_TYPE) {
204
                return $expenseTransfer;
205
            }
206
        }
207
208
        return null;
209
    }
210
211
    /**
212
     * @param array $orderItemsGroupedByTransaction
213
     * @param \Generated\Shared\Transfer\TransactionMetaTransfer $transactionMetaTransfer
214
     * @param \Generated\Shared\Transfer\RefundTransfer $refundTransfer
215
     *
216
     * @return void
217
     */
218
    protected function executeTransactionByItems(
219
        array $orderItemsGroupedByTransaction,
220
        TransactionMetaTransfer $transactionMetaTransfer,
221
        RefundTransfer $refundTransfer
222
    ): void {
223
        foreach ($orderItemsGroupedByTransaction as $transactionId => $data) {
224
            $transactionMetaTransfer->setIdPayment($data[static::KEY_PAYMENT_ID]);
225
            $transactionMetaTransfer->setTransactionIdentifier($transactionId);
226
            $transactionMetaTransfer->setRefundAmount($data[static::KEY_AMOUNT]);
227
228
            $braintreeTransactionResponseTransfer = $this->transaction->executeTransaction($transactionMetaTransfer);
229
230
            if ($braintreeTransactionResponseTransfer->getIsSuccess()) {
231
                $refundTransfer = $this->removeShipmentExpense($refundTransfer);
232
            }
233
        }
234
    }
235
236
    /**
237
     * @param \ArrayObject|\Generated\Shared\Transfer\ItemTransfer[] $itemTransfers
238
     *
239
     * @return array
240
     */
241
    protected function mapItemsAmount(iterable $itemTransfers): array
242
    {
243
        $itemsAmountMap = [];
244
245
        foreach ($itemTransfers as $itemTransfer) {
246
            $itemsAmountMap[$itemTransfer->getIdSalesOrderItem()] = $itemTransfer->getPriceToPayAggregation();
247
        }
248
249
        return $itemsAmountMap;
250
    }
251
}
252