some edits for pargar

This commit is contained in:
2026-07-27 15:44:21 +03:30
parent a849150339
commit d4fba50845
2 changed files with 30 additions and 100 deletions
+9 -95
View File
@@ -22,11 +22,11 @@ use Rooyesh\Wallet\models\Transaction;
* محصولات خارج از کیف اصلی هرگز از مانده اثر نمی‌گیرند.
* 3) ماندهٔ کهنه دور ریخته می‌شود، نه معوق: اگر سند ما هنوز pending باشد یا snapshot
* پیش از ثبت سند گرفته شده باشد، اعمال نمی‌شود و منتظر ماندهٔ بعدی می‌مانیم.
* 4) اعمال فقط با دو snapshot پیاپیِ هم‌مقدار — تا مانده‌ای که وسط ثبت اسناد گرفته شده
* موجودی مشتری را عقب نبرد.
* 4) ماندهٔ تازهٔ پرگار (از جمله صفر/تغییر دستی حسابدار) بلافاصله اعمال می‌شود —
* دیگر منتظر دو snapshot یکسان یا بلوک صفر نمی‌مانیم.
* 5) اگر واریز/برداشت ریالی‌ای اصلاً سند پرگار نداشته باشد، مانده اعمال نمی‌شود؛
* پرگار از آن پول خبر ندارد و اعمال مانده موجودی مشتری را پاک می‌کند.
* 6) دکمهٔ ادمین با force می‌تواند همهٔ گیت‌های بالا را رد کند (ابزار اصلاح دستی).
* 6) دکمهٔ ادمین با force می‌تواند گیت‌های سند pending را رد کند (ابزار اصلاح دستی).
*/
class PargarInboundWalletService
{
@@ -461,9 +461,12 @@ class PargarInboundWalletService
}
/**
* ماندهٔ پرگار فقط وقتی معتبر است که همهٔ اسناد ما در پرگار ثبت شده باشند و
* snapshot بعد از آن ثبت گرفته شده باشد. اعمال ماندهٔ قدیمی یعنی برگرداندن
* موجودی مشتری به قبل از سند — همان «وزن/ریالم کم شد».
* ماندهٔ پرگار منبع حقیقت است — از جمله تغییر دستی حسابدار در پنل پرگار.
* فقط وقتی نگه می‌داریم که هنوز سندِ ساخته‌شدهٔ خودمان در پرگار ثبت نشده باشد؛
* وگرنه موجودی مشتری به قبل از آن سند برمی‌گردد («وزن/ریالم کم شد»).
*
* دیگر منتظر «دو snapshot یکسان» یا بلوک صفر نمی‌مانیم: حسابدار ممکن است عمداً
* مانده را صفر/عوض کند و باید همان لحظه روی اپ بنشیند.
*
* @param array<string, mixed> $data
* @return array{reason: string, message: string}|null null یعنی معتبر
@@ -499,28 +502,6 @@ class PargarInboundWalletService
];
}
$previous = $this->previousComparableMande($log, $lastConfirmedAt);
if ($previous === null) {
return [
'reason' => 'awaiting_second_snapshot',
'message' => 'منتظر ماندهٔ بعدی برای تأیید پایداری',
];
}
if (! $this->mandeValuesMatch($data, $previous)) {
return [
'reason' => 'unstable_snapshot',
'message' => 'ماندهٔ پرگار هنوز در حال تغییر است — منتظر مقدار پایدار',
];
}
if ($this->isSuspiciousZeroSnapshot($customer, $data)) {
return [
'reason' => 'zero_snapshot',
'message' => 'ماندهٔ پرگار صفر است ولی کیف مشتری خالی نیست — برای جلوگیری از صفر شدن اشتباه اعمال نشد',
];
}
return null;
}
@@ -595,29 +576,6 @@ class PargarInboundWalletService
return $lastConfirmedAt ?? $integrationStart;
}
/**
* ماندهٔ صفرِ هر دو فیلد برای مشتری‌ای که کیفش خالی نیست، تقریباً همیشه یعنی
* پرگار حساب را پیدا نکرده — نه اینکه مشتری تسویه کرده باشد.
*
* @param array<string, mixed> $data
*/
private function isSuspiciousZeroSnapshot(Customer $customer, array $data): bool
{
$goldInv = $this->parseNumber($data['GoldInv'] ?? 0);
$rialInv = $this->parseNumber($data['RialInv'] ?? 0);
if (abs($goldInv) >= 0.001 || abs($rialInv) >= 1) {
return false;
}
$ownerType = (int) ($customer->type ?? 2);
$mainGold = app(WalletBalanceService::class)
->effectiveMainWalletGold((int) $customer->id, $ownerType);
$cash = (float) ((new WalletInterface((int) $customer->id, $ownerType))->wallet->cash ?? 0);
return abs($mainGold) >= 0.01 || abs($cash) >= 1;
}
/**
* آخرین لحظه‌ای که پرگار یکی از اسناد ما را ثبت کرده است.
*/
@@ -640,50 +598,6 @@ class PargarInboundWalletService
return $value !== null ? Carbon::parse($value) : null;
}
/**
* ماندهٔ قبلی که آن هم بعد از ثبت آخرین سند گرفته شده باشد.
*
* @return array<string, mixed>|null
*/
private function previousComparableMande(PargarSyncLog $log, ?Carbon $lastConfirmedAt): ?array
{
$query = PargarSyncLog::query()
->where('customer_id', $log->customer_id)
->where('type', PargarSyncService::TYPE_MANDE)
->where('id', '<', $log->id)
->orderByDesc('id');
if ($lastConfirmedAt !== null) {
$query->where('created_at', '>', $lastConfirmedAt);
}
$previous = $query->first();
if ($previous === null) {
return null;
}
$data = json_decode((string) $previous->data, true);
return is_array($data) ? $data : null;
}
/**
* @param array<string, mixed> $current
* @param array<string, mixed> $previous
*/
private function mandeValuesMatch(array $current, array $previous): bool
{
$goldMatch = abs(
$this->parseNumber($current['GoldInv'] ?? 0) - $this->parseNumber($previous['GoldInv'] ?? 0)
) < 0.001;
$rialMatch = abs(
$this->parseNumber($current['RialInv'] ?? 0) - $this->parseNumber($previous['RialInv'] ?? 0)
) < 1;
return $goldMatch && $rialMatch;
}
/**
* @param array<string, mixed> $data
*/