feat(finance): expose Form 990 line catalog endpoint

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Chris Chen
2026-06-24 19:36:01 -07:00
parent 3f61e9ceaf
commit 1a03a1cbba
4 changed files with 27 additions and 0 deletions
@@ -12,6 +12,9 @@ public class Form990ReportController : ControllerBase
private readonly IForm990ReportService _svc; private readonly IForm990ReportService _svc;
public Form990ReportController(IForm990ReportService svc) => _svc = svc; public Form990ReportController(IForm990ReportService svc) => _svc = svc;
[HttpGet("lines")]
public async Task<IActionResult> Lines() => Ok(await _svc.GetLinesAsync());
[HttpGet("functional-expenses")] [HttpGet("functional-expenses")]
public async Task<IActionResult> FunctionalExpenses([FromQuery] DateOnly? from, [FromQuery] DateOnly? to) public async Task<IActionResult> FunctionalExpenses([FromQuery] DateOnly? from, [FromQuery] DateOnly? to)
=> Ok(await _svc.GetFunctionalExpenseStatementAsync(from, to)); => Ok(await _svc.GetFunctionalExpenseStatementAsync(from, to));
@@ -23,3 +23,13 @@ public class FunctionalExpenseStatementDto
/// <summary>Expenses with no explicit 990 mapping (counted under line 24). Prompts mapping cleanup.</summary> /// <summary>Expenses with no explicit 990 mapping (counted under line 24). Prompts mapping cleanup.</summary>
public int UnmappedExpenseCount { get; set; } public int UnmappedExpenseCount { get; set; }
} }
/// <summary>A single IRS Form 990 expense line from the catalog (used to populate mapping dropdowns).</summary>
public class Form990ExpenseLineDto
{
public int Id { get; set; }
public string LineCode { get; set; } = "";
public string Name_en { get; set; } = "";
public string? Name_zh { get; set; }
public int SortOrder { get; set; }
}
@@ -15,6 +15,19 @@ public class Form990ReportService : IForm990ReportService
private readonly AppDbContext _db; private readonly AppDbContext _db;
public Form990ReportService(AppDbContext db) => _db = db; public Form990ReportService(AppDbContext db) => _db = db;
public async Task<List<Form990ExpenseLineDto>> GetLinesAsync() =>
await _db.Form990ExpenseLines.AsNoTracking().Where(l => l.IsActive)
.OrderBy(l => l.SortOrder)
.Select(l => new Form990ExpenseLineDto
{
Id = l.Id,
LineCode = l.LineCode,
Name_en = l.Name_en,
Name_zh = l.Name_zh,
SortOrder = l.SortOrder,
})
.ToListAsync();
public async Task<FunctionalExpenseStatementDto> GetFunctionalExpenseStatementAsync(DateOnly? from, DateOnly? to) public async Task<FunctionalExpenseStatementDto> GetFunctionalExpenseStatementAsync(DateOnly? from, DateOnly? to)
{ {
var lines = await _db.Form990ExpenseLines.AsNoTracking() var lines = await _db.Form990ExpenseLines.AsNoTracking()
@@ -4,4 +4,5 @@ namespace ROLAC.API.Services;
public interface IForm990ReportService public interface IForm990ReportService
{ {
Task<FunctionalExpenseStatementDto> GetFunctionalExpenseStatementAsync(DateOnly? from, DateOnly? to); Task<FunctionalExpenseStatementDto> GetFunctionalExpenseStatementAsync(DateOnly? from, DateOnly? to);
Task<List<Form990ExpenseLineDto>> GetLinesAsync();
} }