Coverage Summary for Class: TransactionSplitLineUi (com.georgeci.moneysurfer.feature.transaction.creation)

Class Class, % Method, % Branch, % Line, % Instruction, %
TransactionSplitLineUi 100% (1/1) 100% (1/1) 100% (3/3) 100% (19/19)


 package com.georgeci.moneysurfer.feature.transaction.creation
 
 import com.georgeci.moneysurfer.domain.model.Category
 import com.georgeci.moneysurfer.domain.model.Transaction
 import com.georgeci.moneysurfer.domain.primitives.RecurringRuleId
 import com.georgeci.moneysurfer.domain.primitives.SplitId
 import com.georgeci.moneysurfer.domain.primitives.TransactionId
 import com.georgeci.moneysurfer.domain.primitives.TransactionStatus
 import com.georgeci.moneysurfer.domain.primitives.TransferId
 
 /**
  * Everything a stored transaction carries that this screen has no field for.
  *
  * `saveTransaction` builds a whole new [Transaction] instead of patching the stored row, so a
  * field that is not routed back through here is silently reset to its default on update — which
  * is how editing used to wipe a transaction's merchant and tags, downgrade a `PLANNED` row to
  * `ACTUAL`, and orphan the other leg of a transfer by dropping its `transferId`.
  *
  * The defaults are what a brand-new transaction should have, so a blank form needs no special case.
  */
 data class PreservedTransactionFields(
     val merchant: String = "",
     val tags: List<String> = emptyList(),
     val status: TransactionStatus = TransactionStatus.ACTUAL,
     val transferId: TransferId? = null,
     /**
      * The receipt this row is one leg of. Dropping it on save would not merely lose a link: the
      * remaining legs would stay behind with no collapsed row left to reveal them, and the edited
      * row would leave the group without ever being deleted from it.
      */
     val splitId: SplitId? = null,
     val recurringRuleId: RecurringRuleId? = null,
 ) {
     companion object {
         /** Everything [transaction] holds outside the form — what an edit must hand back untouched. */
         fun of(transaction: Transaction): PreservedTransactionFields = PreservedTransactionFields(
             merchant = transaction.merchant,
             tags = transaction.tags,
             status = transaction.status,
             transferId = transaction.transferId,
             splitId = transaction.splitId,
             recurringRuleId = transaction.recurringRuleId,
         )
     }
 }
 
 /**
  * One line of the split editor: a slice of the receipt and the category it is filed under.
  *
  * [key] is a per-screen counter, not an id of anything stored — nothing is written until Save, and
  * two lines picking the same category must still be two distinct lines the user can edit and remove
  * independently.
  *
  * [amount] is raw input, empty until typed, and it is ignored on the **last** line: that one always
  * shows whatever is left of the receipt, so the legs add up to the amount by construction rather
  * than by asking the user to make them.
  */
 data class TransactionSplitLineUi(
     val key: Int,
     val category: Category? = null,
     val amount: String = "",
 )
 
 /**
  * The existing transaction the creation screen opens on, and what it is there for.
  *
  * One nullable parameter rather than an id plus a flag: the screen loads exactly one transaction
  * in either mode, and two independent parameters could contradict each other (a duplicate flag
  * with no id, an id with no mode).
  */
 data class TransactionCreationSeed(
     val transactionId: TransactionId,
     val mode: Mode,
 ) {
     enum class Mode {
         /** Update the transaction in place. */
         Edit,
 
         /** Use it as a template for a brand-new transaction. */
         Duplicate,
     }
 }
 
 /**
  * The transaction being edited, as it was stored — what the edit screen's identity band renders so
  * the user can tell which row they opened without scrolling or going back.
  *
  * A snapshot, not a view of the form: it is taken once when the transaction is loaded and never
  * follows the fields the user is editing.
  */
 data class TransactionEditIdentity(
     /** Short human-readable id, e.g. `TX-8213`. */
     val reference: String,
     val type: TransactionTypeUi,
     /** The note, falling back to the merchant when there is none; may still be blank. */
     val note: String,
     /** Signed for income and expense, unsigned for a transfer leg. */
     val formattedAmount: String,
     /** The category's stored appearance, fed to the shared bubble resolver. */
     val categoryId: String,
     val categoryIconKey: String,
     val categoryHue: Int,
     val categorySystemKind: String?,
 )