A software engineer website

Abaks: events

Gautier DI FOLCO June 07, 2023 [dev] #haskell #design #project #abaks

I tend to start with the events whenever I start an event source-based system.

But first, let's recall the requirements:

  • I should start a Period with a name (i.e. "June 2023"), start and stop dates, an initial balance
  • I can add/change/comment/delete an Entry, which is defined by an amount, a date, and a category
  • An Entry can be expected or not
  • At the end, I should be able to validate or flag in conflict an entry

Which gives us:

data AbaksEvent
  = Started {periodId :: PeriodId, name :: Text, from :: Day, to :: Day, initialBalance :: Amount}
  | EntryAdded {entry :: Entry}
  | EntryAmountChanged {entryId :: EntryId, amount :: Amount}
  | EntryValidated {entryId :: EntryId}
  | EntryCommented {entryId :: EntryId, comment :: Text}
  | EntryMarkedInConflict {entryId :: EntryId, reason :: Text}
  | EntryDeleted {entryId :: EntryId, comment :: Text}
  deriving stock (Eq, Show, Generic)

Also with the following supporting types:

newtype PeriodId = PeriodId {getPeriodId :: Int}
  deriving stock (Eq, Ord, Show, Generic)

data Entry = Entry
  { entryId :: EntryId,
    amount :: Amount,
    category :: Text,
    comment :: Text,
    state :: EntryState,
    date :: Day
  }
  deriving stock (Eq, Show, Generic)

newtype EntryId = EntryId {getEntryId :: Int}
  deriving stock (Eq, Ord, Show, Generic)

newtype Amount = Amount {getAmountInCents :: Int}
  deriving stock (Eq, Ord, Show, Generic)

data EntryState
  = Expected
  | Unexpected
  | Validated
  | InConflict Text
  deriving stock (Eq, Show, Generic)

Actually, there's four shortcomings in this design:

I would argue that these are 'improvements' made for UX purposes, users can make mistakes, enter the wrong amount, or on the wrong period, etc.

Next time we will see the commands, we'll have a lot to cover since I have a quite opinionated design.