{"body":"use Test;\n\nuse Sourcing;\n\nclass AccountOpened {\n\thas UInt $.account-id is required;\n\thas Rat  $.initial-amount where * >= 0;\n}\n\nclass Deposited {\n\thas UInt $.account-id is required;\n\thas Rat  $.amount where * >= 0;\n\thas UInt $.transfered-from;\n}\n\nclass Withdrew {\n\thas UInt $.account-id is required;\n\thas Rat  $.amount where * >= 0;\n\thas UInt $.transfered-to;\n}\n\nclass AccountClosed {\n\thas UInt $.account-id is required;\n}\n\nmy $next-id = 1;\ncommander Account {\n\thas UInt $.account-id is required is projection-id;\n\thas Rat  $.amount where * >= 0;\n\thas Bool $.active = False;\n\n\t# proto method apply($_) {\n\t# \t{*};\n\t# \tsay \"event  : \", $_;\n\t# \tsay \"account: \", self\n\t#\n\t# }\n\n\tmulti method apply(AccountOpened $_) {\n\t\t$!account-id = .account-id;\n\t\t$!amount     = .initial-amount;\n\t\t$!active     = True;\n\t}\n\n\tmulti method apply(Deposited $_) {\n\t\t$!amount += .amount;\n\t}\n\n\tmulti method apply(Withdrew $_) {\n\t\t$!amount -= .amount;\n\t}\n\n\tmulti method apply(AccountClosed $_) {\n\t\t$!active = False;\n\t}\n\n\tmethod open-account(::?CLASS:U: Rat() $initial-amount where * >= 0) {\n\t\tmy $account-id = $next-id++;\n\t\tmy $new = sourcing self, :$account-id;\n\t\t$new.account-opened: :$initial-amount;\n\t}\n\n\tmethod deposit(Rat() $amount where * >= 0) {\n\t\tdie \"Account $!account-id not active\" unless $!active;\n\t\t$.deposited: :$amount\n\t}\n\n\tmethod withdraw(Rat() $amount where * >= 0) {\n\t\tdie \"Account $!account-id not active\" unless $!active;\n\t\tdie \"Not enough money to withdraw $amount on account $!account-id\" unless $!amount >= $amount;\n\t\t$.withdrew: :$amount\n\t}\n\n\tmethod transfer(UInt $to, Rat() $amount) {\n\t\tdie \"Account from and to are the same account\" if $!account-id == $to;\n\t\tdie \"Account $!account-id not active\" unless $!active;\n\t\tdie \"Not enough money to withdraw $amount on account $!account-id\" unless $!amount >= $amount;\n\t\t\n\t\tmy $to-account = sourcing ::?CLASS, :account-id($to);\n\t\tdie \"Account $to to transfer to is not active\" unless $to-account.active;\n\n\t\t$.withdrew: :$amount, :transfered-to($to);\n\t\t$.deposited: :account-id($to), :$amount, :transfered-from($!account-id);\n\t}\n\n\tmethod close-account {\n\t\tdie \"Cannot close account $!account-id that still has amount\" if $!amount;\n\t\t$.account-closed\n\t}\n}\n\nuse Sourcing::Plugin::Memory;\nSourcing::Plugin::Memory.use;\n\nmy $e1 = Account.open-account: 100;\nmy $e2 = Account.open-account: 600;\n\nis-deeply\n\t(my $a1 = sourcing Account, account-id => $e1.account-id),\n\tAccount.new(account-id => 1, amount => 100.0, active => Bool::True)\n;\nis-deeply\n\t(my $a2 = sourcing Account, account-id => $e2.account-id),\n\tAccount.new(account-id => 2, amount => 600.0, active => Bool::True)\n;\n\n$a1.deposit:  300;\n$a2.withdraw: 200;\n\nis-deeply\n\t($a1 = sourcing Account, account-id => $e1.account-id),\n\tAccount.new(account-id => 1, amount => 400.0, active => Bool::True)\n;\nis-deeply\n\t($a2 = sourcing Account, account-id => $e2.account-id),\n\tAccount.new(account-id => 2, amount => 400.0, active => Bool::True)\n;\n\n$a1.transfer: $a2.account-id, $a1.amount;\n\nis-deeply\n\t($a1 = sourcing Account, account-id => $e1.account-id),\n\tAccount.new(account-id => 1, amount => 0.0, active => Bool::True)\n;\nis-deeply\n\t($a2 = sourcing Account, account-id => $e2.account-id),\n\tAccount.new(account-id => 2, amount => 800.0, active => Bool::True)\n;\n\n$a1.close-account;\n\nis-deeply\n\t($a1 = sourcing Account, account-id => $e1.account-id),\n\tAccount.new(account-id => 1, amount => 0.0, active => Bool::False)\n;\nis-deeply\n\t($a2 = sourcing Account, account-id => $e2.account-id),\n\tAccount.new(account-id => 2, amount => 800.0, active => Bool::True)\n;\n","name":"","extension":"raku","url":"https://www.irccloud.com/pastebin/ussVylOh","modified":1773629550,"id":"ussVylOh","size":3543,"lines":139,"own_paste":false,"theme":"","date":1773629550}