Add Development Guide

2026-03-21 07:32:43 +00:00
parent 131283eae7
commit 6a3961bf5f

97
Development-Guide.md Normal file

@@ -0,0 +1,97 @@
# Development Guide
---
## Setting Up a Dev Environment
```bash
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
```bash
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:
```bash
go test ./Engine/internal/service/...
```
To run with verbose output:
```bash
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.
**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
```bash
go build -o fpa-engine ./main.go
```
For a lean, statically linked binary suitable for containers:
```bash
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.