feat: add Plaid transaction handling and async queue processing

- introduced new migration to add Cursor column to AccountMetadata.
- updated AppDbContext model snapshot to reflect changes in the database schema.
- implemented async queue processing with ChannelAsyncQueue and AsyncQueueHostedService.
- created Plaid transaction handlers for added, modified, and removed transactions.
- developed PlaidTransactionService and PlaidTransactionSyncer for syncing transactions.
- added SyncUpdatesProcessor to handle sync updates from Plaid.
- updated tests to accommodate changes in institution and account metadata handling.
This commit is contained in:
Stevan Freeborn
2026-03-09 04:29:01 -05:00
parent 48e95e5242
commit a9f1ced0d5
62 changed files with 3625 additions and 68 deletions
@@ -172,7 +172,7 @@ public class AddTests(TestApi testApi) : IntegrationTest(testApi)
await context.AddAsync(user, ct);
var encryptedAccessToken = await encryptor.EncryptAsyncFor(user, "accessToken", ct);
var plaidMetadata = PlaidMetadata.From("alreadyExists", "Some Bank", encryptedAccessToken);
var plaidMetadata = PlaidInstitutionMetadata.From("alreadyExists", "Some Bank", encryptedAccessToken);
var institution = Institution.From("Some Bank", plaidMetadata);
await context.AddAsync(institution, ct);
@@ -192,7 +192,7 @@ public class AddTests(TestApi testApi) : IntegrationTest(testApi)
.WithUserId(user.Id)
.WithBody(new
{
plaidInstitutionId = ((PlaidMetadata)institution.Metadata!).PlaidId,
plaidInstitutionId = ((PlaidInstitutionMetadata)institution.Metadata!).PlaidId,
plaidAccountId = ((PlaidAccountMetadata)account.Metadata!).PlaidId,
plaidAccountName = ((PlaidAccountMetadata)account.Metadata).PlaidName,
accountCurrencyCode = "USD",
@@ -217,7 +217,7 @@ public class AddTests(TestApi testApi) : IntegrationTest(testApi)
var user = User.From("User1", passwordHasher.Hash("@Password1"), userEncryptionKey);
var encryptedAccessToken = await encryptor.EncryptAsyncFor(user, "accessToken", ct);
var plaidMetadata = PlaidMetadata.From("id", "Some Bank", encryptedAccessToken);
var plaidMetadata = PlaidInstitutionMetadata.From("id", "Some Bank", encryptedAccessToken);
var institution = Institution.From("Some Bank", plaidMetadata);
user.AddInstitution(institution);
@@ -237,7 +237,7 @@ public class AddTests(TestApi testApi) : IntegrationTest(testApi)
.WithUserId(user.Id)
.WithBody(new
{
plaidInstitutionId = ((PlaidMetadata)institution.Metadata!).PlaidId,
plaidInstitutionId = ((PlaidInstitutionMetadata)institution.Metadata!).PlaidId,
plaidAccountId = newAccountId,
plaidAccountName = newAccountName,
accountCurrentBalance = expectedBalance,