Files
carvalho-finances/apps/api/internal/handler/credit_bill.go
T
Mlcavalho1andClaude Sonnet 4.6 e3b3433703 feat(#37): módulo de cartão de crédito com faturas mensais
- Migration 011: closing_day/due_day em accounts + tabela credit_bills
- CreditBillService: cria/atualiza fatura corrente on-demand no GET /accounts
- Widget FATURA ATUAL no dashboard com total e botão PAGAR
- AccountsView: campos closing_day/due_day para contas credit + painel fatura
- Dashboard: current_bills lista faturas não pagas de todos os cartões

Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
2026-05-27 15:12:53 -03:00

87 lines
2.3 KiB
Go

package handler
import (
"encoding/json"
"net/http"
"strconv"
"github.com/go-chi/chi/v5"
"financeiro-carvalho/internal/service"
)
type CreditBillHandler struct {
svc *service.CreditBillService
}
func NewCreditBillHandler(svc *service.CreditBillService) *CreditBillHandler {
return &CreditBillHandler{svc: svc}
}
func (h *CreditBillHandler) ListByAccount(w http.ResponseWriter, r *http.Request) {
id, err := strconv.Atoi(chi.URLParam(r, "id"))
if err != nil {
respondError(w, http.StatusBadRequest, "invalid id")
return
}
bills, err := h.svc.ListByAccount(r.Context(), id)
if err != nil {
respondError(w, http.StatusInternalServerError, "failed to list bills")
return
}
respondJSON(w, http.StatusOK, bills)
}
func (h *CreditBillHandler) GetCurrent(w http.ResponseWriter, r *http.Request) {
id, err := strconv.Atoi(chi.URLParam(r, "id"))
if err != nil {
respondError(w, http.StatusBadRequest, "invalid id")
return
}
bill, err := h.svc.GetCurrent(r.Context(), id)
if err != nil {
respondError(w, http.StatusInternalServerError, "failed to get current bill")
return
}
if bill == nil {
respondJSON(w, http.StatusOK, nil)
return
}
respondJSON(w, http.StatusOK, bill)
}
func (h *CreditBillHandler) EnsureCurrent(w http.ResponseWriter, r *http.Request) {
id, err := strconv.Atoi(chi.URLParam(r, "id"))
if err != nil {
respondError(w, http.StatusBadRequest, "invalid id")
return
}
var body struct {
ClosingDay int `json:"closing_day"`
DueDay int `json:"due_day"`
}
_ = json.NewDecoder(r.Body).Decode(&body)
if err := h.svc.EnsureCurrentBill(r.Context(), id, body.ClosingDay, body.DueDay); err != nil {
respondError(w, http.StatusInternalServerError, "failed to ensure bill")
return
}
w.WriteHeader(http.StatusNoContent)
}
func (h *CreditBillHandler) MarkPaid(w http.ResponseWriter, r *http.Request) {
id, err := strconv.Atoi(chi.URLParam(r, "id"))
if err != nil {
respondError(w, http.StatusBadRequest, "invalid id")
return
}
var body struct {
PaymentAccountID *int `json:"payment_account_id"`
}
_ = json.NewDecoder(r.Body).Decode(&body)
if err := h.svc.MarkPaid(r.Context(), id, body.PaymentAccountID); err != nil {
respondError(w, http.StatusInternalServerError, "failed to mark bill paid")
return
}
w.WriteHeader(http.StatusNoContent)
}