new endpoints
This commit is contained in:
211
README.md
211
README.md
@@ -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
|
||||
Reference in New Issue
Block a user