fix pargar bugs

This commit is contained in:
2026-07-21 12:49:08 +03:30
parent ebfeb24e60
commit d43c5e1f25
3 changed files with 179 additions and 2 deletions
@@ -5,6 +5,8 @@ namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Models\Customer;
use App\Models\PargarSyncLog;
use App\Services\ConfigService;
use App\Services\PargarInboundWalletService;
use App\Services\PargarSyncService;
use Illuminate\Http\Request;
@@ -253,6 +255,36 @@ class PargarController extends Controller
return response()->json($result, ($result['ok'] ?? false) ? 200 : 422);
}
public function syncCustomerWallet($customerId)
{
if (! app(ConfigService::class)->isPargarAccounting()) {
return response()->json([
'ok' => false,
'message' => 'حسابداری پرگار فعال نیست',
], 422);
}
$customer = Customer::findOrFail($customerId);
if (trim((string) ($customer->pargar_account_id ?? '')) === '') {
return response()->json([
'ok' => false,
'message' => 'این مشتری کد حساب پرگار ندارد',
], 422);
}
$result = app(PargarInboundWalletService::class)->syncWalletFromPargar($customer);
$appliedDocs = (int) ($result['documents']['applied'] ?? 0);
$appliedMande = (bool) ($result['mande']['applied'] ?? false);
return response()->json([
'ok' => $appliedDocs > 0 || $appliedMande,
'message' => $appliedDocs > 0 || $appliedMande
? 'مانده از پرگار روی کیف اعمال شد'
: ($result['mande']['message'] ?? 'سند قابل‌اعمالی یافت نشد'),
'result' => $result,
], $appliedDocs > 0 || $appliedMande ? 200 : 422);
}
private function uniqueReferralId(): string
{
do {
+146 -2
View File
@@ -122,17 +122,161 @@ class PargarInboundWalletService
return $result;
}
/**
* اسناد ذخیره‌شدهٔ قبلی (قبل از deploy) را از لاگ دوباره اعمال می‌کند.
*
* @return array{applied: int, skipped: int, errors: list<string>, logs: list<int>}
*/
public function replayStoredDocuments(Customer $customer): array
{
$accountId = trim((string) ($customer->pargar_account_id ?? ''));
$logs = PargarSyncLog::query()
->where('type', PargarSyncService::TYPE_DOCUMENT)
->where(function ($q) use ($customer, $accountId) {
$q->where('customer_id', $customer->id);
if ($accountId !== '') {
$q->orWhere('pargar_ref', $accountId);
}
})
->orderBy('id')
->get();
$total = [
'applied' => 0,
'skipped' => 0,
'errors' => [],
'logs' => [],
];
foreach ($logs as $log) {
$data = json_decode((string) $log->data, true);
if (! is_array($data) || empty($data['transactions']) || ! is_array($data['transactions'])) {
continue;
}
$batch = $this->applyDocuments($customer, $data);
$total['applied'] += $batch['applied'];
$total['skipped'] += $batch['skipped'];
$total['errors'] = array_merge($total['errors'], $batch['errors']);
$total['logs'] = array_merge($total['logs'], $batch['logs']);
}
return $total;
}
/**
* آخرین ماندهٔ پرگار را (در صورت اختلاف) یک‌بار روی کیف اعمال می‌کند — فقط با درخواست ادمین.
*
* @return array{applied: bool, gold_delta?: float, rial_delta?: float, message: string}
*/
public function applyLatestMandeDifference(Customer $customer): array
{
$log = PargarSyncLog::query()
->where('customer_id', $customer->id)
->where('type', PargarSyncService::TYPE_MANDE)
->orderByDesc('id')
->first();
if ($log === null) {
return ['applied' => false, 'message' => 'لاگ ماندهٔ پرگار برای این مشتری یافت نشد'];
}
$data = json_decode((string) $log->data, true) ?: [];
if (! empty($data['wallet_applied_from_mande'])) {
return ['applied' => false, 'message' => 'ماندهٔ پرگار قبلاً روی کیف اعمال شده است'];
}
$goldInv = $this->parseNumber($data['GoldInv'] ?? 0);
$rialInv = $this->parseNumber($data['RialInv'] ?? 0);
$ownerType = (int) ($customer->type ?? 2);
$walletInterface = new WalletInterface((int) $customer->id, $ownerType);
$wallet = $walletInterface->wallet;
$goldDiff = $goldInv - (float) ($wallet->gold ?? 0);
$rialDiff = $rialInv - (float) ($wallet->cash ?? 0);
if (abs($goldDiff) < 0.01 && abs($rialDiff) < 1) {
$data['wallet_applied_from_mande'] = true;
$log->data = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
$log->save();
return ['applied' => false, 'message' => 'اختلافی بین ماندهٔ پرگار و کیف اپ نیست'];
}
$input = [
'title' => 'تطبیق ماندهٔ پرگار',
'note' => 'mande-log:' . $log->id,
'expire_at' => now(),
'active' => true,
];
if (abs($goldDiff) >= 0.01) {
$input['gold'] = abs($goldDiff);
}
if (abs($rialDiff) >= 1) {
$input['cash'] = abs($rialDiff);
}
new TransactionInterface(
$walletInterface,
$input,
self::TX_TYPE_PARGAR,
$goldDiff > 0,
$rialDiff > 0
);
$data['wallet_applied_from_mande'] = true;
$data['applied_gold_delta'] = $goldDiff;
$data['applied_rial_delta'] = $rialDiff;
$log->data = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
$log->desc = 'اعمال ماندهٔ پرگار روی کیف اپ';
$log->save();
$this->walletBroadcast->broadcastForCustomer((int) $customer->id, $ownerType);
return [
'applied' => true,
'gold_delta' => $goldDiff,
'rial_delta' => $rialDiff,
'message' => 'ماندهٔ پرگار روی کیف اعمال شد',
];
}
/**
* @return array{
* documents: array{applied: int, skipped: int, errors: list<string>, logs: list<int>},
* mande: array{applied: bool, gold_delta?: float, rial_delta?: float, message: string}
* }
*/
public function syncWalletFromPargar(Customer $customer): array
{
return [
'documents' => $this->replayStoredDocuments($customer),
'mande' => $this->applyLatestMandeDifference($customer),
];
}
public function isDocumentApplied(string $docId): bool
{
if ($docId === '') {
return false;
}
return PargarSyncLog::query()
$logs = PargarSyncLog::query()
->where('type', PargarSyncService::TYPE_DOCUMENT)
->where('pargar_ref', $docId)
->where('sync_status', PargarSyncService::STATUS_SUCCESS)
->exists();
->get(['data']);
foreach ($logs as $log) {
$data = json_decode((string) $log->data, true);
if (($data['wallet_applied'] ?? false) === true) {
return true;
}
}
return false;
}
/**