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 }