fix(server): queue tiny Pargar gold wallet documents instead of skipping them

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-18 17:57:22 +03:30
co-authored by Cursor
parent e158831fd3
commit 0afa01eea9
3 changed files with 121 additions and 9 deletions
+75 -3
View File
@@ -35,6 +35,9 @@ class PargarInboundWalletService
public const KILL_SWITCH_CACHE_KEY = 'pargar_wallet_apply_disabled';
/** شارژ/کسر طلای کیف ادمین + پاداش معرفی/ثبت‌نام */
public const GOLD_DOCUMENT_TX_TYPES = [7, 8];
/** واریز و برداشت ریالی — دو نوعی که باید سند ریالی پرگار داشته باشند */
public const CASH_DOCUMENT_TX_TYPES = [3, 4];
@@ -404,7 +407,9 @@ class PargarInboundWalletService
$goldDiff = $goldInv - $mainGold;
$rialDiff = $rialInv - (float) ($wallet->cash ?? 0);
if (abs($goldDiff) < 0.01 && abs($rialDiff) < 1) {
$goldSame = ! PargarSyncService::isWalletDocAmount($goldDiff);
$rialSame = abs($rialDiff) < 1;
if ($goldSame && $rialSame) {
$data['wallet_applied_from_mande'] = true;
unset($data['mande_skip_reason'], $data['mande_skipped_at']);
$log->data = json_encode($data, JSON_UNESCAPED_UNICODE);
@@ -423,7 +428,7 @@ class PargarInboundWalletService
'expire_at' => now(),
'active' => true,
];
if (abs($goldDiff) >= 0.01) {
if (PargarSyncService::isWalletDocAmount($goldDiff)) {
$input['gold'] = abs($goldDiff);
}
if (abs($rialDiff) >= 1) {
@@ -528,6 +533,32 @@ class PargarInboundWalletService
];
}
$missingGold = $this->unexportedGoldMovement($customer, $lastConfirmedAt);
if ($missingGold !== null) {
$queued = 0;
try {
$queued = app(PargarSyncService::class)->queueMissingGoldDocuments(
$customer,
$missingGold['rows'],
'mande_auto_missing_gold'
);
} catch (\Throwable $e) {
report($e);
}
$suffix = $queued > 0
? ' — سند در صف ثبت قرار گرفت؛ تا تأیید پرگار، مانده اعمال نمی‌شود'
: ' — تا ثبت سند، مانده اعمال نمی‌شود';
return [
'reason' => 'unexported_gold_movement',
'message' => 'حرکت طلایی '
. rtrim(rtrim(number_format($missingGold['amount'], 6, '.', ''), '0'), '.')
. ' گرم هنوز سندی در پرگار ندارد'
. $suffix,
];
}
return null;
}
@@ -562,7 +593,8 @@ class PargarInboundWalletService
->whereNotNull('withdraw_id')
->where('created_at', '>', $since)
->where(function ($q) {
$q->where('cash', '>=', 1)->orWhere('cash', '<=', -1);
$q->where('cash', '>=', PargarSyncService::WALLET_DOC_EPSILON)
->orWhere('cash', '<=', -PargarSyncService::WALLET_DOC_EPSILON);
})
->whereNotExists(function ($q) {
$q->select(DB::raw(1))
@@ -583,6 +615,46 @@ class PargarInboundWalletService
];
}
/**
* شارژ طلا / پاداش که سند پرگارش ساخته نشده (از جمله وزن زیر ۰٫۰۱ گرم).
*
* @return array{amount: float, withdraw_ids: list<int>, rows: \Illuminate\Support\Collection}|null
*/
private function unexportedGoldMovement(Customer $customer, ?Carbon $lastConfirmedAt): ?array
{
$since = $this->cashMovementScanStart($customer, $lastConfirmedAt);
if ($since === null) {
return null;
}
$rows = Transaction::query()
->where('customer_id', $customer->id)
->whereIn('type', self::GOLD_DOCUMENT_TX_TYPES)
->whereNotNull('withdraw_id')
->where('created_at', '>', $since)
->where(function ($q) {
$q->where('gold', '>=', PargarSyncService::WALLET_DOC_EPSILON)
->orWhere('gold', '<=', -PargarSyncService::WALLET_DOC_EPSILON);
})
->whereNotExists(function ($q) {
$q->select(DB::raw(1))
->from('pargar_sync_logs')
->whereColumn('pargar_sync_logs.withdraw_id', 'transactions.withdraw_id')
->where('pargar_sync_logs.type', PargarSyncService::TYPE_WALLET_GOLD);
})
->get(['withdraw_id', 'gold', 'note']);
if ($rows->isEmpty()) {
return null;
}
return [
'amount' => (float) $rows->sum(fn ($row) => abs((float) $row->gold)),
'withdraw_ids' => $rows->pluck('withdraw_id')->map(fn ($id) => (int) $id)->all(),
'rows' => $rows,
];
}
/**
* از کجا دنبال سند جاافتاده بگردیم: بعد از آخرین سند ثبت‌شده، و اگر نبود از
* شروع اتصال همین مشتری به پرگار. تراکنش‌های قبل از اتصال سند ندارند و نباید