package inventory import "fmt" // CatalogStatus represents the lifecycle stage of a cataloged hardware item. // Stored as the catalog_status custom field value in NetBox. type CatalogStatus string const ( StatusDraft CatalogStatus = "draft" StatusIndexed CatalogStatus = "indexed" StatusNeedsResearch CatalogStatus = "needs_research" StatusResearched CatalogStatus = "researched" StatusComplete CatalogStatus = "complete" ) // validTransitions defines the allowed state machine transitions. // No backward transitions are permitted (lifecycle is forward-only). var validTransitions = map[CatalogStatus][]CatalogStatus{ StatusDraft: {StatusIndexed}, StatusIndexed: {StatusNeedsResearch, StatusResearched}, StatusNeedsResearch: {StatusResearched}, StatusResearched: {StatusComplete}, StatusComplete: {}, // terminal — no further transitions } // CanTransitionTo returns true if transitioning from s to next is permitted. func (s CatalogStatus) CanTransitionTo(next CatalogStatus) bool { allowed, ok := validTransitions[s] if !ok { return false } for _, a := range allowed { if a == next { return true } } return false } // Transition attempts to move from current to next status. // Returns the new status on success, or an error describing the invalid transition. func Transition(current, next CatalogStatus) (CatalogStatus, error) { if !current.CanTransitionTo(next) { return "", fmt.Errorf("invalid transition: %s → %s (not in valid transitions map)", current, next) } return next, nil } // ParseCatalogStatus parses a string to a CatalogStatus. // Returns error for unknown status values. func ParseCatalogStatus(s string) (CatalogStatus, error) { cs := CatalogStatus(s) if _, ok := validTransitions[cs]; ok { return cs, nil } return "", fmt.Errorf("unknown catalog status: %q (valid: draft, indexed, needs_research, researched, complete)", s) } // AllStatuses returns all valid catalog statuses in lifecycle order. func AllStatuses() []CatalogStatus { return []CatalogStatus{ StatusDraft, StatusIndexed, StatusNeedsResearch, StatusResearched, StatusComplete, } }