Passed
Pull Request — master (#13)
by Oleksandr
20:56 queued 15:27
created

RefundItemsTransactionHandler::refund()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 14
nc 6
nop 2
dl 0
loc 25
rs 9.7998
c 0
b 0
f 0
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 $transaction
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 $transaction,
45
        TransactionMetaVisitorInterface $transactionMetaVisitor,
46
        BraintreeToRefundFacadeInterface $refundFacade,
47
        BraintreeRepositoryInterface $braintreeRepository
48
    ) {
49
        parent::__construct($transaction, $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->getTransactionMetaTransfer($salesOrderItems, $salesOrderEntity, $refundTransfer);
65
66
        $orderItemsGroupedByTransaction = $this->getOrderItemsGroupedByTransaction($transactionMetaTransfer);
67
        $shipmentExpense = $this->getShipmentExpenseTransfer($refundTransfer);
68
69
        foreach ($orderItemsGroupedByTransaction as $transactionId => $data) {
70
            $transactionMetaTransfer->setIdPayment($data[static::KEY_PAYMENT_ID]);
71
            $transactionMetaTransfer->setTransactionIdentifier($transactionId);
72
            $transactionMetaTransfer->setRefundAmount($data[static::KEY_AMOUNT]);
73
74
            $braintreeTransactionResponseTransfer = $this->transaction->executeTransaction($transactionMetaTransfer);
75
76
            if ($braintreeTransactionResponseTransfer->getIsSuccess()) {
77
                $refundTransfer = $this->removeShipmentExpense($refundTransfer);
78
            }
79
        }
80
81
        if ($shipmentExpense) {
82
            $refundTransfer->getExpenses()->append($shipmentExpense);
83
        }
84
85
        $this->refundFacade->saveRefund($refundTransfer);
86
    }
87
88
    /**
89
     * @param \Orm\Zed\Sales\Persistence\SpySalesOrderItem[] $salesOrderItems
90
     * @param \Orm\Zed\Sales\Persistence\SpySalesOrder $salesOrderEntity
91
     *
92
     * @return \Generated\Shared\Transfer\RefundTransfer
93
     */
94
    protected function getRefund(array $salesOrderItems, SpySalesOrder $salesOrderEntity): RefundTransfer
95
    {
96
        return $this->refundFacade->calculateRefund($salesOrderItems, $salesOrderEntity);
97
    }
98
99
    /**
100
     * @param \Orm\Zed\Sales\Persistence\SpySalesOrderItem[] $orderItems
101
     *
102
     * @return \ArrayObject
103
     */
104
    protected function getItemsForRefunding(array $orderItems): ArrayObject
105
    {
106
        $itemsForRefunding = [];
107
108
        foreach ($orderItems as $orderItem) {
109
            $itemTransfer = new ItemTransfer();
110
            $itemTransfer->fromArray($orderItem->toArray(), true);
111
            $itemsForRefunding[] = $itemTransfer;
112
        }
113
114
        return $this->getRefundedUniqItems($itemsForRefunding);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getRefunde...ems($itemsForRefunding) returns the type iterable which is incompatible with the type-hinted return ArrayObject.
Loading history...
115
    }
116
117
    /**
118
     * @param \Orm\Zed\Sales\Persistence\SpySalesOrderItem[] $salesOrderItems
119
     * @param \Orm\Zed\Sales\Persistence\SpySalesOrder $salesOrderEntity
120
     * @param \Generated\Shared\Transfer\RefundTransfer $refundTransfer
121
     *
122
     * @return \Generated\Shared\Transfer\TransactionMetaTransfer
123
     */
124
    protected function getTransactionMetaTransfer(array $salesOrderItems, SpySalesOrder $salesOrderEntity, RefundTransfer $refundTransfer): TransactionMetaTransfer
125
    {
126
        $transactionMetaTransfer = new TransactionMetaTransfer();
127
        $transactionMetaTransfer->setIdSalesOrder($salesOrderEntity->getIdSalesOrder());
128
        $transactionMetaTransfer->setRefund($refundTransfer);
129
        $transactionMetaTransfer->setItems($this->getItemsForRefunding($salesOrderItems));
130
131
        return $transactionMetaTransfer;
132
    }
133
134
    /**
135
     * @param \ArrayObject|\Generated\Shared\Transfer\ItemTransfer[] $itemTransfers
136
     *
137
     * @return \ArrayObject|\Generated\Shared\Transfer\ItemTransfer[]
138
     */
139
    protected function getRefundedUniqItems(array $itemTransfers): iterable
140
    {
141
        $uniqItems = [];
142
        $uniqItemIds = [];
143
144
        foreach ($itemTransfers as $itemTransfer) {
145
            if (!in_array($itemTransfer->getIdSalesOrderItem(), $uniqItemIds)) {
146
                $uniqItems[] = $itemTransfer;
147
                $uniqItemIds[] = $uniqItemIds;
148
            }
149
        }
150
151
        $uniqItems = new ArrayObject($uniqItems);
152
153
        return $uniqItems;
154
    }
155
156
    /**
157
     * @param \Generated\Shared\Transfer\TransactionMetaTransfer $transactionMetaTransfer
158
     *
159
     * @return array
160
     */
161
    protected function getOrderItemsGroupedByTransaction(TransactionMetaTransfer $transactionMetaTransfer): array
162
    {
163
        $itemsByTransactions = [];
164
165
        foreach ($transactionMetaTransfer->getItems() as $itemTransfer) {
166
            $paymentBraintreeOrderItemTransfer = $this->braintreeRepository
167
                ->findPaymentBraintreeOrderItemByIdSalesOrderItem($itemTransfer->getIdSalesOrderItem());
168
169
            $paymentBraintreeTransactionSatusLogTransfer = $this->braintreeRepository
170
                ->findPaymentBraintreeTransactionStatusLogQueryByPaymentBraintreeOrderItem($paymentBraintreeOrderItemTransfer->getIdPaymentBraintreeOrderItem());
171
172
            $amount = $itemsByTransactions[$paymentBraintreeTransactionSatusLogTransfer->getTransactionId()][static::KEY_AMOUNT] ?? 0;
173
174
            $itemsByTransactions[$paymentBraintreeTransactionSatusLogTransfer->getTransactionId()] = [
175
                static::KEY_PAYMENT_ID => $paymentBraintreeOrderItemTransfer->getFkPaymentBraintree(),
176
                static::KEY_AMOUNT => $amount + $itemTransfer->getPriceToPayAggregation(),
177
            ];
178
        }
179
180
        return $itemsByTransactions;
181
    }
182
183
    /**
184
     * @param \Generated\Shared\Transfer\RefundTransfer $refundTransfer
185
     *
186
     * @return \Generated\Shared\Transfer\RefundTransfer
187
     */
188
    protected function removeShipmentExpense(RefundTransfer $refundTransfer): RefundTransfer
189
    {
190
        $expenses = [];
191
192
        foreach ($refundTransfer->getExpenses() as $expenseTransfer) {
193
            if ($expenseTransfer->getType() !== ShipmentConstants::SHIPMENT_EXPENSE_TYPE) {
194
                $expenses[] = $expenseTransfer;
195
            }
196
        }
197
198
        $refundTransfer->setExpenses(new ArrayObject($expenses));
199
200
        return $refundTransfer;
201
    }
202
203
    /**
204
     * @param \Generated\Shared\Transfer\RefundTransfer $refundTransfer
205
     *
206
     * @return \Generated\Shared\Transfer\ExpenseTransfer|null
207
     */
208
    protected function getShipmentExpenseTransfer(RefundTransfer $refundTransfer): ?ExpenseTransfer
209
    {
210
        foreach ($refundTransfer->getExpenses() as $expenseTransfer) {
211
            if ($expenseTransfer->getType() === ShipmentConstants::SHIPMENT_EXPENSE_TYPE) {
212
                return $expenseTransfer;
213
            }
214
        }
215
216
        return null;
217
    }
218
}
219