Add step type support for work order profiles and steps, update database schema, APIs, and UI components to handle configurable step types.

This commit is contained in:
2026-05-17 19:21:11 -04:00
parent 309f19520b
commit 6307babbfa
8 changed files with 481 additions and 89 deletions
+17 -8
View File
@@ -178,14 +178,17 @@ func (h *ProfileHandler) CreateStep(w http.ResponseWriter, r *http.Request) {
respondError(w, http.StatusBadRequest, "title required")
return
}
if body.StepType == "" {
body.StepType = "work_step"
}
var maxOrder int
h.db.QueryRow(`SELECT ISNULL(MAX(step_order),0) FROM wo_profile_steps WHERE profile_id=@p1`, profileID).Scan(&maxOrder)
var sid int
err = h.db.QueryRow(`
INSERT INTO wo_profile_steps (profile_id, step_order, title, description, required)
OUTPUT INSERTED.id VALUES (@p1, @p2, @p3, @p4, @p5)`,
profileID, maxOrder+1, body.Title, body.Description, body.Required,
INSERT INTO wo_profile_steps (profile_id, step_order, title, description, required, step_type, type_config)
OUTPUT INSERTED.id VALUES (@p1, @p2, @p3, @p4, @p5, @p6, @p7)`,
profileID, maxOrder+1, body.Title, body.Description, body.Required, body.StepType, body.TypeConfig,
).Scan(&sid)
if err != nil {
respondError(w, http.StatusInternalServerError, err.Error())
@@ -207,8 +210,11 @@ func (h *ProfileHandler) UpdateStep(w http.ResponseWriter, r *http.Request) {
respondError(w, http.StatusBadRequest, "title required")
return
}
h.db.Exec(`UPDATE wo_profile_steps SET title=@p1, description=@p2, required=@p3, step_order=@p4 WHERE id=@p5`,
body.Title, body.Description, body.Required, body.StepOrder, sid)
if body.StepType == "" {
body.StepType = "work_step"
}
h.db.Exec(`UPDATE wo_profile_steps SET title=@p1, description=@p2, required=@p3, step_order=@p4, step_type=@p5, type_config=@p6 WHERE id=@p7`,
body.Title, body.Description, body.Required, body.StepOrder, body.StepType, body.TypeConfig, sid)
var step model.ProfileStep
h.db.Get(&step, `SELECT * FROM wo_profile_steps WHERE id=@p1`, sid)
respond(w, http.StatusOK, step)
@@ -262,10 +268,13 @@ func (h *ProfileHandler) Apply(w http.ResponseWriter, r *http.Request) {
h.db.QueryRow(`SELECT ISNULL(MAX(step_order),0) FROM wo_steps WHERE wo_id=@p1`, woID).Scan(&maxOrder)
for _, s := range steps {
if s.StepType == "" {
s.StepType = "work_step"
}
h.db.Exec(`
INSERT INTO wo_steps (wo_id, step_order, title, description, required)
VALUES (@p1, @p2, @p3, @p4, @p5)`,
woID, maxOrder+s.StepOrder, s.Title, s.Description, s.Required)
INSERT INTO wo_steps (wo_id, step_order, title, description, required, step_type, type_config)
VALUES (@p1, @p2, @p3, @p4, @p5, @p6, @p7)`,
woID, maxOrder+s.StepOrder, s.Title, s.Description, s.Required, s.StepType, s.TypeConfig)
}
// Fill instructions if blank; update priority only on draft WOs
+6 -3
View File
@@ -41,11 +41,14 @@ func (h *StepHandler) Create(w http.ResponseWriter, r *http.Request) {
var maxOrder int
h.db.QueryRow(`SELECT ISNULL(MAX(step_order),0) FROM wo_steps WHERE wo_id=@p1`, woID).Scan(&maxOrder)
if body.StepType == "" {
body.StepType = "work_step"
}
var sid int
err = h.db.QueryRow(`
INSERT INTO wo_steps (wo_id,step_order,title,description,required)
OUTPUT INSERTED.id VALUES (@p1,@p2,@p3,@p4,@p5)`,
woID, maxOrder+1, body.Title, body.Description, body.Required,
INSERT INTO wo_steps (wo_id,step_order,title,description,required,step_type,type_config)
OUTPUT INSERTED.id VALUES (@p1,@p2,@p3,@p4,@p5,@p6,@p7)`,
woID, maxOrder+1, body.Title, body.Description, body.Required, body.StepType, body.TypeConfig,
).Scan(&sid)
if err != nil {
respondError(w, http.StatusInternalServerError, err.Error())
+4
View File
@@ -56,6 +56,8 @@ type Step struct {
Title string `db:"title" json:"title"`
Description string `db:"description" json:"description"`
Required bool `db:"required" json:"required"`
StepType string `db:"step_type" json:"step_type"`
TypeConfig string `db:"type_config" json:"type_config"`
Completed bool `db:"completed" json:"completed"`
CompletedBy *string `db:"completed_by" json:"completed_by"`
CompletedAt *time.Time `db:"completed_at" json:"completed_at"`
@@ -166,6 +168,8 @@ type ProfileStep struct {
Title string `db:"title" json:"title"`
Description string `db:"description" json:"description"`
Required bool `db:"required" json:"required"`
StepType string `db:"step_type" json:"step_type"`
TypeConfig string `db:"type_config" json:"type_config"`
}
// ── Users & Auth ──────────────────────────────────────────────────────────────
@@ -0,0 +1,31 @@
-- Work Order Profiles
IF NOT EXISTS (SELECT 1 FROM sys.tables WHERE name = 'wo_profiles')
BEGIN
CREATE TABLE wo_profiles (
id INT IDENTITY PRIMARY KEY,
name NVARCHAR(200) NOT NULL,
description NVARCHAR(MAX),
category NVARCHAR(100),
default_priority NVARCHAR(10) NOT NULL DEFAULT 'normal',
default_duration_hours INT,
default_instructions NVARCHAR(MAX),
active BIT NOT NULL DEFAULT 1,
created_at DATETIME2 NOT NULL DEFAULT GETUTCDATE(),
updated_at DATETIME2 NOT NULL DEFAULT GETUTCDATE()
);
END
IF NOT EXISTS (SELECT 1 FROM sys.tables WHERE name = 'wo_profile_steps')
BEGIN
CREATE TABLE wo_profile_steps (
id INT IDENTITY PRIMARY KEY,
profile_id INT NOT NULL REFERENCES wo_profiles(id) ON DELETE CASCADE,
step_order INT NOT NULL,
title NVARCHAR(200) NOT NULL,
description NVARCHAR(MAX),
required BIT NOT NULL DEFAULT 1
);
CREATE INDEX ix_profile_steps ON wo_profile_steps (profile_id, step_order);
END
@@ -0,0 +1,15 @@
-- Add step_type and type_config to profile steps and WO steps
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID('wo_profile_steps') AND name = 'step_type')
ALTER TABLE wo_profile_steps ADD step_type NVARCHAR(30) NOT NULL DEFAULT 'work_step';
-- 'work_step' | 'photo' | 'inspection' | 'note'
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID('wo_profile_steps') AND name = 'type_config')
ALTER TABLE wo_profile_steps ADD type_config NVARCHAR(MAX) NULL;
-- JSON; shape depends on step_type (see CLAUDE.md)
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID('wo_steps') AND name = 'step_type')
ALTER TABLE wo_steps ADD step_type NVARCHAR(30) NOT NULL DEFAULT 'work_step';
IF NOT EXISTS (SELECT 1 FROM sys.columns WHERE object_id = OBJECT_ID('wo_steps') AND name = 'type_config')
ALTER TABLE wo_steps ADD type_config NVARCHAR(MAX) NULL;