Money.cs 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. namespace Domain.Entities.Common.ValueObject;
  2. public sealed record Money
  3. {
  4. public decimal Value { get; }
  5. public string Currency { get; }
  6. private Money(decimal value, string currency)
  7. {
  8. if (value < 0)
  9. {
  10. throw new ArgumentException("금액은 음수가 될 수 없습니다.");
  11. }
  12. Currency = currency;
  13. Value = Normalize(value, currency);
  14. }
  15. public static Money KRW(decimal value) => new(value, "KRW");
  16. public static Money Zero(string currency) => new(0m, currency);
  17. public bool IsZero => Value == 0m;
  18. public static Money operator +(Money a, Money b)
  19. {
  20. EnsureSameCurrency(a, b);
  21. return new Money(a.Value + b.Value, a.Currency);
  22. }
  23. public static Money operator -(Money a, Money b)
  24. {
  25. EnsureSameCurrency(a, b);
  26. if (a.Value < b.Value)
  27. {
  28. throw new InvalidOperationException("잔액 부족");
  29. }
  30. return new Money(a.Value - b.Value, a.Currency);
  31. }
  32. public static bool operator >=(Money a, Money b)
  33. {
  34. EnsureSameCurrency(a, b);
  35. return a.Value >= b.Value;
  36. }
  37. public static bool operator <=(Money a, Money b)
  38. {
  39. EnsureSameCurrency(a, b);
  40. return a.Value <= b.Value;
  41. }
  42. private static void EnsureSameCurrency(Money a, Money b)
  43. {
  44. if (a.Currency != b.Currency)
  45. {
  46. throw new InvalidOperationException("통화가 다릅니다.");
  47. }
  48. }
  49. private static decimal Normalize(decimal value, string currency)
  50. {
  51. var scale = currency == "KRW" ? 0 : 2; // KRW 0자리, 그 외 2자리 같은 정책 예시
  52. return decimal.Round(value, scale, MidpointRounding.AwayFromZero);
  53. }
  54. }