b09f3220a1
- :core:model: DefaultCategoryKey in AC-7.2 order (14 keys: housing, insurance, children, fees added), ColorToken + SLATE, AMBER, CategoryIcons.ALL + key, shield, account_balance (33), ExpenseRepository.suggestCategory(accountId, description); ContractTest updated. - :domain: parseCategoryKeywords (pure, shared by :data and :core:fakes) with a parser test; the suggestCategory records and rule unchanged, suggest_category vectors pass. - :data: PlatformUnicodeText (java.text.Normalizer, Character), CategoryKeywords parsed once from the Java resource that copyCategoryKeywords copies from contracts/category-keywords.csv at build time (missing file fails the build), ExpenseRepositoryImpl.suggestCategory over the Room snapshot and the DataStore last-used category; tests: byte identity and the 14.8 rules of the bundled table, the UnicodeText binding, and Room/Robolectric cases for history, first token, ties, keywords, fallback, archived categories, deleted expenses, both users and accounts, null account. - :core:fakes: the 14 defaults with the schema v2 ids, fake suggestCategory through :domain with its own build-time copy of the table; tests. - Room schema unchanged (version 1). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
50 lines
2.1 KiB
Kotlin
50 lines
2.1 KiB
Kotlin
// :core:fakes — scenario-driven fakes of every repository interface of SPEC §14.2.4. Only for tests, screenshot tests
|
|
// and debug previews (the architecture check rejects it in release configurations). Computed values come from :domain.
|
|
// M7x add their scenarios under src/main/kotlin/se/hagstedt/kvitt/fakes/<feature>/ and nowhere else (SPEC §11.3).
|
|
plugins {
|
|
id("kvitt.android.library")
|
|
}
|
|
|
|
dependencies {
|
|
api(project(":core:model"))
|
|
implementation(project(":domain"))
|
|
testImplementation(libs.kotlinx.coroutines.test)
|
|
}
|
|
|
|
// The keyword table of the category suggestion (UX-3, SPEC §9.11 CS-6) is bundled as the Java resource
|
|
// se/hagstedt/kvitt/fakes/category-keywords.csv, copied from contracts/category-keywords.csv at build time (never
|
|
// hand-copied). A missing table fails the build: the task's input file must exist.
|
|
abstract class CopyCategoryKeywords : DefaultTask() {
|
|
@get:InputFile
|
|
@get:PathSensitive(PathSensitivity.NONE)
|
|
abstract val table: RegularFileProperty
|
|
|
|
@get:Input
|
|
abstract val resourcePath: Property<String>
|
|
|
|
@get:OutputDirectory
|
|
abstract val outputDir: DirectoryProperty
|
|
|
|
@TaskAction
|
|
fun copy() {
|
|
val source = table.get().asFile
|
|
if (!source.isFile) throw GradleException("missing ${source.path}")
|
|
val root = outputDir.get().asFile
|
|
root.deleteRecursively()
|
|
val target = root.resolve(resourcePath.get())
|
|
target.parentFile.mkdirs()
|
|
source.copyTo(target)
|
|
}
|
|
}
|
|
|
|
val categoryKeywordsTable = rootProject.layout.projectDirectory.file("../contracts/category-keywords.csv")
|
|
val copyCategoryKeywords = tasks.register<CopyCategoryKeywords>("copyCategoryKeywords") {
|
|
description = "Copies contracts/category-keywords.csv into the main Java resources."
|
|
table.set(categoryKeywordsTable)
|
|
resourcePath.set("se/hagstedt/kvitt/fakes/category-keywords.csv")
|
|
outputDir.set(layout.buildDirectory.dir("generated/category-keywords"))
|
|
}
|
|
androidComponents {
|
|
onVariants { variant -> variant.sources.resources?.addGeneratedSourceDirectory(copyCategoryKeywords, CopyCategoryKeywords::outputDir) }
|
|
}
|