Smart onboarding: residence home profile + suggestion engine

14 new optional residence fields (heating, cooling, water heater, roof,
pool, sprinkler, septic, fireplace, garage, basement, attic, exterior,
flooring, landscaping) with JSONB conditions on templates.

Suggestion engine scores templates against home profile: string match
+0.25, bool +0.3, property type +0.15, universal base 0.3. Graceful
degradation from minimal to full profile info.

GET /api/tasks/suggestions/?residence_id=X returns ranked templates.
54 template conditions across 44 templates in seed data.
8 suggestion service tests.
This commit is contained in:
Trey T
2026-03-30 09:02:03 -05:00
parent 4c9a818bd9
commit cb7080c460
16 changed files with 1347 additions and 32 deletions

View File

@@ -0,0 +1,50 @@
package handlers
import (
"net/http"
"strconv"
"github.com/labstack/echo/v4"
"github.com/treytartt/honeydue-api/internal/apperrors"
"github.com/treytartt/honeydue-api/internal/middleware"
"github.com/treytartt/honeydue-api/internal/services"
)
// SuggestionHandler handles task suggestion endpoints
type SuggestionHandler struct {
suggestionService *services.SuggestionService
}
// NewSuggestionHandler creates a new suggestion handler
func NewSuggestionHandler(suggestionService *services.SuggestionService) *SuggestionHandler {
return &SuggestionHandler{
suggestionService: suggestionService,
}
}
// GetSuggestions handles GET /api/tasks/suggestions/?residence_id=X
// Returns task template suggestions scored against the residence's home profile
func (h *SuggestionHandler) GetSuggestions(c echo.Context) error {
user, err := middleware.MustGetAuthUser(c)
if err != nil {
return err
}
residenceIDStr := c.QueryParam("residence_id")
if residenceIDStr == "" {
return apperrors.BadRequest("error.residence_id_required")
}
residenceID, err := strconv.ParseUint(residenceIDStr, 10, 32)
if err != nil {
return apperrors.BadRequest("error.invalid_id")
}
resp, err := h.suggestionService.GetSuggestions(uint(residenceID), user.ID)
if err != nil {
return err
}
return c.JSON(http.StatusOK, resp)
}