package domain import ( "strings" "time" ) // ParentKind identifies which hierarchy entity owns a practice (exactly one). type ParentKind string const ( ParentKindCourse ParentKind = "COURSE" ParentKindModule ParentKind = "MODULE" ParentKindLesson ParentKind = "LESSON" ) // PracticePublishStatus controls learner visibility for a practice shell (independent of question_set.status). type PracticePublishStatus string const ( PracticePublishDraft PracticePublishStatus = "DRAFT" PracticePublishPublished PracticePublishStatus = "PUBLISHED" ) // ParsePracticePublishStatusInput maps API input. Empty or unknown values default to PUBLISHED for backward compatibility. func ParsePracticePublishStatusInput(raw string) PracticePublishStatus { switch strings.TrimSpace(strings.ToUpper(raw)) { case string(PracticePublishDraft): return PracticePublishDraft case string(PracticePublishPublished): return PracticePublishPublished default: return PracticePublishPublished } } // PracticePublishStatusFromDB maps persisted values into the domain type. func PracticePublishStatusFromDB(raw string) PracticePublishStatus { return ParsePracticePublishStatusInput(raw) } // Practice is question-set content (story, persona, tips) scoped to a course, module, or lesson. type Practice struct { ID int64 `json:"id"` ParentKind ParentKind `json:"parent_kind"` ParentID int64 `json:"parent_id"` Title string `json:"title"` StoryDescription *string `json:"story_description,omitempty"` StoryImage *string `json:"story_image,omitempty"` PersonaID *int64 `json:"persona_id,omitempty"` QuestionSetID int64 `json:"question_set_id"` PublishStatus PracticePublishStatus `json:"publish_status"` QuickTips *string `json:"quick_tips,omitempty"` CreatedAt time.Time `json:"created_at"` UpdatedAt *time.Time `json:"updated_at,omitempty"` } // VisibleToLearners is true when the practice shell should appear in subscribed learner catalogs and progression. func (p Practice) VisibleToLearners() bool { return p.PublishStatus == PracticePublishPublished } type CreatePracticeInput struct { ParentKind ParentKind `json:"parent_kind" validate:"required,oneof=COURSE MODULE LESSON"` ParentID int64 `json:"parent_id" validate:"required,gt=0"` Title string `json:"title" validate:"required"` StoryDescription *string `json:"story_description,omitempty"` StoryImage *string `json:"story_image,omitempty"` PersonaID *int64 `json:"persona_id,omitempty"` QuestionSetID int64 `json:"question_set_id" validate:"required,gt=0"` QuickTips *string `json:"quick_tips,omitempty"` // Omit or empty for backward compatibility defaults to PUBLISHED; set DRAFT to save hidden from learners until published. PublishStatus string `json:"publish_status,omitempty" validate:"omitempty,oneof=DRAFT draft PUBLISHED published"` } type UpdatePracticeInput struct { Title *string `json:"title,omitempty"` StoryDescription *string `json:"story_description,omitempty"` StoryImage *string `json:"story_image,omitempty"` PersonaID *int64 `json:"persona_id,omitempty"` QuestionSetID *int64 `json:"question_set_id,omitempty"` QuickTips *string `json:"quick_tips,omitempty"` PublishStatus *string `json:"publish_status,omitempty" validate:"omitempty,oneof=DRAFT draft PUBLISHED published"` }