fix(wallet): absorb cash left on old owner type
Deposits credited before customer type was set stayed on owner_type 0 and assets ignored them. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -26,6 +26,10 @@ class AssetSummaryService
|
||||
|
||||
public function buildForCustomer(int $customerId, int $ownerType, bool $includeInactiveProducts = false): array
|
||||
{
|
||||
if ($customerId > 0 && $ownerType > 0) {
|
||||
$this->walletBalanceService->absorbMismatchedOwnerTypeBalances($customerId, $ownerType);
|
||||
}
|
||||
|
||||
$catalogQuery = Product::query()->with('file');
|
||||
if (!$includeInactiveProducts) {
|
||||
$catalogQuery->where('active', 1);
|
||||
|
||||
@@ -7,6 +7,8 @@ use App\Models\Price;
|
||||
use App\Models\Product;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Rooyesh\Wallet\interfaces\TransactionInterface;
|
||||
use Rooyesh\Wallet\interfaces\WalletInterface;
|
||||
use Rooyesh\Wallet\models\Wallet;
|
||||
|
||||
/**
|
||||
@@ -17,6 +19,11 @@ use Rooyesh\Wallet\models\Wallet;
|
||||
*/
|
||||
class WalletBalanceService
|
||||
{
|
||||
/** @var array<string, true> */
|
||||
private static array $absorbedOwnerTypes = [];
|
||||
|
||||
private static bool $absorbingOwnerType = false;
|
||||
|
||||
public function __construct(
|
||||
private ConfigService $configService,
|
||||
private BalanceReportService $balanceReportService
|
||||
@@ -161,6 +168,85 @@ class WalletBalanceService
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* ماندهٔ کیفهایی که owner_typeشان با نوع فعلی مشتری یکی نیست
|
||||
* (مثلاً واریز وقتی type هنوز ۰ بوده) به کیف همان محصول/قلک روی نوع فعلی منتقل میشود.
|
||||
*/
|
||||
public function absorbMismatchedOwnerTypeBalances(int $ownerId, int $canonicalType): bool
|
||||
{
|
||||
if ($ownerId <= 0 || $canonicalType <= 0 || self::$absorbingOwnerType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$key = $ownerId.':'.$canonicalType;
|
||||
if (isset(self::$absorbedOwnerTypes[$key])) {
|
||||
return false;
|
||||
}
|
||||
self::$absorbedOwnerTypes[$key] = true;
|
||||
|
||||
$foreign = Wallet::query()
|
||||
->where('owner', $ownerId)
|
||||
->where('owner_type', '!=', $canonicalType)
|
||||
->where(function ($query) {
|
||||
$query->where('cash', '!=', 0)->orWhere('gold', '!=', 0);
|
||||
})
|
||||
->get();
|
||||
|
||||
if ($foreign->isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
self::$absorbingOwnerType = true;
|
||||
try {
|
||||
foreach ($foreign as $row) {
|
||||
DB::transaction(function () use ($row, $ownerId, $canonicalType) {
|
||||
$locked = Wallet::query()->whereKey($row->id)->lockForUpdate()->first();
|
||||
if (!$locked) {
|
||||
return;
|
||||
}
|
||||
|
||||
$cash = (int) round((float) $locked->cash);
|
||||
$gold = (float) $locked->gold;
|
||||
if ($cash === 0 && abs($gold) < 0.0000001) {
|
||||
return;
|
||||
}
|
||||
|
||||
$from = new WalletInterface($ownerId, (int) $locked->owner_type, $locked->fund_id, $locked->product_id);
|
||||
$to = new WalletInterface($ownerId, $canonicalType, $locked->fund_id, $locked->product_id);
|
||||
$note = 'انتقال مانده به کیف اصلی مشتری';
|
||||
|
||||
if ($cash !== 0) {
|
||||
$payload = [
|
||||
'cash' => abs($cash),
|
||||
'gold' => 0,
|
||||
'note' => $note,
|
||||
'expire_at' => now(),
|
||||
'active' => true,
|
||||
];
|
||||
new TransactionInterface($from, $payload, 7, false, $cash < 0);
|
||||
new TransactionInterface($to, $payload, 7, false, $cash > 0);
|
||||
}
|
||||
|
||||
if (abs($gold) >= 0.0000001) {
|
||||
$payload = [
|
||||
'gold' => abs($gold),
|
||||
'cash' => 0,
|
||||
'note' => $note,
|
||||
'expire_at' => now(),
|
||||
'active' => true,
|
||||
];
|
||||
new TransactionInterface($from, $payload, 7, $gold < 0, false);
|
||||
new TransactionInterface($to, $payload, 7, $gold > 0, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
self::$absorbingOwnerType = false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** ادغام همهٔ کیفهای legacy محصولات main_wallet_products برای یک کاربر */
|
||||
public function consolidateAllMainWalletProductsForOwner(int $ownerId, int $ownerType): void
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user