new endpoints

This commit is contained in:
zipfriis
2026-03-25 16:54:46 +01:00
parent 4e5b830e75
commit 52d99c7012
8 changed files with 305 additions and 99 deletions

211
README.md
View File

@@ -1,15 +1,16 @@
# Portfolio Engine
A lightweight portfolio and financial data backend written in Go. Tracks companies, currencies, and revenue reports across configurable time periods — replacing spreadsheets with a proper database, REST API, and interactive shell.
A lightweight portfolio and financial data backend written in Go. Tracks companies, currencies, revenue reports, and trades across configurable time periods — replacing spreadsheets with a proper database, REST API, and interactive shell.
## Features
- SQLite database with foreign key enforcement
- REST API on port `8080`
- Interactive shell for managing data without an HTTP client
- Revenue tracking by period (quarterly, half-year, full year)
- Revenue broken down by custom categories (product, location, segment...)
- Health endpoint with DB latency, memory, and uptime stats
* SQLite database with foreign key enforcement
* REST API on port `8080`
* Interactive shell for managing data without an HTTP client
* Revenue tracking by period (quarterly, half-year, full year)
* Revenue broken down by custom categories (product, location, segment...)
* Trade tracking (stocks, options, currency trades)
* Health endpoint with DB latency, memory, and uptime stats
## Project Structure
@@ -25,12 +26,14 @@ A lightweight portfolio and financial data backend written in Go. Tracks compani
├── handlers/
│ ├── main.go # HealthHandler
│ ├── currency.go # AddCurrencyHandler, GetCurrenciesHandler
── revenue.go # AddRevenueEntryHandler, GetRevenueReportHandler, GetRevenueSumHandler
── 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
── 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
@@ -46,14 +49,14 @@ A lightweight portfolio and financial data backend written in Go. Tracks compani
### Prerequisites
- Go 1.21+
- GCC (required for SQLite CGO bindings)
- Ubuntu/Debian: `sudo apt install gcc`
- macOS: comes with Xcode Command Line Tools
* Go 1.21+
* GCC (required for SQLite CGO bindings)
+ Ubuntu/Debian: `sudo apt install gcc`
+ macOS: comes with Xcode Command Line Tools
### Install & Run
```bash
```
git clone git@git.samantha42.xyz:samantha/Portifolio-Engine.git
cd Portifolio-Engine
go mod download
@@ -62,7 +65,7 @@ go run main.go
Or build first:
```bash
```
chmod +x build.sh
./build.sh
./Portifolio
@@ -89,7 +92,7 @@ The HTTP server and shell run concurrently — the API is live while you type sh
Returns server status, DB connection info, memory usage, and uptime.
```bash
```
curl http://localhost:8080/health
```
@@ -120,7 +123,7 @@ Returns `503` with `"status": "degraded"` if the database is unreachable.
### `POST /add/company`
```bash
```
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}'
@@ -130,7 +133,7 @@ curl -X POST http://localhost:8080/add/company \
### `GET /companies`
```bash
```
curl http://localhost:8080/companies
```
@@ -138,7 +141,7 @@ curl http://localhost:8080/companies
### `POST /add/currency`
```bash
```
curl -X POST http://localhost:8080/add/currency \
-H "Content-Type: application/json" \
-d '{"code":"DKK","name":"Danish Krone"}'
@@ -148,17 +151,77 @@ curl -X POST http://localhost:8080/add/currency \
### `GET /currencies`
```bash
```
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.
```bash
```
curl -X POST http://localhost:8080/add/revenue/entry \
-H "Content-Type: application/json" \
-d '{
@@ -187,7 +250,7 @@ curl -X POST http://localhost:8080/add/revenue/entry \
Get all revenue entries for a company and period.
```bash
```
curl "http://localhost:8080/revenue/report?company_id=1&period_type=Q&year=2025&index=1"
```
@@ -197,7 +260,7 @@ curl "http://localhost:8080/revenue/report?company_id=1&period_type=Q&year=2025&
Sum all revenue entries for a company across all periods of a given type in a year.
```bash
```
curl "http://localhost:8080/revenue/sum?company_id=1&period_type=Q&year=2025"
```
@@ -205,63 +268,17 @@ 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 |
### Example session
```
> add-currency
Code (e.g. DKK): DKK
Name (e.g. Danish Krone): Danish Krone
✓ Currency 'Danish Krone' (DKK) added with ID 1
> add-company
Name: Novo Nordisk
Shares outstanding: 4442064180
Price: 251.00
Currency ID: 1
✓ Company 'Novo Nordisk' added.
> add-revenue
Company ID: 1
Currency ID: 1
Period type (Q/H/Y): Q
Year: 2025
Index (Q: 1-4 | H: 1-2 | Y: 1): 1
Category (product/location/total): product
Label (e.g. iPhone, Americas): Diabetes Care
Value: 54200
✓ Revenue entry added: product / Diabetes Care = 54200.00 (Q1 2025)
> sum-revenue
Company ID: 1
Period type to sum (Q/H/Y): Q
Year: 2025
Revenue Sum — FY2025
Total: 54200.00
By Category:
product 54200.00
By Label:
Diabetes Care 54200.00
> list-companies
ID NAME CURRENCY PRICE SHARES
------------------------------------------------------------
1 Novo Nordisk DKK 251.00 4442064180
```
| 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 |
---
@@ -313,20 +330,15 @@ CREATE TABLE revenue_entries (
FOREIGN KEY (currency_id) REFERENCES currencies(id)
);
CREATE TABLE category_defs (
id INTEGER PRIMARY KEY AUTOINCREMENT,
company_id INTEGER NOT NULL,
name TEXT NOT NULL,
FOREIGN KEY (company_id) REFERENCES companies(id),
UNIQUE(company_id, name)
);
CREATE TABLE category_labels (
id INTEGER PRIMARY KEY AUTOINCREMENT,
category_def_id INTEGER NOT NULL,
label TEXT NOT NULL,
FOREIGN KEY (category_def_id) REFERENCES category_defs(id),
UNIQUE(category_def_id, label)
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
);
```
@@ -334,8 +346,9 @@ CREATE TABLE category_labels (
## Roadmap
- `GET /company/{id}/revenue` — full revenue history for a company
- Price update endpoint
- Market cap calculation (price × shares outstanding)
- Multi-currency conversion
- Frontend dashboard
* `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