quicknotes/notes/service.go

136 lines
3.3 KiB
Go
Raw Normal View History

package notes
import (
"fmt"
"github.com/google/uuid"
"gorm.io/gorm"
)
// Service handles note operations
type Service struct {
db *gorm.DB
}
// NewService creates a new note service
func NewService(db *gorm.DB) *Service {
return &Service{db: db}
}
// Create creates a new note
func (s *Service) Create(note *Note) error {
note.ID = uuid.New().String()
err := s.db.Transaction(func(tx *gorm.DB) error {
// Create the note
if err := tx.Create(note).Error; err != nil {
return fmt.Errorf("failed to create note: %w", err)
}
// Update links in this note
if err := note.UpdateLinks(tx); err != nil {
return fmt.Errorf("failed to update note links: %w", err)
}
// Find and update notes that link to this note's title
var notesToUpdate []Note
if err := tx.Where("content LIKE ?", "%[["+note.Title+"]]%").Find(&notesToUpdate).Error; err != nil {
return fmt.Errorf("failed to find notes linking to %q: %w", note.Title, err)
}
for _, n := range notesToUpdate {
if err := n.UpdateLinks(tx); err != nil {
return fmt.Errorf("failed to update links in note %q: %w", n.Title, err)
}
}
return nil
})
if err != nil {
return err
}
// Load the note with its relationships
if err := s.db.Preload("LinksTo").First(note).Error; err != nil {
return fmt.Errorf("failed to load note relationships: %w", err)
}
return nil
}
// Get retrieves a note by ID
func (s *Service) Get(id string) (*Note, error) {
var note Note
if err := s.db.
Preload("LinksTo", func(db *gorm.DB) *gorm.DB {
return db.Select("id", "title")
}).
Preload("LinkedBy", func(db *gorm.DB) *gorm.DB {
return db.Select("id", "title")
}).
First(&note, "id = ?", id).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, nil
}
return nil, fmt.Errorf("failed to get note: %w", err)
}
return &note, nil
}
// List retrieves all notes
func (s *Service) List() ([]Note, error) {
var notes []Note
if err := s.db.
Preload("LinksTo", func(db *gorm.DB) *gorm.DB {
return db.Select("id", "title")
}).
Preload("LinkedBy", func(db *gorm.DB) *gorm.DB {
return db.Select("id", "title")
}).
Order("updated_at desc").
Find(&notes).Error; err != nil {
return nil, fmt.Errorf("failed to list notes: %w", err)
}
return notes, nil
}
// Update updates a note
func (s *Service) Update(id string, updates map[string]interface{}) error {
return s.db.Transaction(func(tx *gorm.DB) error {
// Update the note
if err := tx.Model(&Note{}).Where("id = ?", id).Updates(updates).Error; err != nil {
return fmt.Errorf("failed to update note: %w", err)
}
// Load the updated note for link processing
var note Note
if err := tx.First(&note, "id = ?", id).Error; err != nil {
return fmt.Errorf("failed to load note: %w", err)
}
// Update links
if err := note.UpdateLinks(tx); err != nil {
return fmt.Errorf("failed to update note links: %w", err)
}
return nil
})
}
// Delete deletes a note
func (s *Service) Delete(id string) error {
if err := s.db.Delete(&Note{}, "id = ?", id).Error; err != nil {
return fmt.Errorf("failed to delete note: %w", err)
}
return nil
}
// Reset deletes all notes (for testing)
func (s *Service) Reset() error {
if err := s.db.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&Note{}).Error; err != nil {
return fmt.Errorf("failed to reset notes: %w", err)
}
return nil
}