Vibe coding全紀錄-50

A:

要請幫忙一步一步詳細仔細的列出最終版的下列程式碼,謝謝

data/local/entity/*

* Enums.kt

* Account.kt

* AccountSnapshot.kt

* MainCategory.kt

* SubCategory.kt

* Project.kt

* Transaction.kt

* RecurringTransaction.kt 

Q:

好的,沒有問題。

這一步非常重要,因為資料實體 (Entity) 是整個 App 資料庫的藍圖。我將逐一列出 data/local/entity/ 套件底下所有資料實體的最終版程式碼,這些程式碼包含了我們在整個開發過程中所有的修改與擴充。


第廿三步:最終程式碼回顧 (Entity 篇)

檔案路徑: app/src/main/java/com/yourcompany/cashflow/data/local/entity/Enums.kt

<details>

<summary><strong>點此展開 Enums.kt 程式碼</strong></summary>

Kotlin
package com.yourcompany.cashflow.data.local.entity

/**
 * 帳戶類型:銀行(現金資產)、投資、負債
 */
enum class AccountType {
    BANK,
    INVESTMENT,
    LIABILITY
}

/**
 * 交易類型:收入、支出
 */
enum class TransactionType {
    INCOME,
    EXPENSE
}

/**
 * 定期交易的頻率
 */
enum class FrequencyType {
    WEEKLY,
    MONTHLY,
    YEARLY
}

/**
 * 資產類別,用於資產負債表中的配置分析
 */
enum class AssetClass {
    CASH,    // 現金 (對應銀行帳戶)
    STOCK,   // 股票
    BOND,    // 債券
    OTHER    // 其他資產
}

/**
 * 專案狀態:進行中、已完成
 */
enum class ProjectStatus {
    ACTIVE,
    COMPLETED
}

</details>


檔案路徑: app/src/main/java/com/yourcompany/cashflow/data/local/entity/Account.kt

<details>

<summary><strong>點此展開 Account.kt 程式碼</strong></summary>

Kotlin
package com.yourcompany.cashflow.data.local.entity

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "accounts")
data class Account(
    @PrimaryKey(autoGenerate = true)
    val id: Long = 0,
    val name: String,
    val type: AccountType,

    // 用於資產配置分析,並提供預設值以利資料庫遷移
    @ColumnInfo(defaultValue = "CASH")
    val assetClass: AssetClass,

    val initialBalance: Double
)

</details>


檔案路徑: app/src/main/java/com/yourcompany/cashflow/data/local/entity/AccountSnapshot.kt

<details>

<summary><strong>點此展開 AccountSnapshot.kt 程式碼</strong></summary>

Kotlin
package com.yourcompany.cashflow.data.local.entity

import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey

@Entity(
    tableName = "account_snapshots",
    foreignKeys = [ForeignKey(
        entity = Account::class,
        parentColumns = ["id"],
        childColumns = ["accountId"],
        onDelete = ForeignKey.CASCADE // 當帳戶被刪除時,其所有快照也一併刪除
    )]
)
data class AccountSnapshot(
    @PrimaryKey(autoGenerate = true)
    val id: Long = 0,
    val accountId: Long,    // 關聯到哪個帳戶
    val snapshotDate: Long, // 快照日期 (儲存時間戳)
    val value: Double       // 該日期的帳戶價值
)

</details>


檔案路徑: app/src/main/java/com/yourcompany/cashflow/data/local/entity/MainCategory.kt

<details>

<summary><strong>點此展開 MainCategory.kt 程式碼</strong></summary>

Kotlin
package com.yourcompany.cashflow.data.local.entity

import androidx.room.Entity
import androidx.room.Index
import androidx.room.PrimaryKey

@Entity(
    tableName = "main_categories",
    indices = [Index(value = ["name"], unique = true)] // 主分類名稱必須是唯一的
)
data class MainCategory(
    @PrimaryKey(autoGenerate = true)
    val id: Long = 0,
    val name: String,
    val type: TransactionType // 區分是收入類別還是支出類別
)

</details>


檔案路徑: app/src/main/java/com/yourcompany/cashflow/data/local/entity/SubCategory.kt

<details>

<summary><strong>點此展開 SubCategory.kt 程式碼</strong></summary>

Kotlin
package com.yourcompany.cashflow.data.local.entity

import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.Index
import androidx.room.PrimaryKey

@Entity(
    tableName = "sub_categories",
    foreignKeys = [ForeignKey(
        entity = MainCategory::class,
        parentColumns = ["id"],
        childColumns = ["mainCategoryId"],
        onDelete = ForeignKey.CASCADE // 主分類被刪除時,子分類也一併刪除
    )],
    // 確保在同一個主分類下,子分類的名稱是唯一的
    indices = [Index(value = ["mainCategoryId", "name"], unique = true)]
)
data class SubCategory(
    @PrimaryKey(autoGenerate = true)
    val id: Long = 0,
    val mainCategoryId: Long,
    val name: String
)

</details>


檔案路徑: app/src/main/java/com/yourcompany/cashflow/data/local/entity/Project.kt

<details>

<summary><strong>點此展開 Project.kt 程式碼</strong></summary>

Kotlin
package com.yourcompany.cashflow.data.local.entity

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "projects")
data class Project(
    @PrimaryKey(autoGenerate = true)
    val id: Long = 0,
    val name: String,
    val budget: Double,
    val description: String?,

    // 專案狀態,並提供預設值以利資料庫遷移
    @ColumnInfo(defaultValue = "ACTIVE")
    val status: ProjectStatus
)

</details>


檔案路徑: app/src/main/java/com/yourcompany/cashflow/data/local/entity/Transaction.kt

<details>

<summary><strong>點此展開 Transaction.kt 程式碼</strong></summary>

Kotlin
package com.yourcompany.cashflow.data.local.entity

import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.Index
import androidx.room.PrimaryKey

@Entity(
    tableName = "transactions",
    foreignKeys = [
        ForeignKey(
            entity = Account::class,
            parentColumns = ["id"],
            childColumns = ["accountId"],
            onDelete = ForeignKey.RESTRICT // 限制刪除:如果帳戶下有交易,不能直接刪除該帳戶
        ),
        ForeignKey(
            entity = SubCategory::class,
            parentColumns = ["id"],
            childColumns = ["subCategoryId"],
            onDelete = ForeignKey.RESTRICT // 同理,限制分類不能被輕易刪除
        ),
        ForeignKey(
            entity = Project::class,
            parentColumns = ["id"],
            childColumns = ["projectId"],
            onDelete = ForeignKey.SET_NULL // 如果專案被刪除,相關交易的 projectId 設為 NULL
        )
    ],
    // 為外鍵加上索引,可以提升查詢效能
    indices = [Index(value = ["projectId"]), Index(value = ["accountId"]), Index(value = ["subCategoryId"])]
)
data class Transaction(
    @PrimaryKey(autoGenerate = true)
    val id: Long = 0,
    val accountId: Long,
    val subCategoryId: Long,
    val amount: Double,
    val type: TransactionType,
    val transactionDate: Long,
    val note: String?,
    val projectId: Long? // 可為 null,代表這筆交易不屬於任何專案
)

</details>


檔案路徑: app/src/main/java/com/yourcompany/cashflow/data/local/entity/RecurringTransaction.kt

<details>

<summary><strong>點此展開 RecurringTransaction.kt 程式碼</strong></summary>

Kotlin
package com.yourcompany.cashflow.data.local.entity

import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.PrimaryKey

@Entity(
    tableName = "recurring_transactions",
    foreignKeys = [
        ForeignKey(
            entity = Account::class,
            parentColumns = ["id"],
            childColumns = ["accountId"],
            onDelete = ForeignKey.CASCADE // 如果帳戶被刪除,相關的定期規則也應失效
        ),
        ForeignKey(
            entity = SubCategory::class,
            parentColumns = ["id"],
            childColumns = ["subCategoryId"],
            onDelete = ForeignKey.CASCADE // 如果分類被刪除,相關的定期規則也應失效
        )
    ]
)
data class RecurringTransaction(
    @PrimaryKey(autoGenerate = true)
    val id: Long = 0,
    val accountId: Long,
    val subCategoryId: Long,
    val amount: Double,
    val type: TransactionType,
    val note: String?,

    // 週期性規則
    val frequency: FrequencyType,
    val dayOfWeek: Int?,    // 如果是每週 (1=週一...7=週日, 對應 java.time.DayOfWeek.getValue())
    val dayOfMonth: Int?,   // 如果是每月
    val monthOfYear: Int?,  // 如果是每年
    val dayOfYear: Int?,    // 如果是每年
    
    val startDate: Long,    // 此規則的開始日期
    val endDate: Long?      // 此規則的結束日期 (可選)
)

</details>


以上就是我們專案資料庫中所有資料表 (Entity) 的最終結構。這份清晰、完整且關係明確的資料庫藍圖,是我們整個「錢流」App 能夠穩定運作的基石。