Files
workspace/apps/go-crm/README.md
gabspereira 744868caa1 feat(go-crm): full auth, routing, middleware, and supporting infra
- Add auth handlers (signup, login, logout, account management) with bcrypt
- Add client, customer, service, scheduling, payment, question, answer handlers
- Add dashboard, monthly report, and lead pipeline pages
- Add UTF-8 middleware to force charset on HTML responses
- Add config package with env-based overrides for DB path, secrets, endpoints
- Add parser package for WhatsApp message ingestion
- Add clean-arch layers: pkg/domain, pkg/repo, pkg/usecase for leads
- Add cmd/migrate utility for DB migrations
- Add Makefile, README, run-tests.sh, and dev scripts
- Update docker-compose.yml with memory limits
- Update .air.toml to exclude DB files and stop on errors
- Update whatsapp-sync dependencies and add src/index.js entrypoint
- Add whatsme standalone WhatsApp reader app (source only)
- Untrack .opencode-sandbox/data/go-crm.db from git history
- Expand root .gitignore: ngrok, tmp dirs, sandbox DBs, compiled binaries
2026-05-23 16:55:55 -03:00

3.9 KiB

go-crm (lightweight local dev)

This service is intentionally small so junior Go developers can understand it end-to-end without Docker, hot reloads, or other heavy tooling. The goal: go run main.go with a single SQLite file in .dev-data/.

Local development (junior-friendly)

  1. Ensure Go 1.25+ is installed and go is in your PATH.
  2. Run the helper script (no Docker):
    ./scripts/dev.sh
    
  3. The server boots on http://localhost:8080.
  4. The database and WhatsApp store live under .dev-data/ (auto-created).

There are no file watchers or air hot reloads—just the plain Go toolchain so newcomers can focus on code, not tooling.

Project layout (modern, clean layers)

go-crm/
├── cmd/                  # optional commands (e.g. migrations)
│   └── migrate/           # lightweight migration CLI (future)
├── config/               # templated configs (kept simple)
├── data/                 # production data path (gitignored)
├── internal/             # HTTP handlers (usecases wired to HTTP)
│   ├── handlers/
│   ├── middleware/
│   └── templates/
├── pkg/                  # reusable application packages
│   ├── domain/            # entities + repository interfaces
│   ├── usecase/           # application services / business logic
│   └── repo/              # persistence adapters (SQLite, etc.)
├── scripts/              # helper scripts (dev runner, migrations)
├── main.go               # application entrypoint (wire handlers → usecases)
├── go.mod
└── go.sum

pkg/domain/lead.go

package domain

// Lead is the core business entity.
type Lead struct {
    LeadID         int64
    ClientID       int64
    Name           string
    PhoneRaw       string
    PhoneNormalized string
    ServiceInterest string
    Status         string
    PaymentStatus  string
}

// LeadRepository abstracts persistence.
type LeadRepository interface {
    FindAll(ctx context.Context, clientID int64) ([]Lead, error)
    FindByID(ctx context.Context, clientID, leadID int64) (*Lead, error)
    Update(ctx context.Context, lead Lead) error
}

pkg/usecase/lead_service.go

package usecase

import (
    "context"
    "go-crm/pkg/domain"
)

// LeadService orchestrates business logic.
type LeadService struct {
    Repo domain.LeadRepository
}

func (s *LeadService) ListAll(ctx context.Context, clientID int64) ([]domain.Lead, error) {
    return s.Repo.FindAll(ctx, clientID)
}

pkg/repo/sqlite_lead_repo.go

package repo

import (
    "context"
    "database/sql"
    "go-crm/pkg/domain"
)

// SQLiteLeadRepository implements LeadRepository using sqlite.
type SQLiteLeadRepository struct {
    DB *sql.DB
}

func (r *SQLiteLeadRepository) FindAll(ctx context.Context, clientID int64) ([]domain.Lead, error) {
    // query leads table, scan rows, return []domain.Lead
}

Handlers in internal/handlers should accept a clear service layer (usecase.LeadService), not raw DB logic. Keep controllers thin: parse request, call service, write HTML/JSON.

Migration strategy

  • Do not scan/clean the entire leads table on every startup (that was causing RAM blowups).
  • Run the lightweight CLI with make migrate (which builds and runs the migration binary) whenever you need to refresh the schema or re-decode legacy Latin-1 data. To target non-default files, run the migration binary directly:
    go build -o migrate cmd/migrate/main.go && ./migrate --db /path/to/go-crm.db
    

Running tests

go test ./...

Summary

  • No Docker or air watchers—just go run main.go.
  • Clean package boundaries (domain/usecase/repo) improve readability and testability.
  • Scripts under scripts/ orchestrate database setup or helper tasks.
  • Use the architecture sketch above to guide future refactors.