Some checks failed
Build Linux / build (push) Failing after 24s
Features Analytics Page: Full-featured analytics dashboard with KPI cards, cash flow trend chart, net worth progression, spending patterns by day-of-week, top spending categories, and income sources breakdown. Includes PDF export via QuestPDF for selected periods. Implemented on both desktop and mobile (simplified). Auth Error Handling: Map Supabase GotrueException errors to AuthError enum with user-friendly messages for login and signup. Display errors in sign-in and sign-up panels. Dynamic Transaction/Account Counts: Replace hardcoded "46 transactions" and "4 accounts" text with FilteredTransactionCount and ActiveAccountCount properties bound to actual data. Fixes Budget Period Navigation: Fix year-aware date comparison in CanGoToPreviousPeriod and CanGoToNextPeriod. Previously only compared months, preventing navigation before January of current year. Changes AnalyticsViewModel: Period selector, KPI calculations, chart data builders (cash flow, net worth, day-of-week, top categories, income sources), PDF export PdfExportService: QuestPDF report generation with print-optimized styling AuthViewModel: Error display with GotrueException mapping BudgetViewModel: Year-aware period navigation TransactionsViewModel: FilteredTransactionCount property AccountsViewModel: ActiveAccountCount property MainViewModel: Analytics navigation and AnalyticsViewModel integration Views: Analytics button wired, error messages displayed, count bindings updated
57 lines
2.2 KiB
C#
57 lines
2.2 KiB
C#
using System;
|
|
using System.Linq;
|
|
using Clario.Data;
|
|
using Clario.Services;
|
|
using Newtonsoft.Json;
|
|
using Supabase.Postgrest.Attributes;
|
|
using Supabase.Postgrest.Models;
|
|
|
|
namespace Clario.Models;
|
|
|
|
[Table("transactions")]
|
|
public class Transaction : BaseModel
|
|
{
|
|
[PrimaryKey("id", false)] public Guid Id { get; set; }
|
|
|
|
[Column("user_id")] public Guid UserId { get; set; }
|
|
|
|
[Column("account_id")] public Guid AccountId { get; set; }
|
|
|
|
[Column("category_id")] public Guid? CategoryId { get; set; }
|
|
|
|
[JsonIgnore] public Category? Category { get; set; }
|
|
|
|
[Column("amount")] public decimal Amount { get; set; }
|
|
|
|
[Column("type")] public string Type { get; set; } = string.Empty; // "income" or "expense"
|
|
|
|
[Column("description")] public string Description { get; set; } = string.Empty;
|
|
|
|
[Column("note")] public string? Note { get; set; }
|
|
|
|
[Column("date")] public DateTime Date { get; set; }
|
|
|
|
[Column("created_at")] public DateTime CreatedAt { get; set; }
|
|
|
|
[Column("exchange_rate")] public decimal? ExchangeRate { get; set; }
|
|
|
|
[Column("transfer_pair_id")] public Guid? TransferPairId { get; set; }
|
|
|
|
// Set during enrichment by GeneralDataRepo.LinkTransactionAccounts
|
|
[JsonIgnore] public string AccountCurrency { get; set; } = "";
|
|
[JsonIgnore] public string PrimaryAmountFormatted { get; set; } = "";
|
|
[JsonIgnore] public string OriginalAmountFormatted { get; set; } = "";
|
|
[JsonIgnore] public string AccountDisplayText { get; set; } = "";
|
|
|
|
[JsonIgnore] public decimal ConvertedAmount =>
|
|
!string.IsNullOrEmpty(AccountCurrency) && CurrencyService.LiveRates.TryGetValue(AccountCurrency, out var liveRate)
|
|
? Amount * liveRate
|
|
: (ExchangeRate.HasValue ? Amount * ExchangeRate.Value : Amount);
|
|
[JsonIgnore] public bool IsMultiCurrency { get; set; }
|
|
[JsonIgnore] public string PrimaryAmountSignFormatted =>
|
|
Type == "expense" ? $"-{PrimaryAmountFormatted}" : $"+{PrimaryAmountFormatted}";
|
|
|
|
[JsonIgnore] public bool IsTransfer => Type is "transfer_in" or "transfer_out";
|
|
[JsonIgnore] public bool IsTransferOut => Type == "transfer_out";
|
|
[JsonIgnore] public bool GroupHeader { get; set; } = false;
|
|
} |