- 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
126 lines
3.9 KiB
Markdown
126 lines
3.9 KiB
Markdown
# 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):
|
|
```bash
|
|
./scripts/dev.sh
|
|
```
|
|
3. The server boots on [http://localhost:8080](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
|
|
```
|
|
|
|
## Recommended architecture / interfaces
|
|
|
|
### `pkg/domain/lead.go`
|
|
```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`
|
|
```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`
|
|
```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:
|
|
```bash
|
|
go build -o migrate cmd/migrate/main.go && ./migrate --db /path/to/go-crm.db
|
|
```
|
|
|
|
## Running tests
|
|
|
|
```bash
|
|
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.
|