using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace Distribution.Features.RecurringExpense; public record ToggleRequest(bool Paused); [ApiController] [Route("api/recurring-expenses")] public class RecurringExpenseController(RecurringExpenseService service) : ControllerBase { [HttpGet] [Authorize("expense.view")] public async Task List([FromQuery] int page = 1, [FromQuery] int pageSize = 20) => Ok(await service.ListAsync(page, pageSize)); [HttpPost] [Authorize("expense.manage_recurring")] public async Task Create(CreateRecurringExpenseRequest request, CancellationToken ct) { try { return Ok(await service.CreateAsync(request, ct)); } catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } } [HttpPut("{id:guid}")] [Authorize("expense.manage_recurring")] public async Task Update(Guid id, UpdateRecurringExpenseRequest request, CancellationToken ct) { try { var result = await service.UpdateAsync(id, request, ct); return result is null ? NotFound() : Ok(result); } catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } } [HttpPost("{id:guid}/toggle")] [Authorize("expense.manage_recurring")] public async Task Toggle(Guid id, ToggleRequest body, CancellationToken ct) { var result = await service.ToggleAsync(id, body.Paused, ct); return result is null ? NotFound() : Ok(result); } [HttpPost("run-due")] [Authorize("expense.manage_recurring")] public async Task RunDue(CancellationToken ct) { try { return Ok(await service.RunDueAsync(ct)); } catch (InvalidOperationException ex) { return BadRequest(new { error = ex.Message }); } } }