Add infrastructure layer with persistence and services

- EF Core DbContext and entity configurations
- Design-time factory for migrations
- Initial and soft-delete migrations
- Service implementations: Account, AccountYear, Entry,
  BalanceQuery, FileSave, PdfStatement
- Dependency injection registration
This commit is contained in:
2026-03-31 17:12:57 +02:00
parent 8fbb8b8ea2
commit c3d68020d5
19 changed files with 1450 additions and 0 deletions

View File

@@ -0,0 +1,167 @@
// <auto-generated />
using System;
using Duempelkas.Infrastructure.Persistence;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace Duempelkas.Infrastructure.Migrations
{
[DbContext(typeof(FinanceDbContext))]
partial class FinanceDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "10.0.5");
modelBuilder.Entity("Duempelkas.Domain.Entities.Account", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<decimal>("CarryoverBalance")
.HasColumnType("decimal(18,2)");
b.Property<DateTime>("CreatedUtc")
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Accounts");
});
modelBuilder.Entity("Duempelkas.Domain.Entities.Entry", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<int>("AccountId")
.HasColumnType("INTEGER");
b.Property<decimal>("Amount")
.HasColumnType("decimal(18,2)");
b.Property<DateTime>("CreatedUtc")
.HasColumnType("TEXT");
b.Property<DateTime>("Date")
.HasColumnType("TEXT");
b.Property<string>("DisplayId")
.IsRequired()
.HasMaxLength(20)
.HasColumnType("TEXT");
b.Property<bool>("IsDeleted")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER")
.HasDefaultValue(false);
b.Property<string>("Title")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("TEXT");
b.Property<int?>("TransferLinkId")
.HasColumnType("INTEGER");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("DisplayId")
.IsUnique();
b.HasIndex("TransferLinkId");
b.HasIndex("AccountId", "Date");
b.ToTable("Entries");
});
modelBuilder.Entity("Duempelkas.Domain.Entities.TransferLink", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<DateTime>("CreatedUtc")
.HasColumnType("TEXT");
b.Property<string>("Note")
.HasMaxLength(500)
.HasColumnType("TEXT");
b.Property<int>("SourceEntryId")
.HasColumnType("INTEGER");
b.Property<int>("TargetEntryId")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.HasIndex("SourceEntryId")
.IsUnique();
b.HasIndex("TargetEntryId")
.IsUnique();
b.ToTable("TransferLinks");
});
modelBuilder.Entity("Duempelkas.Domain.Entities.Entry", b =>
{
b.HasOne("Duempelkas.Domain.Entities.Account", "Account")
.WithMany("Entries")
.HasForeignKey("AccountId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Duempelkas.Domain.Entities.TransferLink", "TransferLink")
.WithMany()
.HasForeignKey("TransferLinkId")
.OnDelete(DeleteBehavior.Restrict);
b.Navigation("Account");
b.Navigation("TransferLink");
});
modelBuilder.Entity("Duempelkas.Domain.Entities.TransferLink", b =>
{
b.HasOne("Duempelkas.Domain.Entities.Entry", "SourceEntry")
.WithMany()
.HasForeignKey("SourceEntryId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.HasOne("Duempelkas.Domain.Entities.Entry", "TargetEntry")
.WithMany()
.HasForeignKey("TargetEntryId")
.OnDelete(DeleteBehavior.Restrict)
.IsRequired();
b.Navigation("SourceEntry");
b.Navigation("TargetEntry");
});
modelBuilder.Entity("Duempelkas.Domain.Entities.Account", b =>
{
b.Navigation("Entries");
});
#pragma warning restore 612, 618
}
}
}