Update README.md

This commit is contained in:
2026-03-27 18:51:47 +00:00
parent d0cb9af746
commit fa5e9c347c

341
README.md
View File

@@ -12,343 +12,16 @@ A lightweight portfolio and financial data backend written in Go. Tracks compani
* Trade tracking (stocks, options, currency trades)
* Health endpoint with DB latency, memory, and uptime stats
## Project Structure
```
.
├── main.go # Entry point — HTTP routes + shell loop
├── app.db # SQLite database (auto-created on first run)
├── build.sh # Build script
├── go.mod / go.sum
└── internal/
├── database/
│ └── main.go # Schema init (InitDB) — all CREATE TABLE statements
├── handlers/
│ ├── main.go # HealthHandler
│ ├── currency.go # AddCurrencyHandler, GetCurrenciesHandler
│ ├── revenue.go # AddRevenueEntryHandler, GetRevenueReportHandler, GetRevenueSumHandler
│ └── trade.go # AddTradeHandler, GetTradeListHandler
├── model/
│ ├── company.go # Company struct + SQL (InsertCompany, GetAllCompanies)
│ ├── currency.go # Currency struct + SQL (InsertCurrency, GetAllCurrencies)
│ ├── periode.go # Period struct + helpers (QuarterPeriod, HalfYearPeriod, FullYearPeriod)
│ ├── revenue.go # Revenue, RevenueReport, RevSum structs + SQL
│ └── trade.go # Trade struct, TradeType, TradeProduct enums + SQL
├── service/
│ ├── main.go # Service wiring
│ ├── company.go # Company business logic
│ ├── currency.go # Currency business logic
│ └── revenue.go # Revenue aggregation logic
└── shell/
├── company.go # add-company, list-companies
├── currency.go # add-currency, list-currency
└── revenue.go # add-revenue, list-revenue, sum-revenue
```
## Getting Started
### Prerequisites
* Go 1.21+
* GCC (required for SQLite CGO bindings)
+ Ubuntu/Debian: `sudo apt install gcc`
+ macOS: comes with Xcode Command Line Tools
### Install & Run
```
git clone git@git.samantha42.xyz:samantha/Portifolio-Engine.git
cd Portifolio-Engine
go mod download
go run main.go
```
Or build first:
```
chmod +x build.sh
./build.sh
./Portifolio
```
On startup:
```
Connected to SQLite database
Tables ready
Server running on :8080
Shell ready. Type 'help' for commands.
>
```
The HTTP server and shell run concurrently — the API is live while you type shell commands.
---
## REST API
### `GET /health`
Returns server status, DB connection info, memory usage, and uptime.
```
curl http://localhost:8080/health
```
```json
{
"status": "ok",
"uptime": "4m32s",
"database": {
"status": "ok",
"latency": "121µs",
"open_connections": 1,
"in_use": 0,
"idle": 1
},
"memory": {
"alloc_mb": 2.31,
"sys_mb": 9.44,
"num_gc": 3
},
"go_version": "go1.22.0",
"goroutines": 4
}
```
Returns `503` with `"status": "degraded"` if the database is unreachable.
---
### `POST /add/company`
```
curl -X POST http://localhost:8080/add/company \
-H "Content-Type: application/json" \
-d '{"name":"Novo Nordisk","shares_outstanding":4442064180,"price":251.00,"currency_id":1}'
```
---
### `GET /companies`
```
curl http://localhost:8080/companies
```
---
### `POST /add/currency`
```
curl -X POST http://localhost:8080/add/currency \
-H "Content-Type: application/json" \
-d '{"code":"DKK","name":"Danish Krone"}'
```
---
### `GET /currencies`
```
curl http://localhost:8080/currencies
```
---
### `POST /trade/add`
Add a new trade. `product` and `type` are integer enums (see tables below).
```
curl -X POST http://localhost:8080/trade/add \
-H "Content-Type: application/json" \
-d '{
"ticker_id": 1,
"currency": "DKK",
"shares": 100,
"product": 0,
"type": false,
"price": 251.00,
"date": "2025-03-01T00:00:00Z"
}'
```
**`product` values:**
| Value | Meaning |
|-------|------------------|
| `0` | StockTrade |
| `1` | OptionTradeCall |
| `2` | OptionTradePut |
| `3` | CurrencyTrade |
**`type` values:**
| Value | Meaning |
|---------|---------|
| `false` | Buy |
| `true` | Sell |
---
### `GET /trade/list`
Returns all trades as a JSON array.
```
curl http://localhost:8080/trade/list
```
```json
[
{
"Ticker": { "id": 1, "name": "Novo Nordisk", ... },
"Shares": 100,
"Product": 0,
"Type": false,
"Price": 251.00,
"Currency": { "id": 1, "code": "DKK", "name": "Danish Krone" },
"Date": "2025-03-01T00:00:00Z"
}
]
```
---
### `POST /add/revenue/entry`
Add a single revenue line to a report. The period is created automatically if it doesn't exist.
```
curl -X POST http://localhost:8080/add/revenue/entry \
-H "Content-Type: application/json" \
-d '{
"company_id": 1,
"currency_id": 1,
"period_type": "Q",
"year": 2025,
"index": 1,
"category": "product",
"label": "iPhone",
"value": 69143
}'
```
`period_type` is one of:
| Value | Meaning | `index` range |
|-------|-----------|---------------|
| `Q` | Quarter | 14 |
| `H` | Half-year | 12 |
| `Y` | Full year | 1 |
---
### `GET /revenue/report`
Get all revenue entries for a company and period.
```
curl "http://localhost:8080/revenue/report?company_id=1&period_type=Q&year=2025&index=1"
```
---
### `GET /revenue/sum`
Sum all revenue entries for a company across all periods of a given type in a year.
```
curl "http://localhost:8080/revenue/sum?company_id=1&period_type=Q&year=2025"
```
---
## Shell Commands
| Command | Description |
|------------------|--------------------------------------------------|
| `add-company` | Add a new company interactively |
| `list-companies` | List all companies with price and share count |
| `add-currency` | Add a new currency interactively |
| `list-currency` | List all currencies with their IDs |
| `add-revenue` | Add a revenue entry interactively |
| `list-revenue` | List revenue entries for a company/period |
| `sum-revenue` | Sum revenue across all periods in a year |
| `help` | Show all available commands |
| `exit` | Quit |
---
## Database Schema
```sql
CREATE TABLE currencies (
id INTEGER PRIMARY KEY AUTOINCREMENT,
code TEXT NOT NULL UNIQUE,
name TEXT NOT NULL
);
CREATE TABLE companies (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL UNIQUE,
shares_outstanding INTEGER NOT NULL,
price REAL NOT NULL,
currency_id INTEGER NOT NULL,
FOREIGN KEY (currency_id) REFERENCES currencies(id)
);
CREATE TABLE periods (
id INTEGER PRIMARY KEY AUTOINCREMENT,
type TEXT NOT NULL CHECK(type IN ('Q', 'H', 'Y')),
year INTEGER NOT NULL,
idx INTEGER NOT NULL,
start_date TEXT NOT NULL,
end_date TEXT NOT NULL,
UNIQUE(type, year, idx)
);
CREATE TABLE revenue_reports (
id INTEGER PRIMARY KEY AUTOINCREMENT,
company_id INTEGER NOT NULL,
period_id INTEGER NOT NULL,
FOREIGN KEY (company_id) REFERENCES companies(id),
FOREIGN KEY (period_id) REFERENCES periods(id),
UNIQUE(company_id, period_id)
);
CREATE TABLE revenue_entries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
report_id INTEGER NOT NULL,
currency_id INTEGER NOT NULL,
category TEXT NOT NULL,
label TEXT NOT NULL,
value REAL NOT NULL,
FOREIGN KEY (report_id) REFERENCES revenue_reports(id),
FOREIGN KEY (currency_id) REFERENCES currencies(id)
);
CREATE TABLE trades (
id INTEGER PRIMARY KEY AUTOINCREMENT,
company_id INTEGER NOT NULL,
currency_id INTEGER NOT NULL,
shares INTEGER NOT NULL,
product INTEGER NOT NULL CHECK(product IN (0, 1, 2, 3)),
type INTEGER NOT NULL CHECK(type IN (0, 1)),
price REAL NOT NULL,
traded_at DATETIME NOT NULL
);
```
---
## Roadmap
* `GET /company/{id}/revenue` — full revenue history for a company
* `GET /trade/list?ticker_id=1` — filter trades by company
* Price update endpoint
* Market cap calculation (price × shares outstanding)
* Multi-currency conversion
* Frontend dashboard
* Shares outstanding history db table
* EPS since ownership of shares held
* First In First Out, gain realized
* Dividends earned and taxes
* Total tax obligations
## Learn More WIKI