Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/BuildingBlocks/Core/Domain/Money.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,50 @@ public Money(decimal amount, string currency)
}

public static Money Zero(string currency = "USD") => new(0m, currency);

public Money Add(Money other)
{
ArgumentNullException.ThrowIfNull(other);
EnsureSameCurrency(other);
return this with { Amount = Amount + other.Amount };
}

public Money Subtract(Money other)
{
ArgumentNullException.ThrowIfNull(other);
EnsureSameCurrency(other);
return this with { Amount = Amount - other.Amount };
}

public Money Multiply(decimal factor) => this with { Amount = Amount * factor };

public Money Round(int decimals) =>
this with { Amount = Math.Round(Amount, decimals, MidpointRounding.AwayFromZero) };

public static Money operator +(Money left, Money right)
{
ArgumentNullException.ThrowIfNull(left);
return left.Add(right);
}

public static Money operator -(Money left, Money right)
{
ArgumentNullException.ThrowIfNull(left);
return left.Subtract(right);
}

public static Money operator *(Money left, decimal right)
{
ArgumentNullException.ThrowIfNull(left);
return left.Multiply(right);
}

private void EnsureSameCurrency(Money other)
{
if (!string.Equals(Currency, other.Currency, StringComparison.Ordinal))
{
throw new InvalidOperationException(
$"Cannot operate on Money with different currencies: {Currency} and {other.Currency}.");
}
}
}
4 changes: 2 additions & 2 deletions src/Host/FSH.Starter.DbMigrator/DemoSeed/DemoSeeder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ private async Task SeedTenantSubscriptionAsync(DemoTenant demo, CancellationToke

// Paid plans get an issued term invoice (like real CreateTenant), written directly so no InvoiceIssuedIntegrationEvent fires
// (no outbox dispatcher; seeding mustn't email). Idempotent on invoice number; free plans (term price 0) get none, as in production.
if (plan.TermPrice > 0m)
if (plan.TermPrice.Amount > 0m)
{
var invoiceNumber = string.Create(
CultureInfo.InvariantCulture, $"SUB-{startUtc:yyyyMM}-{demo.Id.ToUpperInvariant()}");
Expand All @@ -251,7 +251,7 @@ private async Task SeedTenantSubscriptionAsync(DemoTenant demo, CancellationToke
CultureInfo.InvariantCulture,
$"{plan.Name} — {plan.Interval} subscription ({startUtc:yyyy-MM-dd} to {endUtc:yyyy-MM-dd})"),
1m,
plan.TermPrice);
plan.TermPrice.Amount);
invoice.Issue();
billingDb.Invoices.Add(invoice);
if (_logger.IsEnabled(LogLevel.Information))
Expand Down
Loading
Loading