M12d: frequentCategoryIds and CategoryRepository.deletable (UX-9, D-059)
ExpenseEditorOptions.frequentCategoryIds per active account (up to five active categories by non-deleted expense count in the account, ties by sort_order) and CategoryRepository.deletable(id) (AC-7.6), from Room queries in :data and the same rule in :core:fakes. Room schema unchanged (version 1). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
This commit is contained in:
@@ -6,7 +6,22 @@ import kotlinx.coroutines.flow.Flow
|
||||
|
||||
data class ExpenseDraft(val id: ExpenseId?, val accountId: AccountId?, val categoryId: CategoryId?, val amountOre: Long?, val description: String, val notes: String, val date: String, val payer: UserId, val mode: SplitMode, val ratioBp: Map<UserId, Int>?, val exactOre: Map<UserId, Long>?, val fullOn: UserId?)
|
||||
|
||||
data class ExpenseEditorOptions(val me: User, val partner: User, val accounts: List<Account>, val categories: List<Category>, val defaultAccountId: AccountId?, val defaultCategoryFor: Map<AccountId, CategoryId>, val today: String)
|
||||
/**
|
||||
* [frequentCategoryIds] (UX-9, D-059): for each active account, up to five active categories ordered by the number of
|
||||
* non-deleted expenses in that account that use them (every expense on the phone: both users, pending, imported and
|
||||
* recurring included), descending; ties by `sort_order` ascending. Categories with no use in the account are left out,
|
||||
* so a list may be shorter or empty; the editor fills its row up from `sort_order` (design rule, not contract).
|
||||
*/
|
||||
data class ExpenseEditorOptions(
|
||||
val me: User,
|
||||
val partner: User,
|
||||
val accounts: List<Account>,
|
||||
val categories: List<Category>,
|
||||
val defaultAccountId: AccountId?,
|
||||
val defaultCategoryFor: Map<AccountId, CategoryId>,
|
||||
val today: String,
|
||||
val frequentCategoryIds: Map<AccountId, List<CategoryId>>,
|
||||
)
|
||||
|
||||
data class TimelineLine(val actor: User?, val action: AuditAction, val source: AuditSource, val clientAt: String, val changes: List<FieldChange>, val pendingLocal: Boolean)
|
||||
|
||||
|
||||
@@ -18,6 +18,13 @@ interface CategoryRepository {
|
||||
suspend fun reorder(idsInOrder: List<CategoryId>): OnlineResult<Unit>
|
||||
suspend fun setArchived(id: CategoryId, archived: Boolean): OnlineResult<Unit>
|
||||
suspend fun delete(id: CategoryId): OnlineResult<Unit>
|
||||
|
||||
/**
|
||||
* UX-9 (AC-7.6): false for a default category (`defaultKey != null`), one used by a non-deleted expense or a
|
||||
* non-deleted recurring template, and an unknown or deleted id. Computed from the phone's copy; the server stays the
|
||||
* authority, so [delete] can still fail with `category_is_default` or `category_in_use`.
|
||||
*/
|
||||
fun deletable(id: CategoryId): Flow<Boolean>
|
||||
}
|
||||
|
||||
data class RecurringTemplate(val id: TemplateId, val draft: ExpenseDraft, val dayOfMonth: Int, val startPeriod: String, val endPeriod: String?, val paused: Boolean, val nextOccurrence: String?)
|
||||
|
||||
Reference in New Issue
Block a user