From 2aed828bace332f8ddebf5a7c760eb852530d319 Mon Sep 17 00:00:00 2001 From: adonis Date: Mon, 27 Jul 2026 21:35:03 +0330 Subject: [PATCH] fix some bugs --- .../Pargar/PargarInboundController.php | 22 ++++++++------- app/Services/PargarInboundWalletService.php | 27 +++++++++++++++---- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/app/Http/Controllers/Pargar/PargarInboundController.php b/app/Http/Controllers/Pargar/PargarInboundController.php index 8ba79bb..986c524 100644 --- a/app/Http/Controllers/Pargar/PargarInboundController.php +++ b/app/Http/Controllers/Pargar/PargarInboundController.php @@ -272,9 +272,9 @@ class PargarInboundController extends Controller 'tx_count' => is_array($data['transactions'] ?? null) ? count($data['transactions']) : 0, ]); - // به‌محض ورود اسناد → ack + اعمال آخرین مانده + // به‌محض ورود اسناد → ack + اعمال آخرین مانده (با تأخیر کوتاه تا webhook مانده قفل را بگیرد) if ($customer) { - $this->inboundWallet()->queueWalletSyncAfterResponse((int) $customer->id); + $this->inboundWallet()->queueWalletSyncAfterResponse((int) $customer->id, delaySeconds: 2); } return response()->json([ @@ -356,19 +356,21 @@ class PargarInboundController extends Controller ]), JSON_UNESCAPED_UNICODE), ]); - // سند pending نباشد → مانده را همین‌جا اعمال کن تا تغییر دستی حسابدار فوری روی اپ بنشیند - // (صف afterResponse برای وقتی است که هنوز باید منتظر ثبت سند پنل بمانیم) + // بدون سند pending → همین‌جا اعمال؛ اگر قفل/خطا بود صف با تأخیر تکرار می‌کند + // (اسناد و مانده اغلب پشت‌سرهم می‌آیند و قفل هم‌زمان شایع است) + $appliedNow = false; if ($pendingOutbound) { - $this->inboundWallet()->queueWalletSyncAfterResponse((int) $customer->id); - $appliedNow = false; + $this->inboundWallet()->queueWalletSyncAfterResponse((int) $customer->id, delaySeconds: 2); } else { - $appliedNow = false; try { $syncResult = $this->inboundWallet()->syncWalletFromPargar($customer, forceMande: false, auto: true); $appliedNow = (bool) ($syncResult['mande']['applied'] ?? false); } catch (\Throwable $e) { report($e); - $this->inboundWallet()->queueWalletSyncAfterResponse((int) $customer->id); + } + + if (! $appliedNow) { + $this->inboundWallet()->queueWalletSyncAfterResponse((int) $customer->id, delaySeconds: 3); } } @@ -378,11 +380,11 @@ class PargarInboundController extends Controller ? 'مانده ذخیره شد؛ بعد از ثبت سند در پرگار خودکار سینک می‌شود' : ($appliedNow ? 'مانده دریافت و روی کیف اپ اعمال شد' - : 'مانده دریافت شد؛ همگام‌سازی انجام شد'), + : 'مانده دریافت شد؛ همگام‌سازی خودکار در صف است'), 'data' => [ 'awaiting_outbound_confirm' => $pendingOutbound, 'wallet_applied' => $appliedNow, - 'auto_sync_queued' => $pendingOutbound, + 'auto_sync_queued' => ! $appliedNow, ], ]); } diff --git a/app/Services/PargarInboundWalletService.php b/app/Services/PargarInboundWalletService.php index 8953730..e4a025b 100644 --- a/app/Services/PargarInboundWalletService.php +++ b/app/Services/PargarInboundWalletService.php @@ -164,6 +164,9 @@ class PargarInboundWalletService $lock = Cache::lock('pargar-wallet-sync:'.$customer->id, 60); if (! $lock->get()) { + // سند و مانده اغلب پشت‌سرهم می‌آیند؛ اگر قفل اشغال است دوباره صف کن + $this->queueWalletSyncAfterResponse((int) $customer->id, delaySeconds: 3); + return [ 'documents' => [ 'applied' => 0, @@ -172,7 +175,7 @@ class PargarInboundWalletService 'acknowledged' => 0, 'errors' => ['همگام‌سازی در حال اجراست'], ], - 'mande' => ['applied' => false, 'message' => 'همگام‌سازی دیگری برای این مشتری در حال اجراست'], + 'mande' => ['applied' => false, 'message' => 'همگام‌سازی دیگری برای این مشتری در حال اجراست — در صف تکرار'], ]; } @@ -381,7 +384,7 @@ class PargarInboundWalletService if (! $force) { $block = $this->mandeBlockReason($customer, $log, $data); if ($block !== null) { - $this->markMandeSkipped($log, $data, $block['reason']); + $this->markMandeSkipped($log, $data, $block['reason'], $block['message']); return ['applied' => false, 'message' => $block['message']]; } @@ -402,7 +405,9 @@ class PargarInboundWalletService if (abs($goldDiff) < 0.01 && abs($rialDiff) < 1) { $data['wallet_applied_from_mande'] = true; + unset($data['mande_skip_reason'], $data['mande_skipped_at']); $log->data = json_encode($data, JSON_UNESCAPED_UNICODE); + $log->desc = 'دریافت مانده از پرگار — بدون اختلاف'; $log->save(); return ['applied' => false, 'message' => 'مانده با پرگار یکسان است']; @@ -601,7 +606,7 @@ class PargarInboundWalletService /** * @param array $data */ - private function markMandeSkipped(PargarSyncLog $log, array $data, string $reason): void + private function markMandeSkipped(PargarSyncLog $log, array $data, string $reason, ?string $message = null): void { if (($data['mande_skip_reason'] ?? null) === $reason) { return; @@ -611,6 +616,12 @@ class PargarInboundWalletService $data['mande_skipped_at'] = now()->toDateTimeString(); $log->data = json_encode($data, JSON_UNESCAPED_UNICODE); + // تا UI روی «در حال اعمال» گیر نکند + if ($message !== null && $message !== '') { + $log->desc = mb_substr($message, 0, 250); + } elseif (is_string($log->desc) && str_contains($log->desc, 'در حال اعمال')) { + $log->desc = mb_substr('مانده نگه‌داشته شد — '.$reason, 0, 250); + } $log->save(); } @@ -625,10 +636,16 @@ class PargarInboundWalletService /** * همگام‌سازی خودکار در پس‌زمینه — بعد از مانده / تأیید سند در پرگار / import. + * + * @param int $delaySeconds تأخیر داخل afterResponse (برای رد شدن از قفل webhook قبلی) */ - public function queueWalletSyncAfterResponse(int $customerId): void + public function queueWalletSyncAfterResponse(int $customerId, int $delaySeconds = 0): void { - dispatch(function () use ($customerId) { + dispatch(function () use ($customerId, $delaySeconds) { + if ($delaySeconds > 0) { + sleep(min($delaySeconds, 10)); + } + $customer = Customer::find($customerId); if ($customer === null || ! $customer->hasValidPargarAccountId()) { return;