Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions TransactionQL.sln
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "TransactionQL.Build", "src\
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "TransactionQL.Plugins.Amex", "src\TransactionQL.Plugins.Amex\TransactionQL.Plugins.Amex.fsproj", "{11ACCFD8-1CF6-4F56-B822-A661A289774C}"
EndProject
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "TransactionQL.Plugins.Triodos", "src\TransactionQL.Plugins.Triodos\TransactionQL.Plugins.Triodos.fsproj", "{1B99474E-7F10-4CE1-ACF6-1D6D3047D1F1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -106,6 +108,10 @@ Global
{11ACCFD8-1CF6-4F56-B822-A661A289774C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{11ACCFD8-1CF6-4F56-B822-A661A289774C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{11ACCFD8-1CF6-4F56-B822-A661A289774C}.Release|Any CPU.Build.0 = Release|Any CPU
{1B99474E-7F10-4CE1-ACF6-1D6D3047D1F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1B99474E-7F10-4CE1-ACF6-1D6D3047D1F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1B99474E-7F10-4CE1-ACF6-1D6D3047D1F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1B99474E-7F10-4CE1-ACF6-1D6D3047D1F1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -115,6 +121,7 @@ Global
{32027311-05E4-465B-9F5A-F5C59768B99A} = {B645AC52-7FA5-47ED-8162-E39B705813C6}
{F6F92978-83BF-4DB9-B513-2B8ABD22AC5F} = {B645AC52-7FA5-47ED-8162-E39B705813C6}
{11ACCFD8-1CF6-4F56-B822-A661A289774C} = {B645AC52-7FA5-47ED-8162-E39B705813C6}
{1B99474E-7F10-4CE1-ACF6-1D6D3047D1F1} = {B645AC52-7FA5-47ED-8162-E39B705813C6}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {55AA355A-8CC6-47CA-BEAB-C07FDEFB4BAB}
Expand Down
1 change: 1 addition & 0 deletions build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dotnet run --project .\src\TransactionQL.Build\TransactionQL.Build.fsproj -t Complete
2 changes: 1 addition & 1 deletion src/TransactionQL.Build/build.fs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ let initTargets () =
Directory.create (stagingDirectory </> "plugins")
Directory.create (stagingDirectory </> "desktop")

let plugins = ["ASN"; "Bunq"; "ING"; "Amex"]
let plugins = ["ASN"; "Bunq"; "ING"; "Amex"; "Triodos"]
let src = plugins |> List.map (fun p -> buildDirectory </> "plugins" </> $"TransactionQL.Plugins.{p}.dll")
let dst = plugins |> List.map (fun p -> stagingDirectory </> "plugins" </> $"{String.toLower p}.dll")

Expand Down
28 changes: 15 additions & 13 deletions src/TransactionQL.Build/tql.iss
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,23 @@ Name: "cli-only"; Description: "Just the CLI"
Name: "Custom"; Description: "Custom installation"; Flags: iscustom

[Components]
Name: "CLI"; Description: "Command Line Interface (tql.exe)"; Types: full cli-only custom;
Name: "GUI"; Description: "Graphical User Interface (Ledger Leo)"; Types: full custom;
Name: "Plugins"; Description: "Transaction Parsers"; Types: full custom;
Name: "Plugins\ASN"; Description: "ASN"; Types: full cli-only custom; Flags: checkablealone
Name: "Plugins\Bunq"; Description: "Bunq"; Types: full cli-only custom; Flags: checkablealone
Name: "Plugins\ING"; Description: "ING"; Types: full cli-only custom; Flags: checkablealone
Name: "Plugins\Amex"; Description: "American Express"; Types: full cli-only custom; Flags: checkablealone
Name: "CLI"; Description: "Command Line Interface (tql.exe)"; Types: full cli-only custom;
Name: "GUI"; Description: "Graphical User Interface (Ledger Leo)"; Types: full custom;
Name: "Plugins"; Description: "Transaction Parsers"; Types: full custom;
Name: "Plugins\ASN"; Description: "ASN"; Types: full cli-only custom; Flags: checkablealone
Name: "Plugins\Amex"; Description: "American Express"; Types: full cli-only custom; Flags: checkablealone
Name: "Plugins\Bunq"; Description: "Bunq"; Types: full cli-only custom; Flags: checkablealone
Name: "Plugins\ING"; Description: "ING"; Types: full cli-only custom; Flags: checkablealone
Name: "Plugins\Triodos"; Description: "Triodos"; Types: full cli-only custom; Flags: checkablealone

[Files]
Source: "{#Staging}\desktop\*"; Components: GUI; DestDir: "{app}\app"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "{#Staging}\tql.exe"; Components: CLI; DestDir: "{app}"; DestName: "tql.exe"; Flags: ignoreversion
Source: "{#Staging}\plugins\asn.dll"; Components: Plugins\ASN; DestDir: "{app}\plugins"; DestName: "asn.dll"; Flags: ignoreversion
Source: "{#Staging}\plugins\bunq.dll"; Components: Plugins\Bunq; DestDir: "{app}\plugins"; DestName: "bunq.dll"; Flags: ignoreversion
Source: "{#Staging}\plugins\ing.dll"; Components: Plugins\ING; DestDir: "{app}\plugins"; DestName: "ing.dll"; Flags: ignoreversion
Source: "{#Staging}\plugins\amex.dll"; Components: Plugins\Amex; DestDir: "{app}\plugins"; DestName: "amex.dll"; Flags: ignoreversion
Source: "{#Staging}\desktop\*"; Components: GUI; DestDir: "{app}\app"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "{#Staging}\tql.exe"; Components: CLI; DestDir: "{app}"; DestName: "tql.exe"; Flags: ignoreversion
Source: "{#Staging}\plugins\amex.dll"; Components: Plugins\Amex; DestDir: "{app}\plugins"; DestName: "amex.dll"; Flags: ignoreversion
Source: "{#Staging}\plugins\asn.dll"; Components: Plugins\ASN; DestDir: "{app}\plugins"; DestName: "asn.dll"; Flags: ignoreversion
Source: "{#Staging}\plugins\bunq.dll"; Components: Plugins\Bunq; DestDir: "{app}\plugins"; DestName: "bunq.dll"; Flags: ignoreversion
Source: "{#Staging}\plugins\ing.dll"; Components: Plugins\ING; DestDir: "{app}\plugins"; DestName: "ing.dll"; Flags: ignoreversion
Source: "{#Staging}\plugins\triodos.dll"; Components: Plugins\triodos; DestDir: "{app}\plugins"; DestName: "triodos.dll"; Flags: ignoreversion
; NOTE: Don't use "Flags: ignoreversion" on any shared system files

[Icons]
Expand Down
2 changes: 1 addition & 1 deletion src/TransactionQL.DesktopApp/Assets/Styles.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
<Style Selector="Button.IconAction /template/ ContentPresenter">
<Setter Property="BoxShadow" Value="none" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{DynamicResource FG.Base.Primary}" />
<Setter Property="Foreground" Value="{DynamicResource FG.Base.Neutral}" />
<Setter Property="FontSize" Value="16" />
<Setter Property="Transitions">
<Transitions>
Expand Down
2 changes: 1 addition & 1 deletion src/TransactionQL.DesktopApp/DesignData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public static class DesignData

public static readonly MessageDialogViewModel Popup = new()
{
Message = "This is a preview message.",
Message = "This is a preview message. With a bit more extra text to make sure we see some line wrapping too.",
Title = "Preview Title",
IsError = false,
Icon = DialogIcon.Success,
Expand Down
38 changes: 35 additions & 3 deletions src/TransactionQL.DesktopApp/ViewModels/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Windows.Input;
Expand Down Expand Up @@ -105,12 +106,43 @@ public ISelectAccounts AccountSelector

public bool IsDone => _numberOfValidTransactions == BankTransactions.Count;


internal void Parse(SelectedData data)
{
try
{
this.ParseUnsafe(data);
}
catch (IOException e) when (e.Message.Contains("it is being used by another process"))
{
ErrorThrown?.Invoke(this, new()
{
Message = "One of the selected files is opened elsewhere. Please close it first.",
Title = "Error",
IsError = true,
});
return;
}
catch (Exception e)
{
ErrorThrown?.Invoke(this, new()
{
Message = "Unexpected error encountered while opening files. Please consider filing a bug report.\r\n\r\n" + e.Message,
Title = "Unexpected Error",
IsError = true,
});
return;
}
}

private void ParseUnsafe(SelectedData data)
{
AccountSelector = FilewatchingAccountSelector.Monitor(data.AccountsFile, Dispatcher.UIThread.Invoke).Result;
var loader = new DataLoader(
TransactionQLApiAdapter.Instance, FilesystemStreamer.Instance, AccountSelector, Configuration.createAndGetPluginDir);

DataLoader loader = new(
TransactionQLApiAdapter.Instance,
FilesystemStreamer.Instance,
AccountSelector,
Configuration.createAndGetPluginDir);

if (!loader.TryLoadData(data, out var ps, out var errorMessage))
{
Expand Down
6 changes: 4 additions & 2 deletions src/TransactionQL.DesktopApp/Views/MessageDialog.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@
Margin="0 30 0 20" />

<TextBlock Text="{Binding Title}"
TextAlignment="Center" Classes="h2" />
TextAlignment="Center" Classes="h2"
Margin="20 0 20 0"/>
<TextBlock Text="{Binding Message}"
TextAlignment="Center"
Foreground="{DynamicResource FG.Elevated.Neutral}"
TextWrapping="Wrap" />
TextWrapping="Wrap"
Margin="20 0 20 0"/>
<Button Click="Button_OnClick"
HorizontalAlignment="Stretch"
Classes.Negative="{Binding IsError}"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyTitle>Triodos</AssemblyTitle>
</PropertyGroup>

<ItemGroup>
<None Include="triodos.csv" />
<Compile Include="Triodos.fs" />
</ItemGroup>

<ItemGroup />

<ItemGroup>
<ProjectReference Include="..\TransactionQL.Input\TransactionQL.Input.fsproj" />
<ProjectReference Include="..\TransactionQL.Parser\TransactionQL.Parser.fsproj" />
<ProjectReference Include="..\TransactionQL.Shared\TransactionQL.Shared.fsproj" />
</ItemGroup>

</Project>
58 changes: 58 additions & 0 deletions src/TransactionQL.Plugins.Triodos/Triodos.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
namespace TransactionQL.Plugins

open System
open System.Globalization
open FSharp.Data
open TransactionQL.Parser.AST
open TransactionQL.Parser.QLInterpreter
open TransactionQL.Input.Converters
open TransactionQL.Shared.Disposables

module Triodos =

let private dateFormat = "dd-MM-yyyy"

type TriodosTransactions = CsvProvider<"triodos.csv">

type TriodosReader() =
let toMap (row: TriodosTransactions.Row) =
let amount =
-1m * Decimal.Parse(row.Bedrag, NumberStyles.AllowLeadingSign ||| NumberStyles.AllowDecimalPoint)

let isSent = row.``Credit/Debet`` = "Debet"

Map.ofList
[ ("Sender", (if isSent then row.Rekening else row.Tegenrekening))
("Receiver", (if isSent then row.Tegenrekening else row.Rekening))
("Amount",
row.Bedrag.Replace(".", "")
|> fun amount -> if isSent then $"-%s{amount}" else amount)
("Total", row.Bedrag.Replace(".", ""))
("Date", row.Transactiedatum)
("Description", $"[{row.Transactiecode}] {row.Omschrijving}")
("Name", row.``Naam Tegenrekening``) ]

interface IConverter with
member this.DateFormat = dateFormat

member this.Read lines =
using (Disposables.changeCulture "nl-NL") (fun _ ->
lines |> TriodosTransactions.ParseRows |> Array.map toMap
)

member this.Map row =
let fromRow col = Map.find col row

{ Header =
Header(
DateTime.ParseExact(fromRow "Date", dateFormat, CultureInfo.InvariantCulture),
fromRow "Name"
)
Lines =
[ { Account = Account [ fromRow "Receiver" ]
Amount = (Commodity "EUR", float (fromRow "Total")) |> Some
Tag = None }
{ Account = Account [ fromRow "Sender" ]
Amount = None
Tag = None } ]
Comments = [ fromRow "Description" ] }
1 change: 1 addition & 0 deletions src/TransactionQL.Plugins.Triodos/triodos.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Transactiedatum,Rekening,Bedrag,Credit/Debet,Naam Tegenrekening,Tegenrekening,Transactiecode,Omschrijving,Saldo
Loading