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>
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>
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>
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>
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>
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>
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>
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>
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 能夠穩定運作的基石。