package models import ( "errors" "time" "github.com/google/uuid" ) const ( TypeDocument = "document" TypeDatabase = "database" ) // DataSource is retained for audit queries around analysis-bound sources. type DataSource struct { ID uuid.UUID `json:"id"` AnalysisID uuid.UUID `json:"analysis_id"` Type string `json:"type"` Name string `json:"name"` ReferenceID string `json:"reference_id"` BoundBy string `json:"bound_by"` BoundAt time.Time `json:"bound_at"` Metadata *DataSourceMetadata `json:"metadata,omitempty"` CreatedAt time.Time `json:"created_at"` } type DataSourceMetadata struct { BindingReason string `json:"binding_reason,omitempty"` OriginalUser string `json:"original_user,omitempty"` DepartmentName string `json:"department,omitempty"` ProjectCode string `json:"project_code,omitempty"` } var ( ErrDataSourceTypeRequired = errors.New("type must be 'document' or 'database'") ErrDataSourceNameRequired = errors.New("name is required") ErrDataSourceReferenceIDRequired = errors.New("reference_id is required") ErrDataSourceBoundByRequired = errors.New("bound_by (user_id) is required") ErrDataSourceAnalysisIDRequired = errors.New("analysis_id is required") ) func (ds *DataSource) Validate() error { if ds == nil { return errors.New("data source cannot be nil") } if ds.AnalysisID == uuid.Nil { return ErrDataSourceAnalysisIDRequired } if ds.Type != TypeDocument && ds.Type != TypeDatabase { return ErrDataSourceTypeRequired } if ds.Name == "" { return ErrDataSourceNameRequired } if ds.ReferenceID == "" { return ErrDataSourceReferenceIDRequired } if ds.BoundBy == "" { return ErrDataSourceBoundByRequired } return nil } func NewDataSource(analysisID uuid.UUID, sourceType, name, referenceID, boundBy string) *DataSource { now := time.Now().UTC() return &DataSource{ ID: uuid.New(), AnalysisID: analysisID, Type: sourceType, Name: name, ReferenceID: referenceID, BoundBy: boundBy, BoundAt: now, CreatedAt: now, } } func (ds *DataSource) SetMetadata(metadata *DataSourceMetadata) { ds.Metadata = metadata }