Reorganize repo: backend/, deploy/, docs/ layout + AGENTS.md
Restructure the monorepo into clear top-level directories: - backend/: Go module root (cmd, internal, pkg, configs, migrations, docs/swagger, scripts, tests, go.mod, Makefile, .air.toml) - deploy/: Docker (Dockerfile, docker-compose*), quickstart, fluentd - docs/: project documentation + reports/ (moved from repo root) - AGENTS.md: new AI coding-agent guide at repo root Update all references to the new layout: - Dockerfile: COPY backend/go.mod, COPY backend/ (context = repo root) - docker-compose files: context ../.., dockerfile deploy/docker/Dockerfile, env_file ../../.env, volume mounts ../../backend:/app - deploy/quickstart/compose.yaml: dockerfile deploy/docker/Dockerfile - CI: working-directory: backend for go commands, file deploy/docker/Dockerfile, coverage path backend/coverage.out, health_check backend/scripts/ - backend/Makefile: docker target uses -f ../deploy/docker/Dockerfile ../ - README: architecture tree, quickstart, config paths updated Move root stray scripts (rename_models.*, run_m11_tests.sh, verify_build.sh, gorm_bool_main.go) to backend/scripts/legacy/. All moves via git mv to preserve history. Build, vet, SQLite tests, and docker compose config verified.
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user