Skip to content

Instantly share code, notes, and snippets.

@emag
Last active December 8, 2024 09:31
Show Gist options
  • Save emag/f2ff62fbc4c5a864e94d52ca673e7986 to your computer and use it in GitHub Desktop.
Save emag/f2ff62fbc4c5a864e94d52ca673e7986 to your computer and use it in GitHub Desktop.
BS 集約 + ドメインロジック
import edomata.core.*
import edomata.syntax.all.*
enum BalanceSheet {
case NotReady
case Ready(
assets: Map[AccountTitle, BigDecimal],
liabilities: Map[AccountTitle, BigDecimal]
)
def initialize(
assets: Map[AccountTitle, BigDecimal],
liabilities: Map[AccountTitle, BigDecimal]
): Decision[BsRejection, BsEvent, Ready] =
this
.decide {
case NotReady => Decision.accept(Initialized(assets, liabilities))
case Ready(_, _) => Decision.reject(AlreadyInitialized)
}
.validate(_.mustBeReady)
def journalize(
entry: JournalEntry
): Decision[BsRejection, BsEvent, Ready] =
this
.perform(mustBeReady.toDecision.flatMap { _ =>
if entry.amount > 0
then Decision.accept(Journalized(entry))
else Decision.reject(NegativeAmountJournalEntry)
})
.validate(_.mustNotBeNegativeBalance)
private def mustBeReady: ValidatedNec[BsRejection, Ready] = this match
case bs @ Ready(_, _) => bs.validNec
case NotReady => BsRejection.NotReady.invalidNec
private def mustNotBeNegativeBalance: ValidatedNec[BsRejection, Ready] =
mustBeReady andThen { bs =>
if bs.assets.forall { case (_, amount) => amount >= 0 } &&
bs.liabilities.forall { case (_, amount) => amount >= 0 }
then bs.validNec
else NegativeBalance.invalidNec
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment