2
Development Guide
samantha edited this page 2026-03-21 07:33:59 +00:00

Development Guide


Setting Up a Dev Environment

git clone https://git.samantha42.xyz/samantha/FPandA-Engine
cd FPandA-Engine
go mod tidy
go run ./main.go

No database setup is needed. The SQLite file is created automatically on first run.


Running Tests

go test ./...

Tests use Go's built-in testing package. The test suite was migrated from Python to Go's native test runner — see commit 771eb9d. Use DB_PATH=:memory: in test setup to avoid leaving .db files on disk.

To run a specific package:

go test ./Engine/internal/service/...

To run with verbose output:

go test -v ./...

Project Conventions

Layer responsibilities:

  • handler/ — HTTP concerns only. Decode the request body, call a service method, encode the response. No business logic here.
  • service/ — All business logic. Favourability calculation, variance rollup, budget rules. No SQL here.
  • database/ — All SQL. Repository structs implement interfaces used by the service layer.
  • model/ — Plain Go structs shared across layers. No methods with business logic, only struct validation.

Error handling:

Go makes every error path explicit. Handlers check service errors and return appropriate HTTP status codes. The server never panics on request errors.

Logging:

Use the slog logger passed into components via dependency injection (or the package-level logger if needed). Log at ERROR for unexpected failures, INFO for lifecycle events. Do not log every request unless debugging.


Adding a New Endpoint

  1. Add the domain type to model/ if needed
  2. Add the repository method to the relevant file in database/
  3. Add the service method in service/
  4. Add the handler method in handler/
  5. Register the route in main.go on the mux

Follow the existing patterns — each handler function decodes JSON, calls one service method, and encodes the response.


Adding a New Budget Version

Budget versions are stored as a string field. Currently supported: original, forecast1, forecast2, forecast3. To add a new version (e.g. forecast4), update the validation in the budget service and add the new value to the Finance Concepts documentation.


Database Migrations

Schema changes are applied via database.Migrate() on startup using CREATE TABLE IF NOT EXISTS and ALTER TABLE IF NOT EXISTS (for additive column changes). This is intentionally simple — there is no migration versioning system.

For destructive changes (dropping columns, renaming tables), apply them manually to existing databases and update the migration function. Document any required manual steps here.


Building a Release Binary

go build -o fpa-engine ./main.go

For a lean, statically linked binary suitable for containers:

CGO_ENABLED=0 GOOS=linux go build -a -ldflags '-extldflags "-static"' -o fpa-engine ./main.go

Note: modernc.org/sqlite is a pure-Go SQLite implementation — CGO is not required, and the binary has no system library dependencies.