rentease/internal/server/handle_reports.go
2025-11-02 21:45:37 +01:00

98 lines
3.2 KiB
Go

package server
import (
"fmt"
"net/http"
"strconv"
"time"
"github.com/a-h/templ"
u "github.com/rjNemo/underscore"
"github.com/rjNemo/rentease/internal/config"
"github.com/rjNemo/rentease/internal/constant"
"github.com/rjNemo/rentease/internal/service/booking"
"github.com/rjNemo/rentease/internal/view"
)
func handleReportsPage() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
monthStr := r.URL.Query().Get("month")
month, err := strconv.Atoi(monthStr)
if err != nil || month < 1 || month > 12 {
month = int(time.Now().Month())
}
yearStr := r.URL.Query().Get("year")
if _, err = strconv.Atoi(yearStr); err != nil {
yearStr = time.Now().Format("2006")
}
component := view.Reports(u.Map(constant.Months, func(m constant.Month) string {
return string(m)
}), month, yearStr)
if err := renderTempl(w, http.StatusOK, component); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
}
func handleReportCompute(bs *booking.Service, hc *config.Host) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if err := r.ParseForm(); err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
period := r.FormValue("period")
if !u.Contains([]string{"month", "year"}, period) {
http.Error(w, fmt.Sprintf("%q is not a valid period", period), http.StatusBadRequest)
return
}
monthStr := r.FormValue("month")
month, err := strconv.Atoi(monthStr)
if err != nil || month < 1 || month > 12 {
http.Error(w, fmt.Sprintf("%q is not a valid month", monthStr), http.StatusBadRequest)
return
}
yearStr := r.FormValue("year")
year, err := strconv.Atoi(yearStr)
if err != nil {
http.Error(w, fmt.Sprintf("%q is not a valid year", yearStr), http.StatusBadRequest)
return
}
report := bs.Report(period, month, year)
reportVm := &view.ReportViewModel{
Total: strconv.FormatFloat(report.Total, 'f', 2, 64),
PlatformFees: strconv.FormatFloat(report.PlatformFees, 'f', 2, 64),
Fee: strconv.FormatFloat(report.Fee, 'f', 2, 64),
Profit: strconv.FormatFloat(report.Profit, 'f', 2, 64),
CardTotal: strconv.FormatFloat(report.CardTotal, 'f', 2, 64),
BookingFees: strconv.FormatFloat(report.BookingFees, 'f', 2, 64),
PdfUrl: templ.URL(fmt.Sprintf("%s/pdf?period=%s&month=%d&year=%d", constant.RouteReports, period, month, year)),
Lines: u.Map(report.Lines, func(l *booking.Line) *view.ReportLine {
return &view.ReportLine{
Id: l.InvoiceNumber(hc),
Url: templ.SafeURL(fmt.Sprintf("%s/%d", constant.RouteBooking, l.ID)),
Total: strconv.FormatFloat(l.Total, 'f', 2, 64),
CustomerName: l.CustomerName,
From: l.From.Format(time.DateOnly),
To: l.To.Format(time.DateOnly),
Platform: l.Platform,
PlatformFees: strconv.FormatFloat(l.PlatformFees, 'f', 2, 64),
Fee: strconv.FormatFloat(l.Fee(), 'f', 2, 64),
Profit: strconv.FormatFloat(l.Profit(), 'f', 2, 64),
}
}),
}
if err := renderTempl(w, http.StatusOK, view.ReportSection(reportVm)); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}
}