Skip to content

Commit 940f256

Browse files
committed
payFreeCart fix
1 parent 7e8b750 commit 940f256

File tree

2 files changed

+71
-30
lines changed

2 files changed

+71
-30
lines changed

phpstan.src.baseline.neon

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,11 +175,6 @@ parameters:
175175
count: 2
176176
path: src/Models/Wallet.php
177177

178-
-
179-
message: "#^Parameter \\#1 \\$objects of method Bavix\\\\Wallet\\\\Services\\\\TransferService\\:\\:apply\\(\\) expects non\\-empty\\-array\\<Bavix\\\\Wallet\\\\Internal\\\\Dto\\\\TransferLazyDtoInterface\\>, array\\<int\\<0, max\\>, Bavix\\\\Wallet\\\\Internal\\\\Dto\\\\TransferLazyDtoInterface\\> given\\.$#"
180-
count: 2
181-
path: src/Models/Wallet.php
182-
183178
-
184179
message: "#^Parameter \\#1 \\$related of method Illuminate\\\\Database\\\\Eloquent\\\\Model\\:\\:hasMany\\(\\) expects class\\-string\\<Illuminate\\\\Database\\\\Eloquent\\\\Model\\>, mixed given\\.$#"
185180
count: 6

src/Traits/CartPay.php

Lines changed: 71 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -57,32 +57,49 @@ trait CartPay
5757
*/
5858
public function payFreeCart(CartInterface $cart): array
5959
{
60+
$atomicService = app(AtomicServiceInterface::class);
61+
$eagerLoaderService = app(EagerLoaderServiceInterface::class);
62+
$basketService = app(BasketServiceInterface::class);
63+
$availabilityAssembler = app(AvailabilityDtoAssemblerInterface::class);
64+
$translator = app(TranslatorServiceInterface::class);
65+
$consistencyService = app(ConsistencyServiceInterface::class);
66+
$castService = app(CastServiceInterface::class);
67+
$prepareService = app(PrepareServiceInterface::class);
68+
$assistantService = app(AssistantServiceInterface::class);
69+
$transferService = app(TransferServiceInterface::class);
70+
6071
// Perform the payment for all products in the cart without any payment.
61-
return app(AtomicServiceInterface::class)->block($this, function () use ($cart) {
72+
return $atomicService->block($this, function () use (
73+
$cart,
74+
$eagerLoaderService,
75+
$basketService,
76+
$availabilityAssembler,
77+
$translator,
78+
$consistencyService,
79+
$castService,
80+
$prepareService,
81+
$assistantService,
82+
$transferService
83+
) {
6284
// Get the basket DTO containing the products in the cart.
6385
$basketDto = $cart->getBasketDto();
6486

6587
// Load the wallets for the products in the cart.
66-
$basketService = app(BasketServiceInterface::class);
67-
$availabilityAssembler = app(AvailabilityDtoAssemblerInterface::class);
68-
app(EagerLoaderServiceInterface::class)->loadWalletsByBasket($this, $basketDto);
88+
$eagerLoaderService->loadWalletsByBasket($this, $basketDto);
6989

7090
// Check if the products are available.
7191
if (! $basketService->availability($availabilityAssembler->create($this, $basketDto, false))) {
7292
throw new ProductEnded(
73-
app(TranslatorServiceInterface::class)->get('wallet::errors.product_stock'),
93+
$translator->get('wallet::errors.product_stock'),
7494
ExceptionInterface::PRODUCT_ENDED
7595
);
7696
}
7797

7898
// Check if the wallet has sufficient funds.
79-
app(ConsistencyServiceInterface::class)->checkPotential($this, 0, true);
99+
$consistencyService->checkPotential($this, 0, true);
80100

81101
// Prepare the transfers for the products in the cart.
82102
$transfers = [];
83-
$castService = app(CastServiceInterface::class);
84-
$prepareService = app(PrepareServiceInterface::class);
85-
$assistantService = app(AssistantServiceInterface::class);
86103

87104
// Iterate over the items in the cart.
88105
foreach ($basketDto->items() as $item) {
@@ -104,10 +121,16 @@ public function payFreeCart(CartInterface $cart): array
104121
}
105122

106123
// Ensure that at least one transfer was prepared.
107-
assert($transfers !== []);
124+
// If the above code executes without throwing an exception,
125+
// we can safely assume that at least one transfer was prepared.
126+
// This assertion is used to ensure that this assumption holds true.
127+
// If the assertion fails, it means that the assumption is incorrect,
128+
// which means that the code execution path leading to this assertion
129+
// is incorrect and should be investigated.
130+
assert($transfers !== [], 'At least one transfer must be prepared.');
108131

109132
// Apply the transfers.
110-
return app(TransferServiceInterface::class)->apply($transfers);
133+
return $transferService->apply($transfers);
111134
});
112135
}
113136

@@ -143,17 +166,16 @@ public function safePayCart(CartInterface $cart, bool $force = false): array
143166
* @param bool $force Whether to force the purchase. Defaults to false.
144167
* @return non-empty-array<Transfer> An array of Transfer instances representing the successfully paid items.
145168
*
146-
* @throws ProductEnded
147-
* @throws BalanceIsEmpty
148-
* @throws InsufficientFunds
149-
* @throws RecordNotFoundException
150-
* @throws RecordsNotFoundException
151-
* @throws TransactionFailedException
152-
* @throws ExceptionInterface
169+
* @throws ProductEnded If the product is ended.
170+
* @throws BalanceIsEmpty If the balance of the wallet is empty.
171+
* @throws InsufficientFunds If there are insufficient funds in the wallet.
172+
* @throws RecordNotFoundException If the record is not found.
173+
* @throws RecordsNotFoundException If the records are not found.
174+
* @throws TransactionFailedException If the transaction fails.
175+
* @throws ExceptionInterface If an exception occurs.
153176
*/
154177
public function payCart(CartInterface $cart, bool $force = false): array
155178
{
156-
// Get the required services.
157179
$atomicService = app(AtomicServiceInterface::class);
158180
$basketService = app(BasketServiceInterface::class);
159181
$availabilityAssembler = app(AvailabilityDtoAssemblerInterface::class);
@@ -162,6 +184,8 @@ public function payCart(CartInterface $cart, bool $force = false): array
162184
$prepareService = app(PrepareServiceInterface::class);
163185
$assistantService = app(AssistantServiceInterface::class);
164186
$transferService = app(TransferServiceInterface::class);
187+
$translator = app(TranslatorServiceInterface::class);
188+
$consistencyService = app(ConsistencyServiceInterface::class);
165189

166190
// Wrap the code in an atomic block to ensure consistency.
167191
return $atomicService->block($this, function () use (
@@ -173,7 +197,9 @@ public function payCart(CartInterface $cart, bool $force = false): array
173197
$castService,
174198
$prepareService,
175199
$assistantService,
176-
$transferService
200+
$transferService,
201+
$translator,
202+
$consistencyService
177203
) {
178204
// Get the items in the cart.
179205
$basketDto = $cart->getBasketDto();
@@ -184,7 +210,7 @@ public function payCart(CartInterface $cart, bool $force = false): array
184210
// Check if the products are available.
185211
if (! $basketService->availability($availabilityAssembler->create($this, $basketDto, $force))) {
186212
throw new ProductEnded(
187-
app(TranslatorServiceInterface::class)->get('wallet::errors.product_stock'),
213+
$translator->get('wallet::errors.product_stock'),
188214
ExceptionInterface::PRODUCT_ENDED
189215
);
190216
}
@@ -219,8 +245,12 @@ public function payCart(CartInterface $cart, bool $force = false): array
219245

220246
// Check that the transfers are consistent if the payment is not forced.
221247
if (! $force) {
222-
app(ConsistencyServiceInterface::class)->checkTransfer($transfers);
248+
$consistencyService->checkTransfer($transfers);
223249
}
250+
// Assert that the $transfers array is not empty.
251+
// This is necessary to avoid a potential PHP warning
252+
// when calling $transferService->apply() with an empty array.
253+
assert($transfers !== [], 'The $transfers array must not be empty.');
224254

225255
// Apply the transfers.
226256
return $transferService->apply($transfers);
@@ -298,6 +328,7 @@ public function safeRefundCart(CartInterface $cart, bool $force = false, bool $g
298328
*/
299329
public function refundCart(CartInterface $cart, bool $force = false, bool $gifts = false): bool
300330
{
331+
// Get the required services.
301332
$atomicService = app(AtomicServiceInterface::class);
302333
$basketDto = $cart->getBasketDto();
303334
$eagerLoaderService = app(EagerLoaderServiceInterface::class);
@@ -308,6 +339,7 @@ public function refundCart(CartInterface $cart, bool $force = false, bool $gifts
308339
$consistencyService = app(ConsistencyServiceInterface::class);
309340
$transferService = app(TransferServiceInterface::class);
310341

342+
// Wrap the code in an atomic block to ensure consistency.
311343
return $atomicService->block($this, function () use (
312344
$force,
313345
$gifts,
@@ -320,18 +352,21 @@ public function refundCart(CartInterface $cart, bool $force = false, bool $gifts
320352
$consistencyService,
321353
$transferService
322354
) {
355+
// Load wallets by basket.
323356
$eagerLoaderService->loadWalletsByBasket($this, $basketDto);
357+
358+
// Get already processed transfers.
324359
$transfers = $purchaseService->already($this, $basketDto, $gifts);
325360

361+
// Check if the count of transfers is equal to the total items in the basket.
326362
if (count($transfers) !== $basketDto->total()) {
327363
throw new ModelNotFoundException(
328-
"No query results for model [{$this->transfers()
329-
->getModel()
330-
->getMorphClass()}]",
364+
"No query results for model [{$this->transfers()->getModel()->getMorphClass()}]",
331365
ExceptionInterface::MODEL_NOT_FOUND
332366
);
333367
}
334368

369+
// Prepare transfers for refund.
335370
$index = 0;
336371
$objects = []; // Array to store the prepared transfers.
337372
$transferIds = []; // Array to store the IDs of the transfers.
@@ -354,12 +389,23 @@ public function refundCart(CartInterface $cart, bool $force = false, bool $gifts
354389
}
355390
}
356391

392+
// Perform consistency check if force is false.
357393
if (! $force) {
358394
$consistencyService->checkTransfer($objects);
359395
}
360396

397+
// Ensure there are prepared transfers.
398+
// Assert that the array of prepared transfers is not empty.
399+
// If the array is empty, it means that there are no transfers to be refunded,
400+
// which is not expected and should not happen.
401+
// The assertion is added to ensure that the refund process is not executed
402+
// without any transfers to be refunded.
403+
assert($objects !== [], 'Array of prepared transfers is empty. There are no transfers to be refunded.');
404+
405+
// Apply refunds.
361406
$transferService->apply($objects);
362407

408+
// Update transfer status to refund.
363409
return $transferService
364410
->updateStatusByIds(Transfer::STATUS_REFUND, $transferIds);
365411
});

0 commit comments

Comments
 (0)