namespace Domain.Entities.Common.ValueObject { public sealed record Money { public decimal Value { get; } public string Currency { get; } private Money(decimal value, string currency) { if (value < 0) { throw new ArgumentException("금액은 음수가 될 수 없습니다."); } Currency = currency; Value = Normalize(value, currency); } public static Money KRW(decimal value) => new(value, "KRW"); public static Money Zero(string currency) => new(0m, currency); public bool IsZero => Value == 0m; public static Money operator +(Money a, Money b) { EnsureSameCurrency(a, b); return new Money(a.Value + b.Value, a.Currency); } public static Money operator -(Money a, Money b) { EnsureSameCurrency(a, b); if (a.Value < b.Value) { throw new InvalidOperationException("잔액 부족"); } return new Money(a.Value - b.Value, a.Currency); } public static bool operator >=(Money a, Money b) { EnsureSameCurrency(a, b); return a.Value >= b.Value; } public static bool operator <=(Money a, Money b) { EnsureSameCurrency(a, b); return a.Value <= b.Value; } private static void EnsureSameCurrency(Money a, Money b) { if (a.Currency != b.Currency) { throw new InvalidOperationException("통화가 다릅니다."); } } private static decimal Normalize(decimal value, string currency) { var scale = currency == "KRW" ? 0 : 2; // KRW 0자리, 그 외 2자리 같은 정책 예시 return decimal.Round(value, scale, MidpointRounding.AwayFromZero); } } }