fix some bugs

This commit is contained in:
2026-07-27 21:35:03 +03:30
parent d8256b3f20
commit 2aed828bac
2 changed files with 34 additions and 15 deletions
@@ -272,9 +272,9 @@ class PargarInboundController extends Controller
'tx_count' => is_array($data['transactions'] ?? null) ? count($data['transactions']) : 0, 'tx_count' => is_array($data['transactions'] ?? null) ? count($data['transactions']) : 0,
]); ]);
// به‌محض ورود اسناد → ack + اعمال آخرین مانده // به‌محض ورود اسناد → ack + اعمال آخرین مانده (با تأخیر کوتاه تا webhook مانده قفل را بگیرد)
if ($customer) { if ($customer) {
$this->inboundWallet()->queueWalletSyncAfterResponse((int) $customer->id); $this->inboundWallet()->queueWalletSyncAfterResponse((int) $customer->id, delaySeconds: 2);
} }
return response()->json([ return response()->json([
@@ -356,19 +356,21 @@ class PargarInboundController extends Controller
]), JSON_UNESCAPED_UNICODE), ]), JSON_UNESCAPED_UNICODE),
]); ]);
// سند pending نباشد → مانده را همین‌جا اعمال کن تا تغییر دستی حسابدار فوری روی اپ بنشیند // بدون سند pending → همین‌جا اعمال؛ اگر قفل/خطا بود صف با تأخیر تکرار می‌کند
// (صف afterResponse برای وقتی است که هنوز باید منتظر ثبت سند پنل بمانیم) // (اسناد و مانده اغلب پشت‌سرهم می‌آیند و قفل هم‌زمان شایع است)
$appliedNow = false;
if ($pendingOutbound) { if ($pendingOutbound) {
$this->inboundWallet()->queueWalletSyncAfterResponse((int) $customer->id); $this->inboundWallet()->queueWalletSyncAfterResponse((int) $customer->id, delaySeconds: 2);
$appliedNow = false;
} else { } else {
$appliedNow = false;
try { try {
$syncResult = $this->inboundWallet()->syncWalletFromPargar($customer, forceMande: false, auto: true); $syncResult = $this->inboundWallet()->syncWalletFromPargar($customer, forceMande: false, auto: true);
$appliedNow = (bool) ($syncResult['mande']['applied'] ?? false); $appliedNow = (bool) ($syncResult['mande']['applied'] ?? false);
} catch (\Throwable $e) { } catch (\Throwable $e) {
report($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 : ($appliedNow
? 'مانده دریافت و روی کیف اپ اعمال شد' ? 'مانده دریافت و روی کیف اپ اعمال شد'
: 'مانده دریافت شد؛ همگام‌سازی انجام شد'), : 'مانده دریافت شد؛ همگام‌سازی خودکار در صف است'),
'data' => [ 'data' => [
'awaiting_outbound_confirm' => $pendingOutbound, 'awaiting_outbound_confirm' => $pendingOutbound,
'wallet_applied' => $appliedNow, 'wallet_applied' => $appliedNow,
'auto_sync_queued' => $pendingOutbound, 'auto_sync_queued' => ! $appliedNow,
], ],
]); ]);
} }
+22 -5
View File
@@ -164,6 +164,9 @@ class PargarInboundWalletService
$lock = Cache::lock('pargar-wallet-sync:'.$customer->id, 60); $lock = Cache::lock('pargar-wallet-sync:'.$customer->id, 60);
if (! $lock->get()) { if (! $lock->get()) {
// سند و مانده اغلب پشت‌سرهم می‌آیند؛ اگر قفل اشغال است دوباره صف کن
$this->queueWalletSyncAfterResponse((int) $customer->id, delaySeconds: 3);
return [ return [
'documents' => [ 'documents' => [
'applied' => 0, 'applied' => 0,
@@ -172,7 +175,7 @@ class PargarInboundWalletService
'acknowledged' => 0, 'acknowledged' => 0,
'errors' => ['همگام‌سازی در حال اجراست'], 'errors' => ['همگام‌سازی در حال اجراست'],
], ],
'mande' => ['applied' => false, 'message' => 'همگام‌سازی دیگری برای این مشتری در حال اجراست'], 'mande' => ['applied' => false, 'message' => 'همگام‌سازی دیگری برای این مشتری در حال اجراست — در صف تکرار'],
]; ];
} }
@@ -381,7 +384,7 @@ class PargarInboundWalletService
if (! $force) { if (! $force) {
$block = $this->mandeBlockReason($customer, $log, $data); $block = $this->mandeBlockReason($customer, $log, $data);
if ($block !== null) { if ($block !== null) {
$this->markMandeSkipped($log, $data, $block['reason']); $this->markMandeSkipped($log, $data, $block['reason'], $block['message']);
return ['applied' => false, 'message' => $block['message']]; return ['applied' => false, 'message' => $block['message']];
} }
@@ -402,7 +405,9 @@ class PargarInboundWalletService
if (abs($goldDiff) < 0.01 && abs($rialDiff) < 1) { if (abs($goldDiff) < 0.01 && abs($rialDiff) < 1) {
$data['wallet_applied_from_mande'] = true; $data['wallet_applied_from_mande'] = true;
unset($data['mande_skip_reason'], $data['mande_skipped_at']);
$log->data = json_encode($data, JSON_UNESCAPED_UNICODE); $log->data = json_encode($data, JSON_UNESCAPED_UNICODE);
$log->desc = 'دریافت مانده از پرگار — بدون اختلاف';
$log->save(); $log->save();
return ['applied' => false, 'message' => 'مانده با پرگار یکسان است']; return ['applied' => false, 'message' => 'مانده با پرگار یکسان است'];
@@ -601,7 +606,7 @@ class PargarInboundWalletService
/** /**
* @param array<string, mixed> $data * @param array<string, mixed> $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) { if (($data['mande_skip_reason'] ?? null) === $reason) {
return; return;
@@ -611,6 +616,12 @@ class PargarInboundWalletService
$data['mande_skipped_at'] = now()->toDateTimeString(); $data['mande_skipped_at'] = now()->toDateTimeString();
$log->data = json_encode($data, JSON_UNESCAPED_UNICODE); $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(); $log->save();
} }
@@ -625,10 +636,16 @@ class PargarInboundWalletService
/** /**
* همگام‌سازی خودکار در پس‌زمینه — بعد از مانده / تأیید سند در پرگار / import. * همگام‌سازی خودکار در پس‌زمینه — بعد از مانده / تأیید سند در پرگار / 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); $customer = Customer::find($customerId);
if ($customer === null || ! $customer->hasValidPargarAccountId()) { if ($customer === null || ! $customer->hasValidPargarAccountId()) {
return; return;