Files
gochat/internal/service/note_service.go
T
2026-06-04 15:44:48 +08:00

84 lines
2.6 KiB
Go

package service
// NoteService provides business logic for contact notes.
// Reference: Chatwoot app/controllers/api/v1/accounts/contacts/notes_controller.rb
import (
"errors"
"github.com/gochat/gochat/internal/model"
"github.com/gochat/gochat/internal/repository"
)
var (
ErrNoteNotFound = errors.New("note not found")
ErrNoteContentEmpty = errors.New("note content is required")
ErrNoteAccountMismatch = errors.New("note does not belong to the account")
)
// NoteService handles CRUD operations for contact notes.
type NoteService struct {
noteRepo *repository.NoteRepo
}
// NewNoteService creates a new NoteService instance.
func NewNoteService(noteRepo *repository.NoteRepo) *NoteService {
return &NoteService{noteRepo: noteRepo}
}
// List returns all notes for a contact in an account, ordered latest first.
// Reference: Chatwoot `def index; @notes = @contact.notes.latest.includes(:user); end`
func (s *NoteService) List(accountID, contactID uint) ([]model.Note, error) {
return s.noteRepo.ListByContact(accountID, contactID)
}
// Get returns a single note by ID.
// Reference: Chatwoot `def show; end`
func (s *NoteService) Get(accountID, contactID, noteID uint) (*model.Note, error) {
note, err := s.noteRepo.GetByID(accountID, contactID, noteID)
if err != nil {
return nil, ErrNoteNotFound
}
return note, nil
}
// Create creates a new note for a contact.
// Reference: Chatwoot `def create; @note = @contact.notes.create!(note_params); end`
// note_params merges contact_id and current_user.id
func (s *NoteService) Create(accountID, contactID uint, userID uint, content string) (*model.Note, error) {
if content == "" {
return nil, ErrNoteContentEmpty
}
note := &model.Note{
Content: content,
AccountID: accountID,
ContactID: contactID,
UserID: &userID,
}
return s.noteRepo.CreateNote(note)
}
// Update updates an existing note's content.
// Reference: Chatwoot `def update; @note.update(note_params); end`
func (s *NoteService) Update(accountID, contactID, noteID uint, content string) (*model.Note, error) {
if content == "" {
return nil, ErrNoteContentEmpty
}
note, err := s.noteRepo.GetByID(accountID, contactID, noteID)
if err != nil {
return nil, ErrNoteNotFound
}
note.Content = content
return s.noteRepo.Update(note)
}
// Delete removes a note.
// Reference: Chatwoot `def destroy; @note.destroy!; head :ok; end`
// Chatwoot returns 200 OK on destroy, not 204 NoContent.
func (s *NoteService) Delete(accountID, contactID, noteID uint) error {
err := s.noteRepo.Delete(accountID, contactID, noteID)
if err != nil {
return ErrNoteNotFound
}
return nil
}