fix bug of pargar 4

This commit is contained in:
2026-07-26 21:17:57 +03:30
parent a9c0fb09e6
commit a849150339
3 changed files with 105 additions and 0 deletions
+95
View File
@@ -7,6 +7,7 @@ use App\Models\Order;
use App\Models\PargarSyncLog;
use App\Models\Product;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
@@ -405,6 +406,100 @@ class PargarSyncService
];
}
/**
* شناسه‌ای که سند با آن در GET /pargar/orders بیرون می‌رود.
*/
public function outboundExportId(PargarSyncLog $log): string
{
if ($log->type === self::TYPE_ORDER) {
return (string) ($log->order_id ?? $log->id);
}
$withdrawId = (int) ($log->withdraw_id ?? 0);
return $withdrawId > 0 ? 'W-'.$withdrawId : 'WLOG-'.$log->id;
}
/**
* اسنادی که در نوبت GET /pargar/orders هستند و پرگار هنوز تأییدشان نکرده است.
*
* تا وقتی این‌ها معلق‌اند، ماندهٔ پرگارِ همان مشتری روی کیف اعمال نمی‌شود؛ پس باید
* در پنل دیده شوند، نه اینکه با شکایت مشتری کشف شوند.
*
* @return array{
* count: int,
* customers: int,
* waited_minutes: int,
* oldest_at: string|null,
* last_confirmed_at: string|null,
* threshold_minutes: int,
* rows: list<array<string, mixed>>
* }
*/
public function stuckOutboundDocuments(int $olderThanMinutes = 15, int $limit = 50): array
{
$threshold = now()->subMinutes(max(0, $olderThanMinutes));
$logs = PargarSyncLog::with('customer')
->whereIn('type', [self::TYPE_ORDER, self::TYPE_WALLET_CASH, self::TYPE_WALLET_GOLD])
->where('sync_status', self::STATUS_PENDING)
->where('created_at', '<=', $threshold)
->where(function ($q) {
// سند کیف تا وقتی pending است در هر fetch فرستاده می‌شود؛ سفارش فقط
// وقتی هنوز در نوبت خروجی است (sts=2 و تأییدنشده).
$q->whereIn('type', [self::TYPE_WALLET_CASH, self::TYPE_WALLET_GOLD])
->orWhereExists(function ($sub) {
$sub->select(DB::raw(1))
->from('orders')
->whereColumn('orders.id', 'pargar_sync_logs.order_id')
->where('orders.sts', 2)
->whereNull('orders.pargar_confirmed_at');
});
})
->orderBy('id')
->get();
$oldest = $logs->first()?->created_at;
return [
'count' => $logs->count(),
'customers' => $logs->pluck('customer_id')->filter()->unique()->count(),
'waited_minutes' => $oldest ? (int) $oldest->diffInMinutes(now()) : 0,
'oldest_at' => $oldest?->toDateTimeString(),
'last_confirmed_at' => $this->lastOutboundConfirmedAt(),
'threshold_minutes' => max(0, $olderThanMinutes),
'rows' => $logs->take($limit)->map(fn (PargarSyncLog $log) => [
'id' => (int) $log->id,
'export_id' => $this->outboundExportId($log),
'type' => (string) $log->type,
'amount' => $log->amount === null ? null : (float) $log->amount,
'desc' => (string) ($log->desc ?? ''),
'order_id' => $log->order_id ? (int) $log->order_id : null,
'withdraw_id' => $log->withdraw_id ? (int) $log->withdraw_id : null,
'customer_id' => $log->customer_id ? (int) $log->customer_id : null,
'customer_name' => $log->customer?->name,
'customer_mobile' => $log->customer?->mobile,
'pargar_account_id' => $log->customer?->pargar_account_id,
'created_at' => $log->created_at?->toDateTimeString(),
'waited_minutes' => $log->created_at ? (int) $log->created_at->diffInMinutes(now()) : 0,
])->values()->all(),
];
}
/** آخرین باری که پرگار سندی از پنل را تأیید کرده است */
private function lastOutboundConfirmedAt(): ?string
{
$query = PargarSyncLog::query()
->whereIn('type', [self::TYPE_ORDER, self::TYPE_WALLET_CASH, self::TYPE_WALLET_GOLD])
->where('sync_status', self::STATUS_SUCCESS);
$confirmedAt = PargarSyncLog::hasConfirmedAtColumn()
? $query->clone()->max('confirmed_at')
: null;
return $confirmedAt ?: $query->max('updated_at');
}
public function retry(PargarSyncLog $log): array
{
if (! $this->isFailed($log) && ! empty($log->pargar_ref)) {