asentrafin/backend/Controllers/TransactionAnalyticsControl...

85 lines
2.8 KiB
C#

using Asentrafin.Api.Contracts.Transactions;
using Asentrafin.Api.Data;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace Asentrafin.Api.Controllers;
[ApiController]
[Route("api/transactions")]
public class TransactionAnalyticsController(AppDbContext dbContext) : ControllerBase
{
[HttpGet("categories")]
public async Task<ActionResult<IReadOnlyList<TransactionCategoryResponse>>> GetCategories(
CancellationToken cancellationToken)
{
var categories = await dbContext.TransactionCategories
.OrderBy(category => category.SortOrder)
.ThenBy(category => category.Name)
.Select(category => new TransactionCategoryResponse(
category.Id,
category.ParentId,
category.Name,
category.Slug,
category.PlaidPrimary,
category.PlaidDetailed,
category.IsSystem))
.ToListAsync(cancellationToken);
return Ok(categories);
}
[HttpGet("category-summaries")]
public async Task<ActionResult<IReadOnlyList<CategorySummaryResponse>>> GetCategorySummaries(
[FromQuery] DateOnly? startDate,
[FromQuery] DateOnly? endDate,
[FromQuery] Guid? accountId,
[FromQuery] bool includePending = false,
CancellationToken cancellationToken = default)
{
var query = dbContext.PlaidTransactions
.AsNoTracking()
.Where(transaction => transaction.RemovedAt == null);
if (!includePending)
{
query = query.Where(transaction => !transaction.Pending);
}
if (startDate is not null)
{
query = query.Where(transaction => transaction.Date >= startDate.Value);
}
if (endDate is not null)
{
query = query.Where(transaction => transaction.Date <= endDate.Value);
}
if (accountId is not null)
{
query = query.Where(transaction => transaction.PlaidAccountId == accountId.Value);
}
var summaries = await query
.Where(transaction => transaction.Classification != null)
.GroupBy(transaction => new
{
transaction.Classification!.Category.Id,
transaction.Classification.Category.Name,
transaction.Classification.Category.Slug
})
.Select(group => new CategorySummaryResponse(
group.Key.Id,
group.Key.Name,
group.Key.Slug,
group.Count(),
group.Sum(transaction => transaction.Amount)))
.OrderByDescending(summary => Math.Abs(summary.TotalAmount))
.ThenBy(summary => summary.CategoryName)
.ToListAsync(cancellationToken);
return Ok(summaries);
}
}