Added a-frame-architecture usiung wolverine sample.

This commit is contained in:
2026-08-03 17:08:18 +02:00
parent 1b5bf4f8d4
commit 61fe59cf83
72 changed files with 3012 additions and 0 deletions
@@ -0,0 +1,42 @@
using FinancialApi.Domain.Entities;
using Microsoft.EntityFrameworkCore;
namespace FinancialApi.Infrastructure;
public class AccountDbContext(DbContextOptions<AccountDbContext> options) : DbContext(options)
{
public DbSet<Account> Accounts => Set<Account>();
public DbSet<BalancedJournalEntry> JournalEntries => Set<BalancedJournalEntry>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Account>()
.HasKey(x => x.Id);
modelBuilder.Entity<Account>()
.HasData(
new Account(1, 10000000.00m, AccountType.Borrow),
new Account(2, 50000000.00m, AccountType.Spend),
new Account(99999, 0.00m, AccountType.Revenue)
);
modelBuilder.Entity<BalancedJournalEntry>(builder =>
{
builder.HasKey(x => x.Id);
builder.OwnsMany(
x => x.Lines,
line =>
{
line.WithOwner()
.HasForeignKey("JournalEntryId");
line.Property<int>("Id")
.ValueGeneratedOnAdd();
line.HasKey("Id");
line.Property(x => x.Type)
.HasConversion<string>();
}
);
}
);
}
}
@@ -0,0 +1,14 @@
using FinancialApi.Application.Interfaces;
using FinancialApi.Domain.Entities;
using Microsoft.EntityFrameworkCore;
namespace FinancialApi.Infrastructure;
public class AccountQuery(AccountDbContext db) : IAccountQuery
{
public async Task<Account?> FindByIdAsync(int id)
{
return await db.Accounts.AsNoTracking()
.FirstOrDefaultAsync(x => x.Id == id);
}
}
@@ -0,0 +1,13 @@
using FinancialApi.Domain.Events;
namespace FinancialApi.Infrastructure;
public class DemoEventStore : IEventTracker
{
public List<string> CapturedEvents { get; } = new();
public void Add(string eventMessage)
{
CapturedEvents.Add($"[{DateTimeOffset.UtcNow:HH:mm:ss}] {eventMessage}");
}
}
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\FinancialApi.Application\FinancialApi.Application.csproj"/>
<ProjectReference Include="..\FinancialApi.Domain\FinancialApi.Domain.csproj"/>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="10.0.9"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.9"/>
<PackageReference Include="WolverineFx" Version="6.18.0"/>
<PackageReference Include="WolverineFx.EntityFrameworkCore" Version="6.18.0"/>
<PackageReference Include="WolverineFx.Sqlite" Version="6.18.0"/>
</ItemGroup>
</Project>
@@ -0,0 +1,50 @@
// <auto-generated />
using FinancialApi.Infrastructure;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace FinancialApi.Infrastructure.Migrations
{
[DbContext(typeof(AccountDbContext))]
[Migration("20260713152041_InitialCreate")]
partial class InitialCreate
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "10.0.9");
modelBuilder.Entity("FinancialApi.Application.Account", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<decimal>("Balance")
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Accounts");
b.HasData(
new
{
Id = 1,
Balance = 100.00m
},
new
{
Id = 2,
Balance = 500.00m
});
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,45 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
namespace FinancialApi.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Accounts",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Balance = table.Column<decimal>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Accounts", x => x.Id);
});
migrationBuilder.InsertData(
table: "Accounts",
columns: new[] { "Id", "Balance" },
values: new object[,]
{
{ 1, 100.00m },
{ 2, 500.00m }
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Accounts");
}
}
}
@@ -0,0 +1,115 @@
// <auto-generated />
using System;
using FinancialApi.Infrastructure;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace FinancialApi.Infrastructure.Migrations
{
[DbContext(typeof(AccountDbContext))]
[Migration("20260715093924_AddJournal")]
partial class AddJournal
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "10.0.9");
modelBuilder.Entity("FinancialApi.Application.Account", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("AccountType")
.IsRequired()
.HasColumnType("TEXT");
b.Property<decimal>("Balance")
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Accounts");
b.HasData(
new
{
Id = 1,
AccountType = "Credit",
Balance = 100.00m
},
new
{
Id = 2,
AccountType = "Liability",
Balance = 500.00m
},
new
{
Id = 99999,
AccountType = "Revenue",
Balance = 0.00m
});
});
modelBuilder.Entity("FinancialApi.Application.JournalEntry", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("JournalEntries");
});
modelBuilder.Entity("FinancialApi.Application.JournalEntry", b =>
{
b.OwnsMany("FinancialApi.Application.JournalLine", "Lines", b1 =>
{
b1.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b1.Property<int>("AccountId")
.HasColumnType("INTEGER");
b1.Property<decimal>("Amount")
.HasColumnType("TEXT");
b1.Property<Guid>("JournalEntryId")
.HasColumnType("TEXT");
b1.Property<string>("Type")
.IsRequired()
.HasColumnType("TEXT");
b1.HasKey("Id");
b1.HasIndex("JournalEntryId");
b1.ToTable("JournalLine");
b1.WithOwner()
.HasForeignKey("JournalEntryId");
});
b.Navigation("Lines");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,100 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace FinancialApi.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class AddJournal : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "AccountType",
table: "Accounts",
type: "TEXT",
nullable: false,
defaultValue: "");
migrationBuilder.CreateTable(
name: "JournalEntries",
columns: table => new
{
Id = table.Column<Guid>(type: "TEXT", nullable: false),
Description = table.Column<string>(type: "TEXT", nullable: false),
CreatedAt = table.Column<DateTimeOffset>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_JournalEntries", x => x.Id);
});
migrationBuilder.CreateTable(
name: "JournalLine",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
AccountId = table.Column<int>(type: "INTEGER", nullable: false),
Amount = table.Column<decimal>(type: "TEXT", nullable: false),
Type = table.Column<string>(type: "TEXT", nullable: false),
JournalEntryId = table.Column<Guid>(type: "TEXT", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_JournalLine", x => x.Id);
table.ForeignKey(
name: "FK_JournalLine_JournalEntries_JournalEntryId",
column: x => x.JournalEntryId,
principalTable: "JournalEntries",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.UpdateData(
table: "Accounts",
keyColumn: "Id",
keyValue: 1,
column: "AccountType",
value: "Credit");
migrationBuilder.UpdateData(
table: "Accounts",
keyColumn: "Id",
keyValue: 2,
column: "AccountType",
value: "Liability");
migrationBuilder.InsertData(
table: "Accounts",
columns: new[] { "Id", "AccountType", "Balance" },
values: new object[] { 99999, "Revenue", 0.00m });
migrationBuilder.CreateIndex(
name: "IX_JournalLine_JournalEntryId",
table: "JournalLine",
column: "JournalEntryId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "JournalLine");
migrationBuilder.DropTable(
name: "JournalEntries");
migrationBuilder.DeleteData(
table: "Accounts",
keyColumn: "Id",
keyValue: 99999);
migrationBuilder.DropColumn(
name: "AccountType",
table: "Accounts");
}
}
}
@@ -0,0 +1,115 @@
// <auto-generated />
using System;
using FinancialApi.Infrastructure;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace FinancialApi.Infrastructure.Migrations
{
[DbContext(typeof(AccountDbContext))]
[Migration("20260715100428_UpdateAccountBalances")]
partial class UpdateAccountBalances
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "10.0.9");
modelBuilder.Entity("FinancialApi.Application.Account", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("AccountType")
.IsRequired()
.HasColumnType("TEXT");
b.Property<decimal>("Balance")
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Accounts");
b.HasData(
new
{
Id = 1,
AccountType = "Credit",
Balance = 10000000.00m
},
new
{
Id = 2,
AccountType = "Liability",
Balance = 50000000.00m
},
new
{
Id = 99999,
AccountType = "Revenue",
Balance = 0.00m
});
});
modelBuilder.Entity("FinancialApi.Application.JournalEntry", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("JournalEntries");
});
modelBuilder.Entity("FinancialApi.Application.JournalEntry", b =>
{
b.OwnsMany("FinancialApi.Application.JournalLine", "Lines", b1 =>
{
b1.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b1.Property<int>("AccountId")
.HasColumnType("INTEGER");
b1.Property<decimal>("Amount")
.HasColumnType("TEXT");
b1.Property<Guid>("JournalEntryId")
.HasColumnType("TEXT");
b1.Property<string>("Type")
.IsRequired()
.HasColumnType("TEXT");
b1.HasKey("Id");
b1.HasIndex("JournalEntryId");
b1.ToTable("JournalLine");
b1.WithOwner()
.HasForeignKey("JournalEntryId");
});
b.Navigation("Lines");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,46 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace FinancialApi.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class UpdateAccountBalances : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "Accounts",
keyColumn: "Id",
keyValue: 1,
column: "Balance",
value: 10000000.00m);
migrationBuilder.UpdateData(
table: "Accounts",
keyColumn: "Id",
keyValue: 2,
column: "Balance",
value: 50000000.00m);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "Accounts",
keyColumn: "Id",
keyValue: 1,
column: "Balance",
value: 100.00m);
migrationBuilder.UpdateData(
table: "Accounts",
keyColumn: "Id",
keyValue: 2,
column: "Balance",
value: 500.00m);
}
}
}
@@ -0,0 +1,114 @@
// <auto-generated />
using System;
using FinancialApi.Infrastructure;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace FinancialApi.Infrastructure.Migrations
{
[DbContext(typeof(AccountDbContext))]
[Migration("20260729103021_AccountTypes")]
partial class AccountTypes
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "10.0.9");
modelBuilder.Entity("FinancialApi.Domain.Entities.Account", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<decimal>("Balance")
.HasColumnType("TEXT");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.ToTable("Accounts");
b.HasData(
new
{
Id = 1,
Balance = 10000000.00m,
Type = 2
},
new
{
Id = 2,
Balance = 50000000.00m,
Type = 0
},
new
{
Id = 99999,
Balance = 0.00m,
Type = 3
});
});
modelBuilder.Entity("FinancialApi.Domain.Entities.JournalEntry", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("JournalEntries");
});
modelBuilder.Entity("FinancialApi.Domain.Entities.JournalEntry", b =>
{
b.OwnsMany("FinancialApi.Domain.Entities.JournalLine", "Lines", b1 =>
{
b1.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b1.Property<int>("AccountId")
.HasColumnType("INTEGER");
b1.Property<decimal>("Amount")
.HasColumnType("TEXT");
b1.Property<Guid>("JournalEntryId")
.HasColumnType("TEXT");
b1.Property<string>("Type")
.IsRequired()
.HasColumnType("TEXT");
b1.HasKey("Id");
b1.HasIndex("JournalEntryId");
b1.ToTable("JournalLine");
b1.WithOwner()
.HasForeignKey("JournalEntryId");
});
b.Navigation("Lines");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,82 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace FinancialApi.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class AccountTypes : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "AccountType",
table: "Accounts");
migrationBuilder.AddColumn<int>(
name: "Type",
table: "Accounts",
type: "INTEGER",
nullable: false,
defaultValue: 0);
migrationBuilder.UpdateData(
table: "Accounts",
keyColumn: "Id",
keyValue: 1,
column: "Type",
value: 2);
migrationBuilder.UpdateData(
table: "Accounts",
keyColumn: "Id",
keyValue: 2,
column: "Type",
value: 0);
migrationBuilder.UpdateData(
table: "Accounts",
keyColumn: "Id",
keyValue: 99999,
column: "Type",
value: 3);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Type",
table: "Accounts");
migrationBuilder.AddColumn<string>(
name: "AccountType",
table: "Accounts",
type: "TEXT",
nullable: false,
defaultValue: "");
migrationBuilder.UpdateData(
table: "Accounts",
keyColumn: "Id",
keyValue: 1,
column: "AccountType",
value: "Credit");
migrationBuilder.UpdateData(
table: "Accounts",
keyColumn: "Id",
keyValue: 2,
column: "AccountType",
value: "Liability");
migrationBuilder.UpdateData(
table: "Accounts",
keyColumn: "Id",
keyValue: 99999,
column: "AccountType",
value: "Revenue");
}
}
}
@@ -0,0 +1,114 @@
// <auto-generated />
using System;
using FinancialApi.Infrastructure;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace FinancialApi.Infrastructure.Migrations
{
[DbContext(typeof(AccountDbContext))]
[Migration("20260731073046_UpdateAccountTypes")]
partial class UpdateAccountTypes
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "10.0.9");
modelBuilder.Entity("FinancialApi.Domain.Entities.Account", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<decimal>("Balance")
.HasColumnType("TEXT");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.ToTable("Accounts");
b.HasData(
new
{
Id = 1,
Balance = 10000000.00m,
Type = 1
},
new
{
Id = 2,
Balance = 50000000.00m,
Type = 0
},
new
{
Id = 99999,
Balance = 0.00m,
Type = 2
});
});
modelBuilder.Entity("FinancialApi.Domain.Entities.BalancedJournalEntry", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("JournalEntries");
});
modelBuilder.Entity("FinancialApi.Domain.Entities.BalancedJournalEntry", b =>
{
b.OwnsMany("FinancialApi.Domain.Entities.JournalLine", "Lines", b1 =>
{
b1.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b1.Property<int>("AccountId")
.HasColumnType("INTEGER");
b1.Property<decimal>("Amount")
.HasColumnType("TEXT");
b1.Property<Guid>("JournalEntryId")
.HasColumnType("TEXT");
b1.Property<string>("Type")
.IsRequired()
.HasColumnType("TEXT");
b1.HasKey("Id");
b1.HasIndex("JournalEntryId");
b1.ToTable("JournalLine");
b1.WithOwner()
.HasForeignKey("JournalEntryId");
});
b.Navigation("Lines");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,46 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace FinancialApi.Infrastructure.Migrations
{
/// <inheritdoc />
public partial class UpdateAccountTypes : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "Accounts",
keyColumn: "Id",
keyValue: 1,
column: "Type",
value: 1);
migrationBuilder.UpdateData(
table: "Accounts",
keyColumn: "Id",
keyValue: 99999,
column: "Type",
value: 2);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.UpdateData(
table: "Accounts",
keyColumn: "Id",
keyValue: 1,
column: "Type",
value: 2);
migrationBuilder.UpdateData(
table: "Accounts",
keyColumn: "Id",
keyValue: 99999,
column: "Type",
value: 3);
}
}
}
@@ -0,0 +1,111 @@
// <auto-generated />
using System;
using FinancialApi.Infrastructure;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace FinancialApi.Infrastructure.Migrations
{
[DbContext(typeof(AccountDbContext))]
partial class AccountDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "10.0.9");
modelBuilder.Entity("FinancialApi.Domain.Entities.Account", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<decimal>("Balance")
.HasColumnType("TEXT");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.ToTable("Accounts");
b.HasData(
new
{
Id = 1,
Balance = 10000000.00m,
Type = 1
},
new
{
Id = 2,
Balance = 50000000.00m,
Type = 0
},
new
{
Id = 99999,
Balance = 0.00m,
Type = 2
});
});
modelBuilder.Entity("FinancialApi.Domain.Entities.BalancedJournalEntry", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<DateTimeOffset>("CreatedAt")
.HasColumnType("TEXT");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("JournalEntries");
});
modelBuilder.Entity("FinancialApi.Domain.Entities.BalancedJournalEntry", b =>
{
b.OwnsMany("FinancialApi.Domain.Entities.JournalLine", "Lines", b1 =>
{
b1.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b1.Property<int>("AccountId")
.HasColumnType("INTEGER");
b1.Property<decimal>("Amount")
.HasColumnType("TEXT");
b1.Property<Guid>("JournalEntryId")
.HasColumnType("TEXT");
b1.Property<string>("Type")
.IsRequired()
.HasColumnType("TEXT");
b1.HasKey("Id");
b1.HasIndex("JournalEntryId");
b1.ToTable("JournalLine");
b1.WithOwner()
.HasForeignKey("JournalEntryId");
});
b.Navigation("Lines");
});
#pragma warning restore 612, 618
}
}
}
@@ -0,0 +1,30 @@
using FinancialApi.Application.Interfaces;
using FinancialApi.Domain.Entities;
using Microsoft.EntityFrameworkCore;
namespace FinancialApi.Infrastructure;
public class ReversalQuery(AccountDbContext db) : IReversalQuery
{
public async Task<(BalancedJournalEntry?, List<Account>?)> GetReversalDataAsync(Guid journalEntryId)
{
var entry = await db.JournalEntries.Include(x => x.Lines)
.AsNoTracking()
.FirstOrDefaultAsync(x => x.Id == journalEntryId);
if (entry == null)
{
return (null, null);
}
var accountIds = entry.Lines.Select(l => l.AccountId)
.Distinct()
.ToList();
var accounts = await db.Accounts.AsNoTracking()
.Where(a => accountIds.Contains(a.Id))
.ToListAsync();
return (entry, accounts);
}
}