The repo CHANGELOG had fallen behind. Adds [Unreleased] entries for the recently shipped work and a README for the previously undocumented PdfService. Added (changelog): - Reports — Purchasing spend analytics (cost centres + accounting codes). - Email PO to vendor + the PdfService microservice (cached per PO). - EpfoService + PdfService microservices and their release auto-deploy. - Unsaved-changes prompt on PO create/edit (#18). - Crew login-on-hire for management ranks. - Delivery Locations (#19), T&C catalogue (#11), advance payment (#92). Fixed (changelog): - "Email to vendor" never rendered (auth middleware bounced the svc fetch) — #127. - Reports charts all one colour (RSC client/server boundary) — #120. New: PdfService/README.md (endpoints, token/origin security, env, app integration). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
54 lines
2.1 KiB
Markdown
54 lines
2.1 KiB
Markdown
# PdfService
|
|
|
|
Renders a PPMS purchase order to a real **PDF** for the **"Email PO to vendor"**
|
|
feature — a standalone **Express + Playwright** microservice, mirroring
|
|
`GstService` / `EpfoService`.
|
|
|
|
The app's `/api/po/:id/export?format=pdf&pdf=1` produces a print-styled HTML page;
|
|
PdfService loads that URL in **headless Chromium** and prints it to an A4 PDF. The
|
|
export URL carries a short-lived **`svc` token** so the export route serves the
|
|
page without a user session (the app's auth middleware allows that one route
|
|
through when the token matches — see `App/lib/pdf-export-auth.ts`).
|
|
|
|
## Endpoints
|
|
|
|
| Method | Path | Body / Headers | Returns |
|
|
|---|---|---|---|
|
|
| GET | `/health` | — | `{ status, browser }` |
|
|
| POST | `/pdf` | `{ url }` + header `x-pdf-token` | `application/pdf` (else `401` / `400` / `403` / `502`) |
|
|
|
|
## Security
|
|
|
|
- **Token** — when `PDF_SERVICE_TOKEN` is set, `/pdf` requires a matching
|
|
`x-pdf-token` header (the app and PdfService share the secret).
|
|
- **Origin allow-list (anti-SSRF)** — when `ALLOWED_ORIGIN` is set, PdfService
|
|
only navigates to URLs whose origin matches it.
|
|
- Both unset (dev) → checks are skipped.
|
|
|
|
## Env
|
|
|
|
```
|
|
PORT=3005
|
|
PDF_SERVICE_TOKEN= # shared secret with the app (app side: PDF_SERVICE_TOKEN)
|
|
ALLOWED_ORIGIN= # e.g. http://localhost:3000 (optional)
|
|
```
|
|
|
|
## Run
|
|
|
|
```
|
|
npm install
|
|
npm run dev # tsx watch src/index.ts
|
|
npm run build && npm start # node dist/index.js
|
|
```
|
|
|
|
## App integration
|
|
|
|
`App/lib/pdf-service.ts` (`renderPoPdf`) POSTs `{ url }` to `/pdf`. The app gates
|
|
the feature on `PDF_SERVICE_URL` + `PDF_SERVICE_TOKEN` (`isPdfServiceConfigured()`),
|
|
uploads the returned PDF to R2 at a **per-PO key** (reused across sends), and
|
|
returns a `mailto:` with a 7-day presigned link. `APP_INTERNAL_URL` is the base URL
|
|
PdfService reaches the app at (falls back to `NEXTAUTH_URL`).
|
|
|
|
On **pms1** the service is auto-deployed on each release tag via the root
|
|
`ecosystem.config.js` (pm2 `pdf-service`, port 3005) — see
|
|
[Deployment and Operations](https://git.pelagiamarine.com/shad0w/pelagia-portal/wiki/Deployment-and-Operations#microservices).
|