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
@@ -32,7 +32,7 @@ class CustomerController extends SuperController
// (referral_to_id در DB هست؛ بدون with فقط کد خام دیده نمی‌شود و UI از userInfo.referral می‌خواند)
$this->with = ['referral'];
$this->select = ['*'];
$search=['name','mobile'];
$search = ['name', 'mobile', 'moshtari_code', 'pargar_account_id', 'referral_id', 'n_code', 'id'];
$this->query = Customer::with($this->with,'wallet')->where('is_archive',false)->where('type',1);
// $this->query = Customer::where('is_archive',false)->get();
parent::__construct(Customer::class, $this->with, $this->select, 'customer', $this->query, $search);
@@ -318,12 +318,35 @@ class CartController extends Controller
'title' => "سبد خرید"
], 12, false, false);
foreach ($cart->items as $item) {
$wallet_interface_product = new WalletInterface(auth('customer')->id(), auth('customer')->user()->type, null, $item->product_id);
$wallet_interface_product->wallet->gold = intval($wallet_interface_product->wallet->gold);
$wallet_interface_product->wallet->save();
$productId = (int) $item->product_id;
$customerId = (int) auth('customer')->id();
$ownerType = (int) auth('customer')->user()->type;
if (self::isMainWalletProduct($productId)) {
app(\App\Services\WalletBalanceService::class)->consolidateOrphanedForOwner(
$customerId,
$ownerType,
$productId
);
}
$wallet_interface_product = new WalletInterface(
$customerId,
$ownerType,
null,
self::effectiveProductWalletId($productId)
);
$product = Product::query()->find($productId);
if (
$wallet_interface_product->wallet
&& $wallet_interface_product->wallet->product_id !== null
&& $product
&& self::isCountBasedProduct(self::productUnitPayload($product))
) {
$wallet_interface_product->wallet->gold = intval($wallet_interface_product->wallet->gold);
$wallet_interface_product->wallet->save();
}
new TransactionInterface($wallet_interface_product, [
"gold" => $item->quantity,
"product_id" => $item->product_id,
"product_id" => $productId,
'expire_at' => now(),
'active' => true,
'order_id' => $order->id,
@@ -29,6 +29,7 @@ use App\Services\ProductPriceService;
use App\Services\ProductDisplayPriceService;
use App\Services\FormulaPriceService;
use App\Services\ReferralGiftService;
use App\Services\WalletBalanceService;
use App\Services\WalletBroadcastService;
@@ -108,8 +109,7 @@ class SingleOrderController extends Controller
$data['payment_remind'] = 0;
$data['fee'] = $data['difference'];
$ownerType = (int) ($customer?->type ?? 2);
$wallet_interface = new WalletInterface($data['customer_id'], $ownerType);
$wallet = $wallet_interface->wallet;
[$wallet, $wallet_interface] = $this->resolveOrderWallet((int) $data['customer_id'], $customer, $ownerType);
if (!$wallet) {
throw new UnprocessableEntityHttpException('کیف پول یافت نشد.');
}
@@ -796,29 +796,86 @@ class SingleOrderController extends Controller
], 1, false, false);
}
/**
* کیف سفارش: مثل goldali — اول legacyهای main_wallet_products روی کیف اصلی ادغام،
* بعد موجودی مؤثر (جمع) روی $wallet برای چک خرید/فروش.
*
* @return array{0: Wallet|null, 1: WalletInterface}
*/
private function resolveOrderWallet(int $customerId, ?Customer $customer = null, ?int $ownerType = null): array
{
$walletOwnerType = $ownerType
?? (int) ($customer?->type ?? 2);
$balanceService = app(WalletBalanceService::class);
$balanceService->consolidateAllMainWalletProductsForOwner($customerId, $walletOwnerType);
$walletInterface = new WalletInterface($customerId, $walletOwnerType);
$wallet = Wallet::query()
->where('owner', $customerId)
->where('owner_type', $walletOwnerType)
->whereNull('fund_id')
->whereNull('product_id')
->first();
if ($wallet === null) {
$wallet = $walletInterface->wallet;
} else {
$wallet->refresh();
}
if ($wallet && $balanceService->mainWalletProductIds() !== []) {
$wallet->cash = $balanceService->effectiveMainWalletCash($customerId, $walletOwnerType);
$wallet->gold = $balanceService->effectiveMainWalletGold($customerId, $walletOwnerType);
}
return [$wallet, $walletInterface];
}
/**
* کیف مؤثر محصول برای تراکنش سفارش.
* محصولات متصل به کیف اصلی (main_wallet_products) مستقیماً روی کیف اصلی می‌نشینند.
*/
private function productWalletInterface(int $productId): WalletInterface
{
$customer = auth('customer')->user();
$customerId = (int) ($customer?->id ?? 0);
$walletOwnerType = (int) ($customer?->type ?? 2);
if ($customerId > 0 && self::isMainWalletProduct($productId)) {
app(WalletBalanceService::class)->consolidateOrphanedForOwner(
$customerId,
$walletOwnerType,
$productId
);
}
return new WalletInterface(
auth('customer')->id(),
auth('customer')->user()->type,
$customerId,
$walletOwnerType,
null,
self::effectiveProductWalletId($productId)
);
}
/** رفتار قدیمیِ رُند کردن موجودی فقط برای کیف خود محصول؛ کیف اصلی هرگز رُند نمی‌شود */
/**
* رُند به عدد صحیح فقط برای محصول تعدادی (سکه/شمش قطعه‌ای).
* روی طلای وزنی/اعشاری و کیف اصلی هرگز اعمال نشود — همان باگ از دست رفتن ۰.۹۱۳ و ۰.۳۹۱.
*/
private function normalizeProductWalletGold(WalletInterface $walletInterface): void
{
if ($walletInterface->wallet->product_id === null) {
$wallet = $walletInterface->wallet;
if (!$wallet || $wallet->product_id === null) {
return;
}
$walletInterface->wallet->gold = intval($walletInterface->wallet->gold);
$walletInterface->wallet->save();
$product = Product::query()->find((int) $wallet->product_id);
if (!$product || !self::isCountBasedProduct(self::productUnitPayload($product))) {
return;
}
$wallet->gold = intval($wallet->gold);
$wallet->save();
}
private function give_order_reward(&$data, $wallet, $wallet_interface)