mirror of
https://github.com/Dvorinka/Bookra.git
synced 2026-10-28 15:51:15 +00:00
feat: data surfacing — intake labels, service metrics, honest capacity
- booking views gain intakeLabels (declared key→label join); dashboard modal + manage view render real question labels with slug fallback - GET /v1/metrics/services aggregates bookings/completed/cancelled/ revenue per service + classBookings; service-report.csv delegates to the same ServiceMetrics aggregation and gains a completed column - services page gains a Service performance card (per-service stat grid, locale CZK revenue, class-bookings footer); demo rows match the fabricated service list - staff capacity utilization subtracts blocked days — tenant-wide and staff-scoped blocks remove that day's rule minutes via blockedAt - tests: blocked-day capacity (tenant + staff scope), service aggregation Authored By: TDvorak <[email protected]> Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
34becc1bf4
commit
5c860a1264
16 files changed
+560
-69
No files matched your search
@@ -1369,6 +1369,20 @@ func NewServer(cfg config.Config, pools *db.Pools) (*Server, error) {
|
||||
c.JSON(http.StatusOK, response)
|
||||
})
|
||||
|
||||
protected.GET("/metrics/services", func(c *gin.Context) {
|
||||
days, _ := strconv.Atoi(c.DefaultQuery("days", "30"))
|
||||
response, err := bookingService.ServiceMetrics(c.Request.Context(), auth.PrincipalFromContext(c), days)
|
||||
if err != nil {
|
||||
status := http.StatusInternalServerError
|
||||
if errors.Is(err, bookings.ErrTenantMembership) {
|
||||
status = http.StatusNotFound
|
||||
}
|
||||
c.JSON(status, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, response)
|
||||
})
|
||||
|
||||
protected.GET("/export/bookings.csv", func(c *gin.Context) {
|
||||
from, to := exportRange(c)
|
||||
var buf bytes.Buffer
|
||||
|
||||
Reference in new issue
Block a user