Add Development Guide
97
Development-Guide.md
Normal file
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.
|
||||||
Reference in New Issue
Block a user