From 1d9ae792fa62e5828b1a604264cdabfb11c3b976 Mon Sep 17 00:00:00 2001 From: henry yo Date: Fri, 3 Jul 2026 02:00:01 +0800 Subject: [PATCH] fix: add md & fix dateformat & add note --- .../Controllers/Api/DashboardController.php | 33 +++++++++++++---- app/Jobs/UpdateAssetPriceJob.php | 7 ++-- develop.md | 35 +++++++++++++++++++ 3 files changed, 67 insertions(+), 8 deletions(-) create mode 100644 develop.md diff --git a/app/Http/Controllers/Api/DashboardController.php b/app/Http/Controllers/Api/DashboardController.php index 5a49ba0..e4aec81 100644 --- a/app/Http/Controllers/Api/DashboardController.php +++ b/app/Http/Controllers/Api/DashboardController.php @@ -15,21 +15,42 @@ class DashboardController extends Controller $userId = Auth::id(); $now = Carbon::now(); + $latestMonth = $now->copy(); + $latestYear = $latestMonth->year; + // 1. 本月基礎統計 (用一個查詢同時撈出「總金額」與「總筆數」) $monthStats = Expense::where('user_id', $userId) - ->whereYear('date', $now->year) - ->whereMonth('date', $now->month) + ->whereYear('date', $latestYear) + ->whereMonth('date', $latestMonth) ->selectRaw('SUM(amount) as total_amount, COUNT(id) as total_count') ->first(); + if (!$monthStats || $monthStats->total_amount == 0) { + // 改用 first() 確保能抓到單筆資料 + $latestExpense = Expense::where('user_id', $userId)->latest('date')->first(); + + if ($latestExpense) { + $targetDate = Carbon::parse($latestExpense->date); + $latestYear = $targetDate->year; + $latestMonth = $targetDate->month; + + // 重新撈取該月份的統計資料 + $monthStats = Expense::where('user_id', $userId) + ->whereYear('date', $latestYear) + ->whereMonth('date', $latestMonth) + ->selectRaw('SUM(amount) as total_amount, COUNT(id) as total_count') + ->first(); + } + } + $monthlyTotal = (float) ($monthStats->total_amount ?? 0); $monthlyCount = (int) ($monthStats->total_count ?? 0); // 2. 本月分類統計(圓餅圖)- 保持集合操作即可 $categoryStats = Expense::with('category') ->where('user_id', $userId) - ->whereYear('date', $now->year) - ->whereMonth('date', $now->month) + ->whereYear('date', $latestYear) + ->whereMonth('date', $latestMonth) ->get() ->groupBy(fn($e) => $e->category?->name ?? '未分類') ->map(fn($group, $name) => [ @@ -86,12 +107,12 @@ class DashboardController extends Controller $monthlyShare = (float) $expense->amount / $totalMonths; // 跑這 6 個月的迴圈,看有沒有落在這筆費用的歸屬區間內 - foreach ($monthlyTrendData as $monthStr => $currentTotal) { + foreach ($monthlyTrendData as $monthStr => &$currentTotal) { $currentMonthObj = Carbon::createFromFormat('Y/m', $monthStr)->startOfMonth(); // 如果圖表上的這個月份,剛好在費用的歸屬起訖之內,就把每月平均金額灌進去! if ($currentMonthObj->betweenIncluded($start, $end)) { - $monthlyTrendData[$monthStr] += $monthlyShare; + $currentTotal += $monthlyShare; } } } diff --git a/app/Jobs/UpdateAssetPriceJob.php b/app/Jobs/UpdateAssetPriceJob.php index 2603f95..6a267fe 100644 --- a/app/Jobs/UpdateAssetPriceJob.php +++ b/app/Jobs/UpdateAssetPriceJob.php @@ -57,7 +57,8 @@ class UpdateAssetPriceJob implements ShouldQueue $latestPrice = floatval($info['z'] ?? $info['o'] ?? 0); $latestPriceDate = isset($info['d']) ? Carbon::parse($info['d'])->format('Y-m-d') : now()->format('Y-m-d'); $name = $info['n'] ?? $this->defaultName; - + // 忘了備份時用的 + // $latestPriceDate = isset($info['d']) ? Carbon::parse($info['d'], 'Asia/Taipei')->subDay()->format('Y-m-d') : now()->subDay()->format('Y-m-d'); if (isset($info['y']) && $latestPrice > 0) { $changeAmount = floatval($latestPrice - $info['y']); $changeRate = ($changeAmount / $info['y']) * 100; @@ -88,7 +89,9 @@ class UpdateAssetPriceJob implements ShouldQueue } if ($headerInfo) { - $latestPriceDate = isset($headerInfo['navDate']) ? substr($headerInfo['navDate'], 0, 10) : now()->format('Y-m-d'); + $latestPriceDate = isset($headerInfo['navDate']) ? Carbon::parse($headerInfo['navDate'], 'Asia/Taipei')->format('Y-m-d') : now()->format('Y-m-d'); + // 忘了備份時用的 + // $latestPriceDate = isset($headerInfo['navDate']) ? Carbon::parse($headerInfo['navDate'], 'Asia/Taipei')->subDay()->format('Y-m-d') : now()->subDay()->format('Y-m-d'); $latestPrice = floatval($headerInfo['nav'] ?? 0); if ($latestPriceDate !== now()->format('Y-m-d')) { diff --git a/develop.md b/develop.md new file mode 100644 index 0000000..17eee15 --- /dev/null +++ b/develop.md @@ -0,0 +1,35 @@ +# Fin-Buddy 專案開發進度與規劃 + +## ✅ 已完成階段 +- [x] **容器架構部署**:Laravel 與 PostgreSQL 成功運行於 `1panel-network`。 +- [x] **資料庫遷移**:順利整合至 1Panel 內建資料庫容器。 +- [x] **環境對齊**:修正 Port 對應 (8081:9000) 及路由快取問題,系統穩定運行。 +- [x] **端到端測試**:核心 API 流程驗證通過。 + +--- + +## ⏳ 待辦與優化清單 + +### 1. 系統清理與維運 +- [ ] 移除舊容器與無用映像檔 (釋放空間)。 +- [ ] 將 `web.php` 內危險的同步腳本遷移至 Laravel Artisan Command。 +- [ ] 檢查 `.env` 安全性設定 (關閉 `APP_DEBUG`)。 +- [ ] 配置 1Panel 資料庫自動備份任務。 + +--- + +## 🚀 未來 Roadmap + +| 階段 | 項目 | 目標 | +| :--- | :--- | :--- | +| **I** | **APP 化 (PWA)** | 將前端轉換為 PWA,實現手機桌面安裝與離線訪問。 | +| **I** | **記帳 Widget** | 實作快速記帳入口,點擊即錄入,簡化操作動線。 | +| **II** | **內容細化與排程** | 擴充 DB Schema,納入「信用卡結帳日」、「發票排程」邏輯。 | +| **II** | **銀行與信用卡聯動** | 實作數據同步機制 (Open Banking / 自動抓取)。 | +| **III** | **後台與權限管理** | 導入 Filament 與 Spatie,建立 API 測試後台與系統監控。 | + +--- + +## 📝 優先級建議 +1. **建議先做:** 將 `sync-all-history` 正式化為 Command,減少系統安全風險。 +2. **開發策略:** 建議優先採用 **Filament** 進行後台開發,這能省去 80% 開發後台介面的時間,讓你直接專注於監控系統與 API 測試。 \ No newline at end of file