feat: add inbox capture workflow
This commit is contained in:
100
backend/internal/inbox/service.go
Normal file
100
backend/internal/inbox/service.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package inbox
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"senlinai-agent/backend/internal/domain"
|
||||
)
|
||||
|
||||
type CaptureInput struct {
|
||||
ProjectID uint
|
||||
UserID uint
|
||||
SourceType string
|
||||
Title string
|
||||
Body string
|
||||
}
|
||||
|
||||
type Suggestion struct {
|
||||
Kind string `json:"kind"`
|
||||
Title string `json:"title"`
|
||||
Body string `json:"body"`
|
||||
}
|
||||
|
||||
type Analyzer interface {
|
||||
Analyze(item domain.InboxItem, userID uint) ([]Suggestion, error)
|
||||
}
|
||||
|
||||
type StaticAnalyzer struct {
|
||||
Suggestions []Suggestion
|
||||
}
|
||||
|
||||
func (a StaticAnalyzer) Analyze(item domain.InboxItem, userID uint) ([]Suggestion, error) {
|
||||
return a.Suggestions, nil
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
db *gorm.DB
|
||||
analyzer Analyzer
|
||||
}
|
||||
|
||||
func NewService(database *gorm.DB, analyzer Analyzer) *Service {
|
||||
return &Service{db: database, analyzer: analyzer}
|
||||
}
|
||||
|
||||
func (s *Service) Capture(input CaptureInput) (*domain.InboxItem, error) {
|
||||
if input.ProjectID == 0 || input.UserID == 0 {
|
||||
return nil, errors.New("project and user are required")
|
||||
}
|
||||
if input.SourceType == "" {
|
||||
return nil, errors.New("source type is required")
|
||||
}
|
||||
item := &domain.InboxItem{
|
||||
ProjectID: input.ProjectID,
|
||||
CreatedBy: input.UserID,
|
||||
SourceType: input.SourceType,
|
||||
Title: input.Title,
|
||||
Body: input.Body,
|
||||
Status: "open",
|
||||
}
|
||||
return item, s.db.Create(item).Error
|
||||
}
|
||||
|
||||
func (s *Service) Analyze(itemID uint, userID uint) ([]Suggestion, error) {
|
||||
var item domain.InboxItem
|
||||
if err := s.db.First(&item, itemID).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if s.analyzer == nil {
|
||||
return []Suggestion{}, nil
|
||||
}
|
||||
return s.analyzer.Analyze(item, userID)
|
||||
}
|
||||
|
||||
func (s *Service) Confirm(itemID uint, selected []Suggestion) error {
|
||||
return s.db.Transaction(func(tx *gorm.DB) error {
|
||||
var item domain.InboxItem
|
||||
if err := tx.First(&item, itemID).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
for _, suggestion := range selected {
|
||||
switch suggestion.Kind {
|
||||
case "task":
|
||||
if err := tx.Create(&domain.Task{ProjectID: item.ProjectID, CreatedBy: item.CreatedBy, Title: suggestion.Title, Description: suggestion.Body}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
case "note":
|
||||
if err := tx.Create(&domain.Note{ProjectID: item.ProjectID, CreatedBy: item.CreatedBy, Title: suggestion.Title, Markdown: suggestion.Body}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
case "source":
|
||||
if err := tx.Create(&domain.Source{ProjectID: item.ProjectID, CreatedBy: item.CreatedBy, Kind: "link", Title: suggestion.Title, ContentText: suggestion.Body}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return errors.New("unsupported suggestion kind")
|
||||
}
|
||||
}
|
||||
return tx.Model(&item).Update("status", "processed").Error
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user