130 lines
4.6 KiB
C#
130 lines
4.6 KiB
C#
using Koogle.Domain.Entities;
|
|
using Koogle.Domain.Enums;
|
|
using Koogle.Domain.Interfaces;
|
|
using KoogleApp.Data;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace Koogle.Infrastructure.Repositories;
|
|
|
|
/// <summary>
|
|
/// Repository implementation for managing cash book entry entities.
|
|
/// </summary>
|
|
/// <param name="contextFactory">The database context factory for creating scoped contexts.</param>
|
|
public class CashBookEntryRepository(IDbContextFactory<AppDbContext> contextFactory) : ICashBookEntryRepository
|
|
{
|
|
/// <inheritdoc />
|
|
public async Task<List<CashBookEntry>> GetByClubIdAsync(Guid clubId, DateTime? from, DateTime? to, CancellationToken ct = default)
|
|
{
|
|
await using var context = await contextFactory.CreateDbContextAsync(ct);
|
|
IQueryable<CashBookEntry> query = context.CashBookEntries
|
|
.Where(e => e.ClubId == clubId && !e.IsDeleted);
|
|
|
|
if (from.HasValue)
|
|
{
|
|
query = query.Where(e => e.BookingDate >= from.Value);
|
|
}
|
|
|
|
if (to.HasValue)
|
|
{
|
|
query = query.Where(e => e.BookingDate <= to.Value);
|
|
}
|
|
|
|
return await query
|
|
.Include(e => e.Category)
|
|
.Include(e => e.Person)
|
|
.Include(e => e.Day)
|
|
.OrderByDescending(e => e.BookingDate)
|
|
.ThenByDescending(e => e.CreatedAt)
|
|
.ToListAsync(ct);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<CashBookEntry?> GetByIdAsync(Guid id, CancellationToken ct = default)
|
|
{
|
|
await using var context = await contextFactory.CreateDbContextAsync(ct);
|
|
return await context.CashBookEntries
|
|
.Include(e => e.Category)
|
|
.Include(e => e.Person)
|
|
.Include(e => e.Day)
|
|
.FirstOrDefaultAsync(e => e.Id == id && !e.IsDeleted, ct);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<decimal> GetBalanceAsync(Guid clubId, DateTime? asOfDate = null, CancellationToken ct = default)
|
|
{
|
|
await using var context = await contextFactory.CreateDbContextAsync(ct);
|
|
|
|
// Get initial balance from club
|
|
var club = await context.Clubs.FirstOrDefaultAsync(c => c.Id == clubId, ct);
|
|
var initialBalance = club?.InitialBalance ?? 0m;
|
|
|
|
var query = context.CashBookEntries
|
|
.Where(e => e.ClubId == clubId && !e.IsDeleted);
|
|
|
|
if (asOfDate.HasValue)
|
|
{
|
|
query = query.Where(e => e.BookingDate <= asOfDate.Value);
|
|
}
|
|
|
|
var entries = await query.ToListAsync(ct);
|
|
|
|
var income = entries
|
|
.Where(e => e.EntryType == CashBookEntryType.Income)
|
|
.Sum(e => e.Amount);
|
|
|
|
var expense = entries
|
|
.Where(e => e.EntryType == CashBookEntryType.Expense)
|
|
.Sum(e => e.Amount);
|
|
|
|
return initialBalance + income - expense;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<CashBookEntry> AddAsync(CashBookEntry entity, CancellationToken ct = default)
|
|
{
|
|
await using var context = await contextFactory.CreateDbContextAsync(ct);
|
|
entity.Id = Guid.NewGuid();
|
|
entity.CreatedAt = DateTime.UtcNow;
|
|
await context.CashBookEntries.AddAsync(entity, ct);
|
|
await context.SaveChangesAsync(ct);
|
|
return entity;
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<List<CashBookEntry>> GetByDayIdAsync(Guid dayId, CancellationToken ct = default)
|
|
{
|
|
await using var context = await contextFactory.CreateDbContextAsync(ct);
|
|
return await context.CashBookEntries
|
|
.Where(e => e.DayId == dayId && !e.IsDeleted)
|
|
.Include(e => e.Category)
|
|
.Include(e => e.Person)
|
|
.OrderByDescending(e => e.CreatedAt)
|
|
.ToListAsync(ct);
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
public async Task<bool> ExistsMembershipFeeForMonthAsync(Guid clubId, int year, int month, CancellationToken ct = default)
|
|
{
|
|
await using var context = await contextFactory.CreateDbContextAsync(ct);
|
|
|
|
// Get the system category for membership fees
|
|
var membershipCategory = await context.BookingCategories
|
|
.FirstOrDefaultAsync(c => c.ClubId == clubId && c.IsSystemCategory && c.Name == "Mitgliedsbeitrag" && !c.IsDeleted, ct);
|
|
|
|
if (membershipCategory == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var startOfMonth = new DateTime(year, month, 1);
|
|
var endOfMonth = startOfMonth.AddMonths(1).AddDays(-1);
|
|
|
|
return await context.CashBookEntries
|
|
.AnyAsync(e => e.ClubId == clubId
|
|
&& e.CategoryId == membershipCategory.Id
|
|
&& e.BookingDate >= startOfMonth
|
|
&& e.BookingDate <= endOfMonth
|
|
&& !e.IsDeleted, ct);
|
|
}
|
|
}
|