fix transaction bug

This commit is contained in:
2026-08-27 14:01:34 +03:30
parent 17d79c0ce6
commit acf229006e
5 changed files with 353 additions and 15 deletions
+92 -2
View File
@@ -2,10 +2,9 @@
namespace App\Services;
use App\Http\Controllers\Controller;
use App\Models\Price;
use App\Models\Product;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Rooyesh\Wallet\models\Wallet;
/**
@@ -77,6 +76,97 @@ class WalletBalanceService
return round($mainGold + $orphanedGold, 3);
}
/**
* موجودی ریالی مؤثر کیف اصلی =
* cash کیف اصلی + cash کیف‌های legacy محصولات main_wallet_products.
*/
public function effectiveMainWalletCash(int $ownerId, ?int $ownerType = null): float
{
$mainQuery = Wallet::query()
->where('owner', $ownerId)
->whereNull('fund_id')
->whereNull('product_id');
if ($ownerType !== null) {
$mainQuery->where('owner_type', $ownerType);
}
$mainCash = (float) $mainQuery->sum('cash');
$productIds = $this->mainWalletProductIds();
if ($productIds === []) {
return $mainCash;
}
$orphanedQuery = Wallet::query()
->where('owner', $ownerId)
->whereNull('fund_id')
->whereIn('product_id', $productIds);
if ($ownerType !== null) {
$orphanedQuery->where('owner_type', $ownerType);
}
$orphanedCash = (float) $orphanedQuery->sum('cash');
return $mainCash + $orphanedCash;
}
/**
* انتقال موجودی کیف legacy یک محصول متصل به کیف اصلی — مثل goldali (idempotent).
* خرید/فروش بعد از این فقط روی یک کیف (اصلی) کسر/واریز می‌شود.
*/
public function consolidateOrphanedForOwner(int $ownerId, int $ownerType, int $productId): bool
{
if (!$this->configService->isMainWalletProduct($productId)) {
return false;
}
$productWallet = Wallet::query()
->where('owner', $ownerId)
->where('owner_type', $ownerType)
->where('product_id', $productId)
->whereNull('fund_id')
->first();
if (!$productWallet) {
return false;
}
$goldToMove = (float) $productWallet->gold;
$cashToMove = (float) $productWallet->cash;
if (abs($goldToMove) < 1e-12 && abs($cashToMove) < 1e-12) {
return false;
}
DB::transaction(function () use ($ownerId, $ownerType, $productWallet, $goldToMove, $cashToMove) {
$mainWallet = Wallet::query()->firstOrCreate(
[
'owner' => $ownerId,
'owner_type' => $ownerType,
'fund_id' => null,
'product_id' => null,
],
['gold' => 0, 'cash' => 0]
);
$mainWallet->gold = (float) $mainWallet->gold + $goldToMove;
$mainWallet->cash = (float) $mainWallet->cash + $cashToMove;
$mainWallet->save();
$productWallet->gold = 0;
$productWallet->cash = 0;
$productWallet->save();
});
return true;
}
/** ادغام همهٔ کیف‌های legacy محصولات main_wallet_products برای یک کاربر */
public function consolidateAllMainWalletProductsForOwner(int $ownerId, int $ownerType): void
{
foreach ($this->mainWalletProductIds() as $productId) {
$this->consolidateOrphanedForOwner($ownerId, $ownerType, (int) $productId);
}
}
/**
* طلای داخل قلک‌های یک محصول (یا همهٔ محصولات main_wallet اگر $productId=null و فقط main).
*/