chore: add repo scaffolding (compose, scripts, gitignore, env example)

This commit is contained in:
ali_mohaghegh
2026-08-25 19:08:02 +03:30
commit 5b27647a0a
6 changed files with 415 additions and 0 deletions
+192
View File
@@ -0,0 +1,192 @@
# Procurement Stack v1.3 — Dockerized (PostgreSQL + FastAPI + React + MinIO)
Self-contained ship package: everything needed to run the stack is in this
folder — no external files or sibling folders required.
| Service | Container | Tech | Exposed port |
|---|---|---|---|
| **postgres** | `procurement-postgres` | PostgreSQL 18 | `5433` |
| **minio** | `procurement-minio` | MinIO object storage (S3-compatible) | `9000` (API), `9001` (console) |
| **casdoor** | `procurement-casdoor` | Casdoor (OIDC identity provider) | `8080` |
| **api** | `procurement-api` | FastAPI + SQLAlchemy (asyncpg) | `8000` |
| **frontend** | `procurement-frontend` | React 19 + Vite, served by nginx | `3000` |
```
Browser ──► frontend :3000 (nginx SPA)
│
└── /api/* proxy ──► api :8000 (FastAPI, /api/v1)
│
├── postgres :5432 (procurement DB)
├── minio :9000 (invoice/proforma files, bucket `procurement-files`)
└── casdoor :8000 (OIDC — login for the inventory panel)
```
---
## 📁 Layout
```text
v1.3/
├── docker-compose.yml ← all paths are relative to this folder
├── start.ps1 ← PowerShell helper (build + start + status)
├── mc.cmd ← MinIO Client helper (inspect the bucket)
├── README.md
├── sql/
│ └── migration.sql ← DB schema v2.6 (auto-runs on first boot)
├── docs/ ← ERDs + migration plan
│ ├── erd.txt (v2.4 — old procurement schema)
│ ├── new erd.txt (v2.5 — material → supplier → category)
│ ├── NewERD.txt (v2.6 — integrated procurement + inventory)
│ └── material-supplier-category-migration-plan.md
├── legacy/
│ └── dash-prototype/ ← shipped HTML/JS inventory dash (reference only)
├── backend/ ← build context of the `api` service
│ ├── Dockerfile
│ ├── requirements.txt
│ ├── .dockerignore
│ ├── app/ (source code — procurement + inventory + auth)
│ └── tools/ (smoke-test + seed scripts, copied into the image)
└── frontend/ ← build context of the `frontend` service
├── Dockerfile
├── nginx.conf
├── .dockerignore
├── .env.example (copy to .env if you need a custom API base URL)
├── index.html
├── package.json
├── package-lock.json
├── tsconfig*.json
├── vite.config.ts
├── public/
└── src/
└── pages/
├── Dashboard/ (procurement office)
├── Wizard/ (add new offer)
├── Suppliers/ (suppliers & topics)
├── Projects/ (projects)
├── Units/ (unit conversions)
└── Inventory/ (warehouse management panel — React port)
```
---
## 🔐 Login
The whole system is behind a login page (`/login`):
- **مدیر پروژه (PM)** → lands in the inventory panel (their project) — can record
stock changes and confirm arrivals («رسید کالاهای در راه»).
- **مدیر تدارکات / ادمین** → lands in the procurement office — can manage quotes,
suppliers and projects, and open the inventory panel in the read-only («فقط خواندنی»)
admin view.
Until Casdoor is fully seeded, use «ورود آزمایشی (توسعه)» on the login page
(role + project). Casdoor (org `inventory`, app `inventory-app`) is the planned
production identity source.
---
## Prerequisites (target machine)
- **Docker Desktop** (Windows) or Docker Engine + Compose plugin (Linux/macOS)
- ~3–4 GB free disk for images (`postgres:18`, `python:3.13-slim`, `node:22-alpine`, `nginx:alpine`, `minio/minio`, `minio/mc`)
- Internet access on first build (image + `npm ci` downloads)
---
## Start the whole stack
```powershell
cd <this-folder>
docker compose up -d --build
```
First run downloads base images and builds the frontend (takes a few minutes).
Subsequent runs: `docker compose up -d`.
Wait until all services are up:
```powershell
docker compose ps
```
All should show `Up` (postgres also `(healthy)`).
---
## Verify
| What | Where |
|---|---|
| Frontend UI | http://localhost:3000 |
| API docs (Swagger) | http://localhost:8000/docs |
| API health | http://localhost:8000/health → `{"status":"ok","service":"procurement-api"}` |
| MinIO console | http://localhost:9001 (user/pass `minioadmin`/`minioadmin`) |
| Database | `localhost:5433`, db `procurement`, user/pass `postgres`/`postgres` |
Quick end-to-end check (frontend proxy → API → DB):
```powershell
curl http://localhost:3000/api/v1/quotes?expand=supplier,project,line_items,termsheets,events,decision,receipt
```
---
## MinIO (object storage for invoice / proforma files)
| Item | Value |
|---|---|
| S3 API endpoint | `localhost:9000` (from the API container: `minio:9000`) |
| Web console | http://localhost:9001 |
| Root user / password | `minioadmin` / `minioadmin` (dev — change for production) |
| Bucket | `procurement-files` (created automatically by the `minio-init` container) |
| Object key layout | `{quote_id}/{kind}/{attachment_id}` where kind = `invoice` \| `proforma` |
File **bytes** live in MinIO; the `quote_attachments` table holds the metadata.
Ad-hoc bucket inspection from the host (see `mc.cmd`):
```powershell
.\mc.cmd ls --recursive
```
---
## Database credentials / connection
```text
Host: localhost
Port: 5433
Database: procurement
Username: postgres
Password: postgres
```
```powershell
docker exec -it procurement-postgres psql -U postgres -d procurement
```
---
## Common operations
```powershell
docker compose logs -f api # see logs
docker compose down # stop (keep data)
docker compose up -d --build # rebuild after code changes
docker compose down -v # ⚠️ full reset — wipes DB + MinIO volumes
```
---
## Known behavior
- The backend has **no authentication** (dev placeholder) — do not expose to the public internet.
- Schema runs automatically ONLY on the first boot of an empty `postgres_data` volume
(see `docker-entrypoint-initdb.d`); the API also runs `CREATE TABLE IF NOT EXISTS`
for the units-dashboard tables and `quote_attachments` at startup.
- Invoice upload requires an `accepted`/`arrived` quote; proforma has no restriction.
- The supplier detail page (`/suppliers/:id`) shows the purchase history with
invoice/proforma download links from MinIO.
- If builds fail with disk-full errors: `docker system prune -a`, then rebuild.
- If the frontend shows «اتصال به سرور برقرار نشد» → the api container is not
reachable; check `docker compose ps` and `docker compose logs api`.