all customer from pargar fixing 3
This commit is contained in:
@@ -11,13 +11,15 @@ use Rooyesh\Wallet\interfaces\WalletInterface;
|
||||
use Rooyesh\Wallet\models\Wallet;
|
||||
|
||||
/**
|
||||
* همگامسازی کیف با پرگار — فقط با دکمهٔ ادمین.
|
||||
* همگامسازی کیف با پرگار.
|
||||
*
|
||||
* قواعد سخت:
|
||||
* 1) webhook اسناد (/documents) هرگز کیف را عوض نمیکند — فقط لاگ.
|
||||
* 2) دکمه: دستههای سند را فقط «مصرفشده» علامت میزند (بدون دلتا روی کیف)،
|
||||
* سپس مانده (mande) را بهعنوان منبع حقیقت روی کیف مینشاند.
|
||||
* 3) اعمال تکتک سطرهای تاریخچهٔ پرگار ممنوع است — باعث تورم/تایماوت میشود.
|
||||
* 1) webhook اسناد inbound فقط لاگ میکند؛ کیف را با replay تاریخچه عوض نمیکند.
|
||||
* 2) مانده برای مشتریانی که سند ارسالیِ pending به پرگار ندارند → خودکار روی کیف ست میشود.
|
||||
* 3) اگر سند پنل هنوز در پرگار ثبت نشده، مانده اعمال نمیشود؛ بعد از تأیید ثبت در پرگار،
|
||||
* ماندهٔ جدید خودکار سینک میشود (تا موجودی مشتری بیدلیل کم/زیاد نشود).
|
||||
* 4) دکمهٔ ادمین میتواند force کند.
|
||||
* 5) اعمال تکتک سطرهای تاریخچهٔ پرگار ممنوع است.
|
||||
*/
|
||||
class PargarInboundWalletService
|
||||
{
|
||||
@@ -44,19 +46,36 @@ class PargarInboundWalletService
|
||||
}
|
||||
|
||||
/**
|
||||
* دکمهٔ ادمین:
|
||||
* ۱) علامت مصرف دستههای سند (بدون نوشتن روی کیف)
|
||||
* آیا سندی از پنل در صف ثبت داخل پرگار است؟ (کیف یا سفارش)
|
||||
* در این حالت مانده را اعمال نمیکنیم تا بعد از ثبت سند، ماندهٔ درست بیاید.
|
||||
*/
|
||||
public function hasPendingOutboundToPargar(Customer $customer): bool
|
||||
{
|
||||
return PargarSyncLog::query()
|
||||
->where('customer_id', $customer->id)
|
||||
->whereIn('type', [
|
||||
PargarSyncService::TYPE_WALLET_CASH,
|
||||
PargarSyncService::TYPE_WALLET_GOLD,
|
||||
PargarSyncService::TYPE_ORDER,
|
||||
])
|
||||
->where('sync_status', PargarSyncService::STATUS_PENDING)
|
||||
->exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* دکمهٔ ادمین / همگامسازی خودکار:
|
||||
* ۱) علامت مصرف دستههای سند inbound (بدون نوشتن روی کیف)
|
||||
* ۲) همترازی مانده با آخرین لاگ mande
|
||||
*
|
||||
* @param bool $forceMande ادمین: حتی با سند ارسالی pending
|
||||
* @param bool $auto مسیر خودکار: سند ارسالی pending محترم بماند
|
||||
* @return array{
|
||||
* documents: array{applied: int, skipped: int, batches: int, acknowledged: int, errors: list<string>},
|
||||
* mande: array{applied: bool, gold_delta?: float, rial_delta?: float, message: string}
|
||||
* }
|
||||
*/
|
||||
public function syncWalletFromPargar(Customer $customer, bool $forceMande = false): array
|
||||
public function syncWalletFromPargar(Customer $customer, bool $forceMande = false, bool $auto = false): array
|
||||
{
|
||||
unset($forceMande); // مانده در دکمه همیشه force میشود
|
||||
|
||||
if (self::isApplyFrozen()) {
|
||||
return [
|
||||
'documents' => [
|
||||
@@ -88,11 +107,19 @@ class PargarInboundWalletService
|
||||
}
|
||||
|
||||
try {
|
||||
// ۱) تاریخچهٔ اسناد را روی کیف replay نکن — فقط مصرفشده علامت بزن
|
||||
$this->attachOrphanDocumentLogs($customer);
|
||||
$this->attachOrphanMandeLogs($customer);
|
||||
|
||||
// ۱) تاریخچهٔ اسناد inbound را روی کیف replay نکن — فقط مصرفشده علامت بزن
|
||||
$documents = $this->acknowledgePendingDocumentBatches($customer);
|
||||
|
||||
// ۲) منبع حقیقت موجودی = ماندهٔ پرگار
|
||||
$mande = $this->applyLatestMandeDifference($customer, force: true);
|
||||
// خودکار: اگر سند پنل هنوز در پرگار ثبت نشده → اعمال نکن (force=false)
|
||||
// ادمین: force تا بتوان اصلاح کرد
|
||||
$mande = $this->applyLatestMandeDifference(
|
||||
$customer,
|
||||
force: $auto ? false : ($forceMande || true)
|
||||
);
|
||||
|
||||
if (($documents['acknowledged'] ?? 0) > 0 || ($mande['applied'] ?? false)) {
|
||||
$this->walletBroadcast->broadcastForCustomer(
|
||||
@@ -251,11 +278,11 @@ class PargarInboundWalletService
|
||||
*/
|
||||
public function applyLatestMandeDifference(Customer $customer, bool $force = false): array
|
||||
{
|
||||
// دکمهٔ ادمین (force): حتی با سند pending خروجی، مانده را همتراز کن تا کیف متورم اصلاح شود
|
||||
if (! $force && $this->hasPendingOutboundWalletSync((int) $customer->id)) {
|
||||
// دکمهٔ ادمین (force): حتی با سند pending خروجی، مانده را همتراز کن
|
||||
if (! $force && $this->hasPendingOutboundToPargar($customer)) {
|
||||
return [
|
||||
'applied' => false,
|
||||
'message' => 'سند ارسالی از پنل هنوز تأیید نشده — مانده اعمال نشد تا شارژ برنگردد',
|
||||
'message' => 'سند پنل هنوز در پرگار ثبت نشده — مانده بعد از ثبت سند اعمال میشود',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -374,15 +401,6 @@ class PargarInboundWalletService
|
||||
return round((float) $query->sum('gold'), 3);
|
||||
}
|
||||
|
||||
private function hasPendingOutboundWalletSync(int $customerId): bool
|
||||
{
|
||||
return PargarSyncLog::query()
|
||||
->where('customer_id', $customerId)
|
||||
->whereIn('type', [PargarSyncService::TYPE_WALLET_CASH, PargarSyncService::TYPE_WALLET_GOLD])
|
||||
->where('sync_status', PargarSyncService::STATUS_PENDING)
|
||||
->exists();
|
||||
}
|
||||
|
||||
private function parseNumber(mixed $value): float
|
||||
{
|
||||
if ($value === null || $value === '') {
|
||||
@@ -393,7 +411,7 @@ class PargarInboundWalletService
|
||||
}
|
||||
|
||||
/**
|
||||
* پس از اتصال کد پرگار / claim ثبتنام — همگامسازی کیف در پسزمینه.
|
||||
* همگامسازی خودکار در پسزمینه — بعد از مانده / تأیید سند در پرگار / import.
|
||||
*/
|
||||
public function queueWalletSyncAfterResponse(int $customerId): void
|
||||
{
|
||||
@@ -403,10 +421,8 @@ class PargarInboundWalletService
|
||||
return;
|
||||
}
|
||||
|
||||
$this->attachOrphanMandeLogs($customer);
|
||||
|
||||
try {
|
||||
$this->syncWalletFromPargar($customer, true);
|
||||
$this->syncWalletFromPargar($customer, forceMande: false, auto: true);
|
||||
} catch (\Throwable $e) {
|
||||
Log::warning('Pargar auto wallet sync failed', [
|
||||
'customer_id' => $customerId,
|
||||
@@ -435,4 +451,24 @@ class PargarInboundWalletService
|
||||
})
|
||||
->update(['customer_id' => $customer->id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* اسناد یتیم (قبل از لینک مشتری) را به customer_id وصل میکند.
|
||||
*/
|
||||
public function attachOrphanDocumentLogs(Customer $customer): int
|
||||
{
|
||||
if (! $customer->hasValidPargarAccountId()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$accountId = trim((string) $customer->pargar_account_id);
|
||||
|
||||
return PargarSyncLog::query()
|
||||
->where('type', PargarSyncService::TYPE_DOCUMENT)
|
||||
->where('pargar_ref', $accountId)
|
||||
->where(function ($q) {
|
||||
$q->whereNull('customer_id')->orWhere('customer_id', 0);
|
||||
})
|
||||
->update(['customer_id' => $customer->id]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user