-
Notifications
You must be signed in to change notification settings - Fork 60
/
Account.cs
77 lines (61 loc) · 2.15 KB
/
Account.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
using Boc.Commands;
using Boc.Domain;
using Boc.Domain.Events;
using LaYumba.Functional;
using static LaYumba.Functional.F;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Boc.Chapter13.Domain
{
public static class Account
{
// handle commands
public static Validation<(Event Event, AccountState NewState)> Debit
(this AccountState @this, MakeTransfer cmd)
{
if (@this.Status != AccountStatus.Active)
return Errors.AccountNotActive;
if (@this.Balance - cmd.Amount < @this.AllowedOverdraft)
return Errors.InsufficientBalance;
var evt = cmd.ToEvent();
var newState = @this.Apply(evt);
return (evt as Event, newState);
}
public static Validation<(Event Event, AccountState NewState)> Freeze
(this AccountState @this, FreezeAccount cmd)
{
if (@this.Status == AccountStatus.Frozen)
return Errors.AccountNotActive;
var evt = cmd.ToEvent();
var newState = @this.Apply(evt);
return (evt as Event, newState);
}
// apply events
public static AccountState Create(CreatedAccount evt)
=> new AccountState
(
Currency: evt.Currency,
Status: AccountStatus.Active
);
public static AccountState Apply(this AccountState acc, Event evt)
=> evt switch
{
DepositedCash e
=> acc with { Balance = acc.Balance + e.Amount },
DebitedTransfer e
=> acc with { Balance = acc.Balance - e.DebitedAmount },
FrozeAccount
=> acc with { Status = AccountStatus.Frozen },
_ => throw new InvalidOperationException()
};
// hydrate
public static Option<AccountState> From(IEnumerable<Event> history)
=> history.Match(
Empty: () => None,
Otherwise: (createdEvent, otherEvents) => Some(
otherEvents.Aggregate(
seed: Account.Create((CreatedAccount)createdEvent),
func: (state, evt) => state.Apply(evt))));
}
}