Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jsmarble/YNAB.Rest
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 1.2
Choose a base ref
...
head repository: jsmarble/YNAB.Rest
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
  • 8 commits
  • 6 files changed
  • 7 contributors

Commits on Mar 18, 2024

  1. Resolved issue of missing enum values for GoalTypes (used in Categori…

    …es) (#22)
    
    Co-authored-by: Randy Gamage <[email protected]>
    rgamage and rgamage-tfmc authored Mar 18, 2024
    Copy the full SHA
    f1df294 View commit details
  2. Resolve issue #23 - GetScheduledTransaction error (#24)

    * Resolved issue of missing enum values for GoalTypes (used in Categories)
    
    * resolve issue #23 - GetScheduledTransaction error
    
    ---------
    
    Co-authored-by: Randy Gamage <[email protected]>
    Co-authored-by: Joshua Marble <[email protected]>
    3 people authored Mar 18, 2024
    Copy the full SHA
    401a79f View commit details

Commits on Apr 5, 2024

  1. Correctly deserialize subtransactions (#25)

    briandadams85 authored Apr 5, 2024
    Copy the full SHA
    09b348c View commit details
  2. Add Debt Transaction Type field (#28)

    briandadams85 authored Apr 5, 2024
    Copy the full SHA
    f596ca0 View commit details
  3. Add MatchedTransactionId field (#26)

    Co-authored-by: Joshua Marble <[email protected]>
    briandadams85 and jsmarble authored Apr 5, 2024
    Copy the full SHA
    9cb232f View commit details
  4. Add FlagName field (#27)

    briandadams85 authored Apr 5, 2024
    Copy the full SHA
    a0451ba View commit details
  5. Rgamage category model (#30)

    +semver: minor
    
    * Add missing Category properties (#29)
    
    * Resolved issue of missing enum values for GoalTypes (used in Categories)
    
    * resolve issue #23 - GetScheduledTransaction error
    
    * added missing Category model properties
    
    * updated Category model
    
    ---------
    
    Co-authored-by: Randy Gamage <[email protected]>
    Co-authored-by: Joshua Marble <[email protected]>
    
    * change goal_target_month to datetime
    
    * improve console exercises
    
    ---------
    
    Co-authored-by: Randy Gamage <[email protected]>
    Co-authored-by: Randy Gamage <[email protected]>
    3 people authored Apr 5, 2024
    Copy the full SHA
    ad944e7 View commit details

Commits on Sep 4, 2024

  1. Fix typo in GetPayee (#31)

    * Fix typo in GetPayee
    
    * Fix GetScheduledTransaction
    Add PostScheduledTransaction
    Add DeleteTransaction
    
    * Update YNAB.Rest/IApiClient.cs
    
    Co-authored-by: Joshua Marble <[email protected]>
    
    * Update YNAB.Rest/IApiClient.cs
    
    Co-authored-by: Joshua Marble <[email protected]>
    
    ---------
    
    Co-authored-by: Jacob Draddy <[email protected]>
    Co-authored-by: Joshua Marble <[email protected]>
    3 people authored Sep 4, 2024
    Copy the full SHA
    9697b17 View commit details
Showing with 309 additions and 217 deletions.
  1. +192 −151 YNAB.Rest.Console/Program.cs
  2. +74 −55 YNAB.Rest/Category.cs
  3. +1 −0 YNAB.Rest/Extensions.cs
  4. +24 −7 YNAB.Rest/IApiClient.cs
  5. +8 −4 YNAB.Rest/ScheduledTransaction.cs
  6. +10 −0 YNAB.Rest/Transaction.cs
343 changes: 192 additions & 151 deletions YNAB.Rest.Console/Program.cs
Original file line number Diff line number Diff line change
@@ -1,151 +1,192 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using YNAB.Rest;

namespace YNAB.RestConsole
{
class Program
{
private const string ACCESS_TOKEN_FILE = "accessToken";

public static async Task Main(string[] args)
{
try
{
HttpClientHandler httpClientHandler = new HttpClientHandler();
//httpClientHandler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;

string token = await GetAccessToken();

var api = ApiClientFactory.Create(token, () => new HttpClient(httpClientHandler));
var budgetsResponse = await api.GetBudgets();
var budgets = budgetsResponse.Data.Budgets;

if (budgets.Count == 0)
throw new InvalidOperationException("No budgets found!");

Console.WriteLine($"Found {budgets.Count} budgets!");
Console.WriteLine();

budgets.ToList().ForEach(b => Console.WriteLine(b.Name));
Console.WriteLine();

var budget = budgets.FirstOrDefault(x => x.Name == "Dev Budget");
Console.WriteLine($"Reading budget {budget.Name} ({budget.Id})");
Console.WriteLine();

var budgetDetails = await api.GetBudget(budget.Id, 115);
Console.WriteLine($"server knowledge: {budgetDetails.Data.ServerKnowledge}");
Console.WriteLine();

var accountsResponse = await api.GetAccounts(budget.Id);
var accounts = accountsResponse.Data.Accounts;
Console.WriteLine($"Found {accounts.Count} accounts!");
Console.WriteLine();

var account = accounts.OrderByDescending(x => x.Balance).FirstOrDefault();
Console.WriteLine($"Reading account {account.Name} ({account.Id}) with balance {account.Balance.YnabIntToDecimal()}");
Console.WriteLine();

var transactionsResponse = await api.GetTransactionsByAccount(budget.Id, account.Id);
var transactions = transactionsResponse.Data.Transactions;
Console.WriteLine($"Found {transactions.Count} transactions!");
Console.WriteLine();

transactions.ToList().ForEach(x => Console.WriteLine($"{x.Id} | {x.PayeeName} | {x.CategoryName} | {x.Memo} | {x.Amount.YnabIntToDecimal():C2} | {x.FlagColor}"));

transactions = new List<Transaction>
{
new Transaction
{
PayeeName = "Test1",
Amount = Convert.ToInt32(108.41 * 1000),
Memo = "This is test 1",
AccountId = account.Id,
Date = new DateTime(2018, 01, 15),
Cleared = ClearedStatus.Cleared
},
new Transaction
{
PayeeName="Test2",
Amount = Convert.ToInt32(208.42 * 1000),
Memo="This is test 2",
AccountId = account.Id,
Date = new DateTime(2018, 02, 15),
Cleared = ClearedStatus.Uncleared
},
new Transaction
{
PayeeName = "Test3",
Amount = Convert.ToInt32(308.43 * 1000),
Memo = "This is test 3",
AccountId = account.Id,
Date = new DateTime(2018, 03, 15),
Cleared = ClearedStatus.Uncleared
}
};

Console.WriteLine($"Posting {transactions.Count} transactions ...");
PostBulkTransactions bulk = new PostBulkTransactions { Transactions = transactions };
var result = await api.PostBulkTransactions(budget.Id, bulk);
Console.WriteLine("Duplicate import IDs: " + string.Join(", ", result.Data.Bulk.DuplicateImportIds));
Console.WriteLine("Transaction IDs: " + string.Join(", ", result.Data.Bulk.TransactionIds));

Console.WriteLine("Posting a single transaction ...");
TransactionBody post = new TransactionBody
{
Transaction = new Transaction
{
PayeeName = "Test123",
Amount = Convert.ToInt32(123.45 * 1000),
Memo = "This is test 123",
AccountId = account.Id,
Date = new DateTime(2018, 01, 23),
Cleared = ClearedStatus.Cleared
}
};
var t = (await api.PostTransaction(budget.Id, post)).Data.Transaction;
Console.WriteLine($"Posted Transaction with ID {t.Id}.");

t.Memo = "updated through PUT";
await api.PutTransaction(budget.Id, t.Id, new TransactionBody { Transaction = t });

var payeesResponse = await api.GetPayees(budget.Id);
var payees = payeesResponse.Data.Payees;
Console.WriteLine($"Found {payees.Count} payees!");
Console.WriteLine();

payees.ToList().ForEach(p => Console.WriteLine($"{p.Id} | {p.Name}"));
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}

Console.WriteLine();
Console.WriteLine("Press Enter to exit ...");
Console.ReadLine();
}

private static async Task<string> GetAccessToken()
{
string apiToken = null;

if (File.Exists(ACCESS_TOKEN_FILE))
{
apiToken = await File.ReadAllTextAsync(ACCESS_TOKEN_FILE);
}
else
{
Console.Write("YNAB API Access Token: ");
apiToken = Console.ReadLine();
}

return apiToken;
}
}
}
using Refit;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using YNAB.Rest;

namespace YNAB.RestConsole
{
class Program
{
private const string ACCESS_TOKEN_FILE = "accessToken";

public static async Task Main(string[] args)
{
try
{
HttpClientHandler httpClientHandler = new HttpClientHandler();

//to intercept traffic with http toolkit (https://httptoolkit.com)
httpClientHandler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
httpClientHandler.Proxy = new WebProxy("http://localhost:8000");

string token = await GetAccessToken();

var api = ApiClientFactory.Create(token, () => new HttpClient(httpClientHandler));
var budgetsResponse = await api.GetBudgets();
var budgets = budgetsResponse.Data.Budgets;

if (budgets.Count == 0)
throw new InvalidOperationException("No budgets found!");

Console.WriteLine($"Found {budgets.Count} budgets!");
Console.WriteLine();

budgets.ToList().ForEach(b => Console.WriteLine(b.Name));
Console.WriteLine();

var budget = budgets.FirstOrDefault(x => x.Name == "Dev Budget");
Console.WriteLine($"Reading budget {budget.Name} ({budget.Id})");
Console.WriteLine();

var budgetDetails = await api.GetBudget(budget.Id, 115);
Console.WriteLine($"server knowledge: {budgetDetails.Data.ServerKnowledge}");
Console.WriteLine();

var accountsResponse = await api.GetAccounts(budget.Id);
var accounts = accountsResponse.Data.Accounts;
Console.WriteLine($"Found {accounts.Count} accounts!");
Console.WriteLine();

var account = accounts.OrderByDescending(x => x.Balance).FirstOrDefault();
Console.WriteLine($"Reading account {account.Name} ({account.Id}) with balance {account.Balance.YnabIntToDecimal()}");
Console.WriteLine();

var transactionsResponse = await api.GetTransactionsByAccount(budget.Id, account.Id);
var transactions = transactionsResponse.Data.Transactions;
Console.WriteLine($"Found {transactions.Count} transactions!");
Console.WriteLine();

transactions.ToList().ForEach(x => Console.WriteLine($"{x.Id} | {x.PayeeName} | {x.CategoryName} | {x.Memo} | {x.Amount.YnabIntToDecimal():C2} | {x.FlagColor}"));

transactions = new List<Transaction>
{
new Transaction
{
PayeeName = "Test1",
Amount = Convert.ToInt32(108.41 * 1000),
Memo = "This is test 1",
AccountId = account.Id,
Date = DateTime.Today.AddDays(-2),
Cleared = ClearedStatus.Cleared
},
new Transaction
{
PayeeName="Test2",
Amount = Convert.ToInt32(208.42 * 1000),
Memo="This is test 2",
AccountId = account.Id,
Date = DateTime.Today.AddDays(-3),
Cleared = ClearedStatus.Uncleared
},
new Transaction
{
PayeeName = "Test3",
Amount = Convert.ToInt32(308.43 * 1000),
Memo = "This is test 3",
AccountId = account.Id,
Date = DateTime.Today.AddDays(-4),
Cleared = ClearedStatus.Uncleared
}
};

Console.WriteLine($"Posting {transactions.Count} transactions ...");
PostBulkTransactions bulk = new PostBulkTransactions { Transactions = transactions };
var result = await api.PostBulkTransactions(budget.Id, bulk);
Console.WriteLine("Duplicate import IDs: " + string.Join(", ", result.Data.Bulk.DuplicateImportIds));
Console.WriteLine("Transaction IDs: " + string.Join(", ", result.Data.Bulk.TransactionIds));

Console.WriteLine("Posting a single transaction ...");
TransactionBody post = new TransactionBody
{
Transaction = new Transaction
{
PayeeName = "Test123",
Amount = Convert.ToInt32(123.45 * 1000),
Memo = "This is test 123",
AccountId = account.Id,
Date = DateTime.Today.AddDays(-1),
Cleared = ClearedStatus.Cleared
}
};
var t = (await api.PostTransaction(budget.Id, post)).Data.Transaction;
Console.WriteLine($"Posted Transaction with ID {t.Id}.");

t.Memo = "updated through PUT";
await api.PutTransaction(budget.Id, t.Id, new TransactionBody { Transaction = t });

var payeesResponse = await api.GetPayees(budget.Id);
var payees = payeesResponse.Data.Payees;
Console.WriteLine($"Found {payees.Count} payees!");
Console.WriteLine();

payees.ToList().ForEach(p => Console.WriteLine($"{p.Id} | {p.Name}"));

Console.WriteLine($"Fetching Categories...");
var categoryResponse = await api.GetCategories(budget.Id);
var categoryGroups = categoryResponse.Data.CategoryGroups;
Console.WriteLine($"Found {categoryGroups.Count} category groups!");
Console.WriteLine();
categoryGroups.ToList().ForEach(p => Console.WriteLine($"{p.Id} | {p.Name}"));
var categories = categoryGroups.SelectMany(p => p.Categories).OrderBy(x => x.CategoryGroupId).ThenBy(x => x.Name).ToList();
Console.WriteLine($"Found {categories.Count} categories!");
Console.WriteLine();
categories.ToList().ForEach(p => Console.WriteLine($"{p.Id} | {p.Name}"));

var catWithGoal = categories.FirstOrDefault(x => x.GoalType.HasValue);
var catWithoutGoal = categories.FirstOrDefault(x => !x.GoalType.HasValue);
if (catWithGoal != null)
Console.WriteLine($"{catWithGoal.Id} | {catWithGoal.GoalType} | {catWithGoal.GoalTargetMonth}");
else
Console.WriteLine("No category with goals!");

if (catWithoutGoal != null)
Console.WriteLine($"{catWithoutGoal.Id} | {catWithoutGoal.GoalType} | {catWithoutGoal.GoalTargetMonth}");
else
await Console.Out.WriteLineAsync("No category without goals!");

Console.WriteLine("Getting scheduled transactions...");
var scheduledTransactionsResponse = await api.GetScheduledTransactions(budget.Id);
var scheduledTransactions = scheduledTransactionsResponse.Data.ScheduledTransactions.Where(x => !x.Deleted).ToList();
Console.WriteLine($"Found {scheduledTransactions.Count} scheduled transactions!");
Console.WriteLine();

scheduledTransactions.ToList().ForEach(x => Console.WriteLine($"{x.Id} | {x.PayeeId} | {x.CategoryId} | {x.Amount.YnabLongToDecimal():C2} | {x.FlagColor}"));
}
catch (ApiException apiEx)
{
Console.WriteLine("Error: " + apiEx.Content);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}

Console.WriteLine();
Console.WriteLine("Press Enter to exit ...");
Console.ReadLine();
}

private static async Task<string> GetAccessToken()
{
string apiToken = null;

if (File.Exists(ACCESS_TOKEN_FILE))
{
apiToken = await File.ReadAllTextAsync(ACCESS_TOKEN_FILE);
apiToken = apiToken.Trim();
}
else
{
Console.Write("YNAB API Access Token: ");
apiToken = Console.ReadLine();
}

return apiToken;
}
}
}
Loading