where('delivery_time', '<=', now()) ->pluck('id'); if ($orderIds->isEmpty()) return; foreach ($orderIds as $orderId) { DB::beginTransaction(); try { $affected = OptionOrder::where('id', $orderId)->where('status', 0) ->update(['status' => 99]); if ($affected === 0) { DB::rollBack(); continue; } $order = OptionOrder::lockForUpdate()->find($orderId); $pair = OptionPair::find($order->pair_id); $match = $pair ? CurrencyMatch::find($pair->currency_match_id) : null; $currency = $match ? Currency::find($match->currency_id) : null; $close_price = $currency ? sprintf("%.6f", $currency->price) : '0'; if (bccomp($close_price, '0', 6) <= 0) { $order->update(['status' => 0]); DB::commit(); $this->warn("Order #{$orderId}: close_price=0, skip"); continue; } $cmp = bccomp($close_price, sprintf("%.6f", $order->open_price), 6); $win = $order->direction == 'up' ? $cmp > 0 : $cmp < 0; $income = $win ? bcmul(sprintf("%.6f", $order->amount), bcdiv(sprintf("%.6f", $order->profit_rate), '100', 8), 6) : bcmul(sprintf("%.6f", $order->amount), '-1', 6); $order->update([ 'close_price' => $close_price, 'income' => $income, 'status' => $win ? 1 : 2, ]); if ($win) { $wallet = UsersWallet::where('user_id', $order->user_id) ->where('currency', 3)->lockForUpdate()->first(); if ($wallet) { $return_amount = bcadd(sprintf("%.6f", $order->amount), $income, 6); $before = $wallet->legal_balance; $wallet->legal_balance = bcadd($wallet->legal_balance, $return_amount, 6); $wallet->save(); AccountLog::insertLog( ['user_id' => $order->user_id, 'value' => $return_amount, 'info' => 'Option Win - ' . $order->symbol, 'type' => AccountLog::MICRO_TRADE_CLOSE_SETTLE, 'currency' => 3], ['balance_type' => 1, 'wallet_id' => $wallet->id, 'lock_type' => 0, 'before' => $before, 'change' => $return_amount, 'after' => $wallet->legal_balance] ); } } DB::commit(); $this->info("Order #{$orderId} settled: " . ($win ? 'WIN' : 'LOSE')); } catch (\Exception $e) { DB::rollBack(); $this->error("Order #{$orderId} error: " . $e->getMessage()); } } } }