2026-01-03 10:29:03 -06:00

94 lines
2.5 KiB
C#

namespace BudgetApp.Domain.Models;
/// <summary>
/// Value object representing a monetary amount.
/// Immutable and ensures non-negative amounts.
/// </summary>
public class Money : IEquatable<Money>
{
public decimal Amount { get; }
public string Currency { get; }
public Money(decimal amount, string currency = "USD")
{
if (amount < 0)
throw new ArgumentException("Amount cannot be negative.", nameof(amount));
if (string.IsNullOrWhiteSpace(currency))
throw new ArgumentException("Currency cannot be null or empty.", nameof(currency));
Amount = amount;
Currency = currency;
}
public Money Add(Money other)
{
if (other == null)
throw new ArgumentNullException(nameof(other));
if (Currency != other.Currency)
throw new InvalidOperationException($"Cannot add money with different currencies: {Currency} and {other.Currency}");
return new Money(Amount + other.Amount, Currency);
}
public Money Subtract(Money other)
{
if (other == null)
throw new ArgumentNullException(nameof(other));
if (Currency != other.Currency)
throw new InvalidOperationException($"Cannot subtract money with different currencies: {Currency} and {other.Currency}");
var result = Amount - other.Amount;
if (result < 0)
throw new InvalidOperationException("Result cannot be negative.");
return new Money(result, Currency);
}
public bool Equals(Money? other)
{
if (other == null) return false;
return Amount == other.Amount && Currency == other.Currency;
}
public override bool Equals(object? obj)
{
return Equals(obj as Money);
}
public override int GetHashCode()
{
return HashCode.Combine(Amount, Currency);
}
public static bool operator ==(Money? left, Money? right)
{
if (ReferenceEquals(left, right)) return true;
if (left is null || right is null) return false;
return left.Equals(right);
}
public static bool operator !=(Money? left, Money? right)
{
return !(left == right);
}
public static Money operator +(Money left, Money right)
{
return left.Add(right);
}
public static Money operator -(Money left, Money right)
{
return left.Subtract(right);
}
public override string ToString()
{
return $"{Amount:F2} {Currency}";
}
}