Money.cs 1.9 KB

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