user()->accounts() ->with(['holdings.transactions', 'holdings.security']) // 👈 確保能直接拿到最新價格 ->get() ->map(function ($account) { $data = $account->toArray(); // 🟢 2. 處理股票與基金的成本與估計現值計算 if (in_array($account->type, ['stock', 'fund'])) { $totalCost = 0; $totalValue = 0; foreach ($account->holdings as $holding) { // 🟢 修正 1:直接拿資料庫存好的庫存股數,不用再去 transactions 加減計算 $remainingShares = floatval($holding->shares); if ($remainingShares > 0) { // 🟢 修正 2:拿到最新價格 (如果沒抓到就先給一個暫時的預設值,例如 10,方便你 debug 畫面) $currentPrice = floatval($holding->security?->latest_price ?? 0); if ($currentPrice == 0) { // 💡 Debug 觀測:如果還是 0,我們先用 avg_cost 頂替,或者去手動確認 securities 表有沒有真的更新到價格 $currentPrice = floatval($holding->avg_cost ?? 0); } // 總現值 = 剩餘單位 * 最新價格 $totalValue += ($remainingShares * $currentPrice); // 總成本:直接拿你畫面上已經有的 avg_cost * shares 算最快最準! $avgCost = floatval($holding->avg_cost ?? 0); $totalCost += ($remainingShares * $avgCost); } } // 🟢 捨入並塞入回傳陣列 $data['total_cost'] = round($totalCost); // 持倉成本 $data['total_value'] = round($totalValue); // 目前市值 // 💡 關鍵補強:計算總損益與總報酬率並塞回陣列,消滅前端的 NaN%! $totalProfit = $totalValue - $totalCost; $totalRate = $totalCost > 0 ? ($totalProfit / $totalCost) * 100 : 0; // 🚨 請確認這裡的 Key 名稱(例如 total_profit 或是 unrealized_profit), // 要跟你在 Vue 前端 account.xxx 綁定的欄位名稱一模一樣喔! $data['total_profit'] = round($totalProfit); $data['total_rate'] = round($totalRate, 2); } // 處理信用卡 if ($account->type === 'credit_card') { $data['unpaid_amount'] = $account->unpaidAmount(); } return $data; }); return response()->json($accounts); } public function store(Request $request) { $validated = $request->validate([ 'name' => 'required|string|max:255', 'type' => 'required|in:cash,bank,stock,fund,wallet,credit_card', 'currency' => 'nullable|string|max:10', 'balance' => 'nullable|numeric', 'note' => 'nullable|string', 'billing_day' => 'nullable|integer|min:1|max:31', 'payment_day' => 'nullable|integer|min:1|max:31', ]); $account = $request->user()->accounts()->create($validated); return response()->json($account, 201); } public function show(Request $request, string $id) { $account = $request->user()->accounts()->findOrFail($id); return response()->json($account); } public function update(Request $request, string $id) { $account = $request->user()->accounts()->findOrFail($id); $validated = $request->validate([ 'name' => 'sometimes|string|max:255', 'type' => 'sometimes|in:cash,bank,stock,fund,wallet,credit_card', 'currency' => 'nullable|string|max:10', 'balance' => 'nullable|numeric', 'note' => 'nullable|string', 'billing_day' => 'nullable|integer|min:1|max:31', 'payment_day' => 'nullable|integer|min:1|max:31', ]); $account->update($validated); return response()->json($account); } public function destroy(Request $request, string $id) { $account = $request->user()->accounts()->findOrFail($id); $account->delete(); return response()->json(null, 204); } }