From 1ce2e73ea9900ba54892b4f4a9d4766bce80a1a1 Mon Sep 17 00:00:00 2001 From: adonis Date: Thu, 2 Jul 2026 21:24:26 +0330 Subject: [PATCH] product time changed 5 --- .../Single/SingleOrderController.php | 99 ++++++++++--------- app/Services/MontzarService.php | 22 ++++- 2 files changed, 70 insertions(+), 51 deletions(-) diff --git a/app/Http/Controllers/Single/SingleOrderController.php b/app/Http/Controllers/Single/SingleOrderController.php index ec9723a..5eed59f 100644 --- a/app/Http/Controllers/Single/SingleOrderController.php +++ b/app/Http/Controllers/Single/SingleOrderController.php @@ -268,6 +268,9 @@ class SingleOrderController extends Controller if ($wallet->cash < $data['payment_amount']) { throw new UnprocessableEntityHttpException('موجودی شما کمتر از میزان سفارش است'); } + + $this->assertProviderOrderAccepted($data); + $data['order'] = $order = Order::create($data); $abshode = $this->resolveAbshodeProductContext($data); $productId = (int) ($data['product_id'] ?? $abshode['id'] ?? 0); @@ -285,9 +288,9 @@ class SingleOrderController extends Controller $buyTransaction['note'] = 'product_id:' . $productId; } new TransactionInterface($wallet_interface, $buyTransaction, 1, true, false); + $this->finalizeProviderOrder($data); $response['1'] = 2; - //send to provider - $this->sendProviderOrder($data, $wallet_interface, (int) $data['direction']); + return $response; } @@ -462,6 +465,9 @@ class SingleOrderController extends Controller if ($wallet->gold < $goldDebit) { throw new UnprocessableEntityHttpException($this->insufficientGoldBalanceMessage($data)); } + + $this->assertProviderOrderAccepted($data); + $data['order'] = $order = Order::create($data); $abshode = $this->resolveAbshodeProductContext($data); $productId = (int) ($data['product_id'] ?? $abshode['id'] ?? 0); @@ -478,10 +484,7 @@ class SingleOrderController extends Controller $sellTransaction['note'] = 'product_id:' . $productId; } new TransactionInterface($wallet_interface, $sellTransaction, 2, false, true); - - //send to Goldir - $this->sendProviderOrder($data, $wallet_interface, (int) $data['direction']); - + $this->finalizeProviderOrder($data); } private function processSellTransactionProduct(&$data, $wallet, $wallet_interface) @@ -689,54 +692,54 @@ class SingleOrderController extends Controller $this->send($customer->mobile, $customerMessage); } - private function sendProviderOrder(array &$data, $wallet_interface, int $direction) + private function assertProviderOrderAccepted(array &$data): void { - if (app(\App\Services\ConfigService::class)->usesMontzarPricing()) { - try { - return app(MontzarService::class)->sendOrder($data); - } catch (UnprocessableEntityHttpException $e) { - $this->rollbackProviderFailedOrder($data, $wallet_interface, $direction); - throw $e; - } catch (\Throwable $e) { - $this->rollbackProviderFailedOrder($data, $wallet_interface, $direction); - - throw new UnprocessableEntityHttpException( - 'خطا در ثبت سفارش ارائه دهنده: ' . $e->getMessage() - ); - } - } - - return null; - } - - private function rollbackProviderFailedOrder(array $data, $wallet_interface, int $direction): void - { - $order = $data['order'] ?? null; - - if (!$order instanceof Order) { + if (!app(ConfigService::class)->usesMontzarPricing()) { return; } - if ($direction === 1) { - new TransactionInterface($wallet_interface, [ - 'cash' => $data['payment_amount'], - 'gold' => $data['amount'], - 'expire_at' => now(), - 'active' => true, - 'order_id' => $order->id, - 'start_at' => now(), - ], 2, false, true); - } else { - new TransactionInterface($wallet_interface, [ - 'gold' => $data['amount'], - 'cash' => $data['total_price'], - 'expire_at' => now(), - 'active' => true, - 'order_id' => $order->id, - ], 1, true, false); + $this->assertNoRecentDuplicateLocalOrder($data); + + $data['_montzar_parsed'] = app(MontzarService::class)->submitOrder($data); + } + + private function finalizeProviderOrder(array &$data): void + { + if (!app(ConfigService::class)->usesMontzarPricing()) { + return; } - $order->delete(); + $parsed = $data['_montzar_parsed'] ?? null; + if (!is_array($parsed)) { + return; + } + + app(MontzarService::class)->applyParsedOrder($data, $parsed); + unset($data['_montzar_parsed']); + } + + private function assertNoRecentDuplicateLocalOrder(array $data): void + { + $customerId = (int) ($data['customer_id'] ?? 0); + if ($customerId <= 0) { + return; + } + + $direction = (int) ($data['direction'] ?? 0); + $amount = round((float) ($data['amount'] ?? 0), 6); + $windowSeconds = 20; + + $duplicate = Order::where('customer_id', $customerId) + ->where('direction', $direction) + ->where('created_at', '>=', now()->subSeconds($windowSeconds)) + ->whereRaw('ROUND(amount, 6) = ?', [$amount]) + ->exists(); + + if ($duplicate) { + throw new UnprocessableEntityHttpException( + 'در حال حاضر سفارش مشابه ثبت شده است. لطفاً چند ثانیه دیگر تلاش کنید.' + ); + } } public function storeBackUp(Request $request) diff --git a/app/Services/MontzarService.php b/app/Services/MontzarService.php index 7732452..591dd5d 100644 --- a/app/Services/MontzarService.php +++ b/app/Services/MontzarService.php @@ -103,7 +103,12 @@ class MontzarService return $response; } - public function sendOrder(array &$data) + /** + * ثبت سفارش در منتظر — قبل از ایجاد سفارش/تراکنش محلی صدا زده می‌شود. + * + * @return array{ok: bool, provider_id: int|null, error: string|null} + */ + public function submitOrder(array &$data): array { $payload = $this->makeOrderPayload($data); $token = $this->getToken(); @@ -147,9 +152,20 @@ class MontzarService ); } - $this->syncOrderWithMontzarResponse($data, $parsed); + return $parsed; + } - return $body; + public function applyParsedOrder(array &$data, array $parsed): void + { + $this->syncOrderWithMontzarResponse($data, $parsed); + } + + public function sendOrder(array &$data) + { + $parsed = $this->submitOrder($data); + $this->applyParsedOrder($data, $parsed); + + return null; } private function makeOrderPayload(array $data): array