Skip to content

Commit

Permalink
pit-stop
Browse files Browse the repository at this point in the history
  • Loading branch information
VMelnalksnis committed Oct 27, 2024
1 parent e2568f7 commit 65cc97d
Show file tree
Hide file tree
Showing 155 changed files with 10,398 additions and 2,269 deletions.
3 changes: 3 additions & 0 deletions source/Gnomeshade.Avalonia.Core/Converters.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ public static class Converters
/// <summary>Gets a <see cref="string"/>/<see cref="NodaTime.LocalDateTime"/> converter.</summary>
public static LocalDateTimeConverter LocalDateTime { get; } = new();

/// <summary>Gets a <see cref="string"/>/<see cref="NodaTime.Period"/> converter.</summary>
public static PeriodConverter Period { get; } = new();

/// <summary>Gets a <see cref="ICollection"/> converter that checks whether the collection is not empty.</summary>
public static IValueConverter NotEmpty { get; } =
new FuncValueConverter<ICollection?, bool>(collection => collection?.Count > 0);
Expand Down
40 changes: 38 additions & 2 deletions source/Gnomeshade.Avalonia.Core/DesignTime/DesignTimeData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ public static class DesignTimeData

/// <summary>Gets an instance of <see cref="TransactionViewModel"/> for use during design time.</summary>
public static TransactionViewModel TransactionViewModel { get; } =
InitializeViewModel<TransactionViewModel, TransactionOverview, TransactionUpsertionViewModel>(new(ActivityService, GnomeshadeClient, DialogService, Clock, DateTimeZoneProvider));
InitializeViewModel<TransactionViewModel, TransactionOverview, TransactionUpsertionBase>(new(ActivityService, GnomeshadeClient, DialogService, Clock, DateTimeZoneProvider));

/// <summary>Gets an instance of <see cref="TransactionFilter"/> for use during design time.</summary>
public static TransactionFilter TransactionFilter { get; } = new(ActivityService, Clock, DateTimeZoneProvider);
Expand All @@ -148,7 +148,7 @@ public static class DesignTimeData
public static LinkViewModel LinkViewModel { get; } =
InitializeViewModel<LinkViewModel, LinkOverview, LinkUpsertionViewModel>(new(ActivityService, GnomeshadeClient, Guid.Empty));

/// <summary>Gets an instance of <see cref="LoanUpsertionViewModel"/> for use during design time.</summary>
/// <summary>Gets an instance of <see cref="LoanPaymentUpsertionViewModel"/> for use during design time.</summary>
public static LoanPaymentUpsertionViewModel LoanPaymentUpsertionViewModel { get; } =
InitializeViewModel(new LoanPaymentUpsertionViewModel(ActivityService, GnomeshadeClient, Guid.Empty, null));

Expand Down Expand Up @@ -240,6 +240,42 @@ public static class DesignTimeData
public static DashboardViewModel DashboardViewModel { get; } =
InitializeViewModel<DashboardViewModel>(new(ActivityService, GnomeshadeClient, Clock, DateTimeZoneProvider));

/// <summary>Gets an instance of <see cref="PlannedTransactionUpsertionViewModel"/> for use during design time.</summary>
public static PlannedTransactionUpsertionViewModel PlannedTransactionUpsertionViewModel { get; } =
InitializeViewModel<PlannedTransactionUpsertionViewModel>(new(ActivityService, GnomeshadeClient, DialogService, DateTimeZoneProvider, null));

/// <summary>Gets an instance of <see cref="TransactionScheduleUpsertionViewModel"/> for use during design time.</summary>
public static TransactionScheduleUpsertionViewModel TransactionScheduleUpsertionViewModel { get; } =
InitializeViewModel<TransactionScheduleUpsertionViewModel>(new(ActivityService, GnomeshadeClient, DialogService, DateTimeZoneProvider, null));

/// <summary>Gets an instance of <see cref="TransactionScheduleViewModel"/> for use during design time.</summary>
public static TransactionScheduleViewModel TransactionScheduleViewModel { get; } =
InitializeViewModel<TransactionScheduleViewModel>(new(ActivityService, GnomeshadeClient, DialogService, DateTimeZoneProvider));

/// <summary>Gets an instance of <see cref="PlannedTransferViewModel"/> for use during design time.</summary>
public static PlannedTransferViewModel PlannedTransferViewModel { get; } =
InitializeViewModel<PlannedTransferViewModel>(new(ActivityService, GnomeshadeClient, DialogService, DateTimeZoneProvider, Guid.Empty));

/// <summary>Gets an instance of <see cref="PlannedTransferUpsertionViewModel"/> for use during design time.</summary>
public static PlannedTransferUpsertionViewModel PlannedTransferUpsertionViewModel { get; } =
InitializeViewModel<PlannedTransferUpsertionViewModel>(new(ActivityService, GnomeshadeClient, DialogService, DateTimeZoneProvider, Guid.Empty, null));

/// <summary>Gets an instance of <see cref="PlannedPurchaseViewModel"/> for use during design time.</summary>
public static PlannedPurchaseViewModel PlannedPurchaseViewModel { get; } =
InitializeViewModel<PlannedPurchaseViewModel>(new(ActivityService, GnomeshadeClient, DialogService, DateTimeZoneProvider, Guid.Empty));

/// <summary>Gets an instance of <see cref="PlannedPurchaseUpsertionViewModel"/> for use during design time.</summary>
public static PlannedPurchaseUpsertionViewModel PlannedPurchaseUpsertionViewModel { get; } =
InitializeViewModel<PlannedPurchaseUpsertionViewModel>(new(ActivityService, GnomeshadeClient, DialogService, DateTimeZoneProvider, Guid.Empty, null));

/// <summary>Gets an instance of <see cref="PlannedLoanPaymentUpsertionViewModel"/> for use during design time.</summary>
public static PlannedLoanPaymentUpsertionViewModel PlannedLoanPaymentUpsertionViewModel { get; } =
InitializeViewModel<PlannedLoanPaymentUpsertionViewModel>(new(ActivityService, GnomeshadeClient, Guid.Empty, null));

/// <summary>Gets an instance of <see cref="PlannedLoanPaymentViewModel"/> for use during design time.</summary>
public static PlannedLoanPaymentViewModel PlannedLoanPaymentViewModel { get; } =
InitializeViewModel<PlannedLoanPaymentViewModel, LoanPaymentRow, PlannedLoanPaymentUpsertionViewModel>(new(ActivityService, GnomeshadeClient, Guid.Empty));

[UnconditionalSuppressMessage(
"Trimming",
"IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ public sealed class DesignTimeGnomeshadeClient : IGnomeshadeClient
private static readonly List<LoanPayment> _loanPayments;
private static readonly List<Project> _projects;

private static readonly List<TransactionSchedule> _transactionSchedules;
private static readonly List<PlannedTransaction> _plannedTransactions;
private static readonly List<PlannedTransfer> _plannedTransfers;
private static readonly List<PlannedPurchase> _plannedPurchases;
private static readonly List<PlannedLoanPayment> _plannedLoanPayments;

static DesignTimeGnomeshadeClient()
{
var euro = new Currency { Id = Guid.NewGuid(), Name = "Euro", AlphabeticCode = "EUR" };
Expand All @@ -55,7 +61,8 @@ static DesignTimeGnomeshadeClient()

var counterparty = new Counterparty { Id = Guid.Empty, Name = "John Doe" };
var otherCounterparty = new Counterparty { Id = Guid.NewGuid(), Name = "Jane Doe" };
_counterparties = [counterparty, otherCounterparty];
var bankCounterparty = new Counterparty { Id = Guid.NewGuid(), Name = "Bank" };
_counterparties = [counterparty, otherCounterparty, bankCounterparty];

var cash = new Account
{
Expand All @@ -69,27 +76,39 @@ static DesignTimeGnomeshadeClient()
new() { Id = Guid.NewGuid(), CurrencyId = usd.Id, CurrencyAlphabeticCode = usd.AlphabeticCode }
],
};

var spending = new Account
{
Id = Guid.NewGuid(),
Name = "Spending",
CounterpartyId = counterparty.Id,
PreferredCurrencyId = euro.Id,
Currencies =
[new() { Id = Guid.NewGuid(), CurrencyId = euro.Id, CurrencyAlphabeticCode = euro.AlphabeticCode }],
Currencies = [new() { Id = Guid.NewGuid(), CurrencyId = euro.Id, CurrencyAlphabeticCode = euro.AlphabeticCode }],
};

var bankAccount = new Account
{
Id = Guid.NewGuid(),
Name = "Bank",
CounterpartyId = bankCounterparty.Id,
PreferredCurrencyId = euro.Id,
Currencies = [new() { Id = Guid.NewGuid(), CurrencyId = euro.Id, CurrencyAlphabeticCode = euro.AlphabeticCode }],
};
_accounts = [cash, spending];

_accounts = [cash, spending, bankAccount];

var kilogram = new Unit { Id = Guid.NewGuid(), Name = "Kilogram" };
var gram = new Unit { Id = Guid.NewGuid(), Name = "Gram", ParentUnitId = kilogram.Id, Multiplier = 1000m };
_units = [kilogram, gram];

var food = new Category { Id = Guid.Empty, Name = "Food" };
_categories = [food];
var liabilities = new Category { Id = Guid.NewGuid(), Name = "Liabilities" };
_categories = [food, liabilities];

var bread = new Product { Id = Guid.NewGuid(), Name = "Bread", CategoryId = food.Id, UnitId = kilogram.Id };
var milk = new Product { Id = Guid.NewGuid(), Name = "Milk", CategoryId = food.Id };
_products = [bread, milk];
var loan = new Product { Id = Guid.NewGuid(), Name = "Loan", CategoryId = liabilities.Id };
_products = [bread, milk, loan];

var transaction = new Transaction
{
Expand Down Expand Up @@ -217,10 +236,94 @@ static DesignTimeGnomeshadeClient()
Name = "Home improvement",
},
];

var transactionSchedule = new TransactionSchedule
{
Id = Guid.Empty,
Name = "Monthly",
StartingAt = SystemClock.Instance.GetCurrentInstant() + Duration.FromDays(15),
Period = Period.FromMonths(1),
Count = 12,
};

_transactionSchedules = [transactionSchedule];
_plannedTransactions = [];
_plannedTransfers = [];
_plannedPurchases = [];
_plannedLoanPayments = [];

var timeZone = DateTimeZoneProviders.Tzdb.GetSystemDefault();
for (var i = 0; i < transactionSchedule.Count; i++)
{
var startingAt = transactionSchedule.StartingAt.InZone(timeZone).LocalDateTime;
for (var j = 0; j < i; j++)
{
startingAt += transactionSchedule.Period;
}

var bookedAt = startingAt.InZoneStrictly(timeZone).ToInstant();

var plannedTransaction = new PlannedTransaction
{
Id = i is 0 ? Guid.Empty : Guid.NewGuid(),
ScheduleId = transactionSchedule.Id,
};

var plannedPrincipalTransfer = new PlannedTransfer
{
Id = i is 0 ? Guid.Empty : Guid.NewGuid(),
TransactionId = plannedTransaction.Id,
SourceAmount = 500,
SourceAccountId = spending.Currencies.Single(account => account.CurrencyId == euro.Id).Id,
TargetAmount = 500,
TargetCounterpartyId = bankCounterparty.Id,
TargetCurrencyId = euro.Id,
BookedAt = bookedAt,
Order = 1,
};

var plannedInterestTransfer = new PlannedTransfer
{
Id = Guid.NewGuid(),
TransactionId = plannedTransaction.Id,
SourceAmount = 150,
SourceAccountId = spending.Currencies.Single(account => account.CurrencyId == euro.Id).Id,
TargetAmount = 150,
TargetCounterpartyId = bankCounterparty.Id,
TargetCurrencyId = euro.Id,
BookedAt = bookedAt,
Order = 2,
};

var plannedPurchase = new PlannedPurchase
{
Id = i is 0 ? Guid.Empty : Guid.NewGuid(),
TransactionId = plannedTransaction.Id,
Price = plannedPrincipalTransfer.SourceAmount + plannedInterestTransfer.SourceAmount,
CurrencyId = euro.Id,
ProductId = loan.Id,
Amount = 1,
ProjectIds = [],
};

var plannedLoanPayment = new PlannedLoanPayment
{
Id = i is 0 ? Guid.Empty : Guid.NewGuid(),
LoanId = _loans.Single().Id,
TransactionId = plannedTransaction.Id,
Amount = plannedPrincipalTransfer.SourceAmount,
Interest = plannedInterestTransfer.SourceAmount,
};

_plannedTransactions.Add(plannedTransaction);
_plannedTransfers.AddRange([plannedPrincipalTransfer, plannedInterestTransfer]);
_plannedPurchases.Add(plannedPurchase);
_plannedLoanPayments.Add(plannedLoanPayment);
}
}

/// <inheritdoc />
public Task<LoginResult> LogInAsync(Login login) => throw new NotImplementedException();
public Task<LoginResult> LogInAsync(Login login) => Task.FromResult<LoginResult>(new SuccessfulLogin());

/// <inheritdoc />
public Task<ExternalLoginResult> SocialRegister() => throw new NotImplementedException();
Expand Down Expand Up @@ -486,6 +589,147 @@ public Task AddRelatedTransactionAsync(Guid id, Guid relatedId) =>
public Task RemoveRelatedTransactionAsync(Guid id, Guid relatedId) =>
throw new NotImplementedException();

/// <inheritdoc />
public Task<List<TransactionSchedule>> GetTransactionSchedules(CancellationToken cancellationToken = default) =>
Task.FromResult(_transactionSchedules.ToList());

/// <inheritdoc />
public Task<TransactionSchedule> GetTransactionSchedule(Guid id, CancellationToken cancellationToken = default) =>
Task.FromResult(_transactionSchedules.Single(schedule => schedule.Id == id));

/// <inheritdoc />
public async Task<Guid> CreateTransactionSchedule(TransactionScheduleCreation schedule)
{
var id = Guid.NewGuid();
await PutTransactionSchedule(id, schedule);
return id;
}

/// <inheritdoc />
public Task PutTransactionSchedule(Guid id, TransactionScheduleCreation schedule)
{
var existing = _transactionSchedules.SingleOrDefault(transactionSchedule => transactionSchedule.Id == id);
existing ??= new();

existing.Name = schedule.Name;
existing.StartingAt = schedule.StartingAt;
existing.Period = schedule.Period;
existing.Count = schedule.Count;

return Task.CompletedTask;
}

/// <inheritdoc />
public async Task DeleteTransactionSchedule(Guid id)
{
var schedule = await GetTransactionSchedule(id);
_transactionSchedules.Remove(schedule);
}

/// <inheritdoc />
public Task<List<PlannedTransaction>> GetPlannedTransactions(Interval interval, CancellationToken cancellationToken = default)
{
var transactions = _plannedTransactions
.Where(transaction =>
{
var date = _plannedTransfers
.Where(transfer => transfer.TransactionId == transaction.Id)
.Select(transfer => transfer.BookedAt)
.Max();
return date is { } instant && interval.Contains(instant);
})
.ToList();

return Task.FromResult(transactions);
}

/// <inheritdoc />
public Task<List<PlannedTransaction>> GetPlannedTransactions(CancellationToken cancellationToken = default) =>
Task.FromResult(_plannedTransactions.ToList());

/// <inheritdoc />
public Task<List<PlannedTransaction>> GetPlannedTransactions(
Guid scheduleId,
CancellationToken cancellationToken = default) =>
Task.FromResult(_plannedTransactions.Where(transaction => transaction.ScheduleId == scheduleId).ToList());

/// <inheritdoc />
public Task<PlannedTransaction> GetPlannedTransaction(Guid id, CancellationToken cancellationToken = default) =>
Task.FromResult(_plannedTransactions.Single(transaction => transaction.Id == id));

/// <inheritdoc />
public Task<Guid> CreatePlannedTransaction(PlannedTransactionCreation transaction) => throw new NotImplementedException();

/// <inheritdoc />
public Task PutPlannedTransaction(Guid id, PlannedTransactionCreation transaction) => throw new NotImplementedException();

/// <inheritdoc />
public Task DeletePlannedTransaction(Guid id) => throw new NotImplementedException();

/// <inheritdoc />
public Task<List<PlannedTransfer>> GetPlannedTransfers(CancellationToken cancellationToken = default) =>
Task.FromResult(_plannedTransfers.ToList());

/// <inheritdoc />
public Task<List<PlannedTransfer>> GetPlannedTransfers(Guid transactionId, CancellationToken cancellationToken = default) =>
Task.FromResult(_plannedTransfers.Where(transfer => transfer.TransactionId == transactionId).ToList());

/// <inheritdoc />
public Task<PlannedTransfer> GetPlannedTransfer(Guid id, CancellationToken cancellationToken = default) =>
Task.FromResult(_plannedTransfers.Single(transfer => transfer.Id == id));

/// <inheritdoc />
public Task<Guid> CreatePlannedTransfer(PlannedTransferCreation transfer) => throw new NotImplementedException();

/// <inheritdoc />
public Task PutPlannedTransfer(Guid id, PlannedTransferCreation transfer) => throw new NotImplementedException();

/// <inheritdoc />
public Task DeletePlannedTransfer(Guid id) => throw new NotImplementedException();

/// <inheritdoc />
public Task<List<PlannedPurchase>> GetPlannedPurchases(CancellationToken cancellationToken = default) =>
Task.FromResult(_plannedPurchases.ToList());

/// <inheritdoc />
public Task<List<PlannedPurchase>> GetPlannedPurchases(Guid transactionId, CancellationToken cancellationToken = default) =>
Task.FromResult(_plannedPurchases.Where(transfer => transfer.TransactionId == transactionId).ToList());

/// <inheritdoc />
public Task<PlannedPurchase> GetPlannedPurchase(Guid id, CancellationToken cancellationToken = default) =>
Task.FromResult(_plannedPurchases.Single(purchase => purchase.Id == id));

/// <inheritdoc />
public Task<Guid> CreatePlannedPurchase(PlannedPurchaseCreation purchase) => throw new NotImplementedException();

/// <inheritdoc />
public Task PutPlannedPurchase(Guid id, PlannedPurchaseCreation purchase) => throw new NotImplementedException();

/// <inheritdoc />
public Task DeletePlannedPurchase(Guid id) => throw new NotImplementedException();

/// <inheritdoc />
public Task<List<PlannedLoanPayment>> GetPlannedLoanPayments(CancellationToken cancellationToken = default) =>
Task.FromResult(_plannedLoanPayments.ToList());

/// <inheritdoc />
public Task<List<PlannedLoanPayment>> GetPlannedLoanPayments(Guid transactionId, CancellationToken cancellationToken = default) =>
Task.FromResult(_plannedLoanPayments.Where(transfer => transfer.TransactionId == transactionId).ToList());

/// <inheritdoc />
public Task<PlannedLoanPayment> GetPlannedLoanPayment(Guid id, CancellationToken cancellationToken = default) =>
Task.FromResult(_plannedLoanPayments.Single(payment => payment.Id == id));

/// <inheritdoc />
public Task<Guid> CreatePlannedLoanPayment(LoanPaymentCreation loanPayment) => throw new NotImplementedException();

/// <inheritdoc />
public Task PutPlannedLoanPayment(Guid id, LoanPaymentCreation transfer) => throw new NotImplementedException();

/// <inheritdoc />
public Task DeletePlannedLoanPayment(Guid id) => throw new NotImplementedException();

/// <inheritdoc />
[Obsolete]
public Task<List<LegacyLoan>> GetLegacyLoans(CancellationToken cancellationToken = default) =>
Expand Down
2 changes: 1 addition & 1 deletion source/Gnomeshade.Avalonia.Core/Loans/LoanPaymentRow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public sealed class LoanPaymentRow : PropertyChangedBase
/// <param name="payment">The payment which this row will represent.</param>
/// <param name="loans">All available loans.</param>
/// <param name="currencies">All available currencies.</param>
public LoanPaymentRow(LoanPayment payment, IEnumerable<Loan> loans, IEnumerable<Currency> currencies)
public LoanPaymentRow(LoanPaymentBase payment, IEnumerable<Loan> loans, IEnumerable<Currency> currencies)
{
var loan = loans.Single(loan => loan.Id == payment.LoanId);
Loan = loan.Name;
Expand Down
Loading

0 comments on commit 65cc97d

Please sign in to comment.