Implement Phase 6: automated bank sync (Plaid + SimpleFIN) & settings
Add automated transaction syncing via Plaid and SimpleFIN providers, a Settings page for managing connections and account mappings, background scheduled syncing, and sync history logging. New backend: BankSync plugin project with PlaidSyncProvider and SimpleFinSyncProvider, SyncConnection/LinkedAccount/SyncLog models, AES-256 encryption service, BankSyncService orchestration, BankSyncBackgroundService (15-min tick), and BankSyncController (13 endpoints). EF migration creates sync_connections, linked_accounts, and sync_logs tables. New frontend: Settings view with 3 tabs (Profile, Bank Connections, Sync History), bankSync API service, BankSyncComplete SignalR notifications, and Settings nav item in sidebar + avatar dropdown. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -25,4 +25,5 @@ public class Account
|
||||
public ICollection<Transaction> Transactions { get; set; } = new List<Transaction>();
|
||||
public ICollection<InvestmentHolding> InvestmentHoldings { get; set; } = new List<InvestmentHolding>();
|
||||
public ICollection<Reconciliation> Reconciliations { get; set; } = new List<Reconciliation>();
|
||||
public ICollection<LinkedAccount> LinkedAccounts { get; set; } = new List<LinkedAccount>();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace Purrse.Core.Models;
|
||||
|
||||
public class LinkedAccount
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid SyncConnectionId { get; set; }
|
||||
public Guid? AccountId { get; set; }
|
||||
public string ExternalAccountId { get; set; } = string.Empty;
|
||||
public string ExternalAccountName { get; set; } = string.Empty;
|
||||
public string? ExternalAccountType { get; set; }
|
||||
public string? ExternalAccountMask { get; set; }
|
||||
public decimal? LastKnownBalance { get; set; }
|
||||
public bool IsEnabled { get; set; } = true;
|
||||
public DateTime? LastSyncAt { get; set; }
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
|
||||
public SyncConnection SyncConnection { get; set; } = null!;
|
||||
public Account? Account { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using Purrse.Core.Enums;
|
||||
|
||||
namespace Purrse.Core.Models;
|
||||
|
||||
public class SyncConnection
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid UserId { get; set; }
|
||||
public SyncProvider Provider { get; set; }
|
||||
public string InstitutionName { get; set; } = string.Empty;
|
||||
public string? InstitutionId { get; set; }
|
||||
public string EncryptedAccessToken { get; set; } = string.Empty;
|
||||
public string? PlaidItemId { get; set; }
|
||||
public bool IsActive { get; set; } = true;
|
||||
public int SyncIntervalMinutes { get; set; } = 360;
|
||||
public DateTime? LastSyncAt { get; set; }
|
||||
public string? LastSyncError { get; set; }
|
||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
|
||||
|
||||
public User User { get; set; } = null!;
|
||||
public ICollection<LinkedAccount> LinkedAccounts { get; set; } = new List<LinkedAccount>();
|
||||
public ICollection<SyncLog> SyncLogs { get; set; } = new List<SyncLog>();
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using Purrse.Core.Enums;
|
||||
|
||||
namespace Purrse.Core.Models;
|
||||
|
||||
public class SyncLog
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid SyncConnectionId { get; set; }
|
||||
public Guid? LinkedAccountId { get; set; }
|
||||
public SyncStatus Status { get; set; }
|
||||
public int TransactionsFetched { get; set; }
|
||||
public int TransactionsImported { get; set; }
|
||||
public int TransactionsSkipped { get; set; }
|
||||
public string? ErrorMessage { get; set; }
|
||||
public DateTime StartedAt { get; set; }
|
||||
public DateTime? CompletedAt { get; set; }
|
||||
public TimeSpan? Duration { get; set; }
|
||||
|
||||
public SyncConnection SyncConnection { get; set; } = null!;
|
||||
public LinkedAccount? LinkedAccount { get; set; }
|
||||
}
|
||||
@@ -12,4 +12,5 @@ public class User
|
||||
public DateTime? RefreshTokenExpiresAt { get; set; }
|
||||
|
||||
public ICollection<Account> Accounts { get; set; } = new List<Account>();
|
||||
public ICollection<SyncConnection> SyncConnections { get; set; } = new List<SyncConnection>();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user