Onboarding: template backlink, bulk-create endpoint, climate-region scoring
Some checks failed
Some checks failed
Clients that send users through a multi-task onboarding step no longer loop N POST /api/tasks/ calls and no longer create "orphan" tasks with no reference to the TaskTemplate they came from. Task model - New task_template_id column + GORM FK (migration 000016) - CreateTaskRequest.template_id, TaskResponse.template_id - task_service.CreateTask persists the backlink Bulk endpoint - POST /api/tasks/bulk/ — 1-50 tasks in a single transaction, returns every created row + TotalSummary. Single residence access check, per-entry residence_id is overridden with batch value - task_handler.BulkCreateTasks + task_service.BulkCreateTasks using db.Transaction; task_repo.CreateTx + FindByIDTx helpers Climate-region scoring - templateConditions gains ClimateRegionID; suggestion_service scores residence.PostalCode -> ZipToState -> GetClimateRegionIDByState against the template's conditions JSON (no penalty on mismatch / unknown ZIP) - regionMatchBonus 0.35, totalProfileFields 14 -> 15 - Standalone GET /api/tasks/templates/by-region/ removed; legacy task_tasktemplate_regions many-to-many dropped (migration 000017). Region affinity now lives entirely in the template's conditions JSON Tests - +11 cases across task_service_test, task_handler_test, suggestion_ service_test: template_id persistence, bulk rollback + cap + auth, region match / mismatch / no-ZIP / unknown-ZIP / stacks-with-others Docs - docs/openapi.yaml: /tasks/bulk/ + BulkCreateTasks schemas, template_id on TaskResponse + CreateTaskRequest, /templates/by-region/ removed Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -92,6 +92,12 @@ type Task struct {
|
||||
ParentTaskID *uint `gorm:"column:parent_task_id;index" json:"parent_task_id"`
|
||||
ParentTask *Task `gorm:"foreignKey:ParentTaskID" json:"parent_task,omitempty"`
|
||||
|
||||
// Template backlink — set when a task is created from a TaskTemplate
|
||||
// (e.g. via onboarding suggestions or the browse-all catalog). Nullable
|
||||
// so custom user tasks remain unaffected.
|
||||
TaskTemplateID *uint `gorm:"column:task_template_id;index" json:"task_template_id,omitempty"`
|
||||
TaskTemplate *TaskTemplate `gorm:"foreignKey:TaskTemplateID" json:"task_template,omitempty"`
|
||||
|
||||
// Completions
|
||||
Completions []TaskCompletion `gorm:"foreignKey:TaskID" json:"completions,omitempty"`
|
||||
|
||||
|
||||
@@ -16,8 +16,17 @@ type TaskTemplate struct {
|
||||
Tags string `gorm:"column:tags;type:text" json:"tags"` // Comma-separated tags for search
|
||||
DisplayOrder int `gorm:"column:display_order;default:0" json:"display_order"`
|
||||
IsActive bool `gorm:"column:is_active;default:true;index" json:"is_active"`
|
||||
Conditions json.RawMessage `gorm:"column:conditions;type:jsonb;default:'{}'" json:"conditions"`
|
||||
Regions []ClimateRegion `gorm:"many2many:task_tasktemplate_regions;" json:"regions,omitempty"`
|
||||
// Conditions is the JSON-encoded scoring condition set evaluated by
|
||||
// SuggestionService. Supported keys: heating_type, cooling_type,
|
||||
// water_heater_type, roof_type, exterior_type, flooring_primary,
|
||||
// landscaping_type, has_pool, has_sprinkler_system, has_septic,
|
||||
// has_fireplace, has_garage, has_basement, has_attic, property_type,
|
||||
// climate_region_id.
|
||||
//
|
||||
// Climate regions used to be stored via a many-to-many with
|
||||
// ClimateRegion; they are now driven entirely by the JSON condition
|
||||
// above. See migration 000017 for the join-table drop.
|
||||
Conditions json.RawMessage `gorm:"column:conditions;type:jsonb;default:'{}'" json:"conditions"`
|
||||
}
|
||||
|
||||
// TableName returns the table name for GORM
|
||||
|
||||
Reference in New Issue
Block a user