# jtlsrv

Built on **libuv** (event loop), **OpenSSL** (TLS), **llhttp** (HTTP parsing), **unixODBC** + [**ODBC Driver 18 for SQL Server**](https://learn.microsoft.com/en-us/sql/connect/odbc/microsoft-odbc-driver-for-sql-server) (database), and **libvips** (image thumbnails). Blocking work (ODBC queries, image processing) runs on libuv worker threads.

## Requirements

| Dependency | Purpose |
|---|---|
| C++17 compiler | gcc or clang |
| GNU Make | Build |
| pkg-config | Dependency flags |
| libuv | Async I/O and thread pool |
| OpenSSL | TLS |
| libvips | Product/category image resizing |
| unixODBC + dev headers | ODBC runtime |
| [ODBC Driver 18 for SQL Server](https://learn.microsoft.com/en-us/sql/connect/odbc/microsoft-odbc-driver-for-sql-server) | Connect to JTL-Wawi (MSSQL) |

Vendored in `vendor/`: **llhttp**, **nlohmann/json** (no install needed).

### Install on Ubuntu / Debian

```bash
sudo apt install \
  build-essential make pkg-config \
  libuv1-dev libssl-dev libvips-dev unixodbc-dev
```

Install [Microsoft's ODBC driver](https://learn.microsoft.com/en-us/sql/connect/odbc/microsoft-odbc-driver-for-sql-server) (required for MSSQL):

```bash
curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | \
  sudo gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg

echo "deb [arch=amd64 signed-by=/usr/share/keyrings/microsoft-prod.gpg] \
  https://packages.microsoft.com/ubuntu/$(lsb_release -rs)/prod $(lsb_release -cs) main" | \
  sudo tee /etc/apt/sources.list.d/mssql-release.list

sudo apt update
sudo ACCEPT_EULA=Y apt install msodbcsql18
```

## Build

```bash
make
```

The binary is written to `./jtlsrv`. After code changes always run `make` before starting the server.

Debug build:

```bash
make debug
```

## Configuration

Copy the example env file from the repo root and edit as needed:

```bash
cp ../.env.example .env
```

Key settings:

| Variable | Default | Description |
|---|---|---|
| `PORT` | `4443` | HTTPS listen port |
| `PAIRING_CODE` | `307018` | Code shown to the POS during pairing |
| `AUTH_TOKEN` | (built-in default) | Device auth token after pairing |
| `MSSQL_*` | — | JTL-Wawi database connection |
| `MANDANT_*` | — | Mandant metadata returned to the client |
| `ROOT_CATEGORY_ID` | `1` | Root category for sync |
| `TAX_ZONE_NAME` | `Zone-EU` | Tax zone for product prices |
| `LOG_FILE` | `logs/requests.log` | Request log path |
| `ORDER_LOG_FILE` | `logs/orders.log` | Order log path |

The server starts without MSSQL if `MSSQL_USER` is unset or the connection fails — pairing and handshake still work, but catalog sync from the database is unavailable.

## TLS certificates

Place a certificate and key at `certs/cert.pem` and `certs/key.pem` (relative to the working directory when you run the binary).

```bash
mkdir -p certs
openssl req -x509 -newkey rsa:2048 -nodes \
  -keyout certs/key.pem -out certs/cert.pem -days 3650 \
  -subj '/CN=localhost/O=JTL POS Sync/C=DE' \
  -addext 'subjectAltName=DNS:localhost,IP:127.0.0.1,IP:0.0.0.0'
```

On startup the server prints the pairing code and whether MSSQL connected.

## API endpoints

| Method | Path | Description |
|---|---|---|
| GET | `/v1/client` | Client discovery / pairing |
| GET | `/v1/init` | Init handshake |
| GET | `/v1/category` | Category sync |
| GET | `/v1/product` | Product sync |
| GET | `/v1/productcomposite` | Composite product sync |
| GET | `/v1/deletedentity` | Deleted entity sync |
| GET | `/v1/customergroup` | Customer group sync |
| POST | `/v1/order` | Submit orders |
| GET | `/v1/pimage` | Product image (resized) |
| GET | `/v1/cimage` | Category image (resized) |

## Project layout

```
Makefile
src/
	main.cpp              Entry point, route registration, startup
	config.hpp            .env loader
	tls_server.{hpp,cpp}  HTTPS over libuv + OpenSSL
	http.{hpp,cpp}        llhttp request/response handling
	router.{hpp,cpp}      Route dispatch
	pairing.{hpp,cpp}     In-memory pairing store
	endpoints/            HTTP handlers
	queries/              SQL query builders (header-only)
	db/pool.{hpp,cpp}     ODBC connection pool
vendor/                 llhttp, nlohmann/json
```
