-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathMoney.cs
executable file
·61 lines (48 loc) · 2.49 KB
/
Money.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
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using MyCompany.ECommerce.TechnicalStuff;
using P3Model.Annotations.Domain.DDD;
namespace MyCompany.ECommerce.Sales.Commons;
[DddValueObject]
public record Money(decimal Value, Currency Currency)
{
public static Money Zero(Currency currency) => new(0, currency);
public static Money Of(decimal value, Currency currency) => new(value, currency);
public static Money operator +(Money x, Money y) => Calculate(x, y, (a, b) => a + b);
public static Money operator -(Money x, Money y) => Calculate(x, y, (a, b) => a - b);
private static Money Calculate(Money x, Money y, Func<decimal, decimal, decimal> calculate)
{
CheckCurrencies(x, y);
return new Money(calculate(x.Value, y.Value), x.Currency);
}
public static Money operator *(Money x, int y) => Calculate(x, y, (a, b) => a * b);
public static Money operator /(Money x, int y) => Calculate(x, y, (a, b) => a / b);
public static Money operator *(Money x, decimal y) => Calculate(x, y, (a, b) => a * b);
public static Money operator /(Money x, decimal y) => Calculate(x, y, (a, b) => a / b);
public static Money operator *(Money x, Percentage y) => Calculate(x, y.Fraction, (a, b) => a * b);
private static Money Calculate<T>(Money x, T y, Func<decimal, T, decimal> calculate) =>
x with { Value = calculate(x.Value, y) };
public static Percentage operator /(Money x, Money y)
{
CheckCurrencies(x, y);
return Percentage.Of((int) Math.Round((x.Value / y.Value) * 100, 0));
}
public static Money Max(Money x, Money y) => x > y ? x : y;
public static bool operator >(Money x, Money y) => Compare(x, y, (a, b) => a > b);
public static bool operator <(Money x, Money y) => Compare(x, y, (a, b) => a < b);
public static bool operator >=(Money x, Money y) => Compare(x, y, (a, b) => a >= b);
public static bool operator <=(Money x, Money y) => Compare(x, y, (a, b) => a <= b);
private static bool Compare(Money x, Money y, Func<decimal, decimal, bool> compare)
{
CheckCurrencies(x, y);
return compare(x.Value, y.Value);
}
[SuppressMessage("ReSharper", "ParameterOnlyUsedForPreconditionCheck.Local")]
private static void CheckCurrencies(Money x, Money y)
{
if (x.Currency != y.Currency)
throw new DomainError();
}
public override string ToString() =>
$"{Value.ToString("F", CultureInfo.InvariantCulture)} {Currency.ToCode()}";
}