getOrderItemsGroupedByTransaction()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

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