feat(metrics): new-clients KPI and scheduled reminder dispatch

The dashboard promised a new-clients card the API never produced; the
metric now counts distinct customer emails whose earliest-ever booking
lands in the window, joining the other four KPIs with the same trend
comparison. The card grid rebalances for five items.

Reminder dispatch also had no trigger — the endpoint existed but
nothing called it. A scheduled GitHub Actions workflow now posts to it
every 15 minutes using the job-runner key, so reminders actually fire
once the two secrets are configured.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Tomas DvorakandDevin committed 2026-09-18 12:59:44 +02:00
1 parent cdad7875e1
commit c7172544b8
8 files changed
+93 -20

No files matched your search

+16
View File
@@ -397,6 +397,7 @@ type DashboardMetrics struct {
CancellationsCount int
UtilizationPercent int
CompletedCount int
NewClientsCount int
}
type ReminderJobParams struct {
@@ -1488,6 +1489,21 @@ func (r *MemoryRepository) GetDashboardMetrics(_ context.Context, tenantID strin
}
}
}
firstSeen := map[string]time.Time{}
for _, booking := range r.bookings {
if booking.TenantID != tenantID {
continue
}
first, ok := firstSeen[booking.CustomerEmail]
if !ok || booking.StartsAt.Before(first) {
firstSeen[booking.CustomerEmail] = booking.StartsAt
}
}
for _, first := range firstSeen {
if !first.Before(startsAt) && first.Before(endsAt) {
metrics.NewClientsCount++
}
}
if metrics.BookingsCount == 0 {
metrics.UtilizationPercent = 0
} else {