diff --git a/README.md b/README.md new file mode 100644 index 0000000..dd4de89 --- /dev/null +++ b/README.md @@ -0,0 +1,204 @@ +# Jorge Cuadros & Asociados — Platform + +Internal platform for a Baja California insurance brokerage and property-services +firm: a single expedient joining each client's **properties/services**, +**insurance policies**, **account statement**, and the firm's **checkbook**. +It replaces a legacy PHP/Access app (see `RESUME.md` and `PLAN.md` for the full +history and rebuild rationale). + +The UI is Spanish-first; the codebase and this document are in English. + +--- + +## Stack + +| Layer | Tech | Port | +| --------- | -------------------------------------------------------------- | ---- | +| Web | Next.js 14 (App Router, React 18) | 3000 | +| API | NestJS 10 · Passport local + `express-session` · Argon2 | 3001 | +| Database | MySQL 8 via Prisma 5 (`@jorgecuadros/database` workspace pkg) | 3306 | +| Migration | Python 3 pipeline (legacy Access → staging → transforms) | — | + +Monorepo managed with **pnpm workspaces**. Node **>= 20**. + +--- + +## Repository layout + +``` +apps/ + web/ Next.js frontend (@jorgecuadros/web) + api/ NestJS backend (@jorgecuadros/api) + scripts/seed-user.mjs idempotent admin seeder +packages/ + database/ Prisma schema + generated client (@jorgecuadros/database) + prisma/schema.prisma +migration/ One-off Python ETL from the legacy Access DB (run_all.py) +docker/ Dockerfiles for api + web +docker-compose.yml mysql + api + web +.env.example copy to .env +``` + +API feature modules: `auth`, `users`, `customers`, `policies`, `properties`, +`billing`, `bank`. Web routes: `/clientes`, `/polizas`, `/servicios`, +`/estado-cuenta`, `/banco` (chequera), `/catalogos`, `/usuarios`, `/login`. + +--- + +## Prerequisites + +- Node.js >= 20 and **pnpm** (`npm i -g pnpm`) +- Docker (for MySQL, or bring your own MySQL 8) +- Python 3 — only if you run the legacy data migration + +--- + +## Run it locally (development) + +### 1. Install + +```bash +pnpm install +``` + +pnpm blocks postinstall build scripts by default; the trusted ones +(`argon2`, `prisma`, `@prisma/client`, `@prisma/engines`, `@nestjs/core`) are +allowlisted in `pnpm-workspace.yaml`, so the native builds run automatically. + +### 2. Configure environment + +```bash +cp .env.example .env +``` + +Then edit `.env`. For the Docker MySQL below the defaults already line up; +just set a real `SESSION_SECRET`: + +```env +DATABASE_URL=mysql://jorgecuadros:jorgecuadros@localhost:3306/jorgecuadros +SESSION_SECRET= +WEB_ORIGIN=http://localhost:3000 +NEXT_PUBLIC_API_ORIGIN=http://localhost:3001 +``` + +The API loads `DATABASE_URL`, `SESSION_SECRET`, `WEB_ORIGIN`, and optional +`PORT` (default `3001`). The web app only needs `NEXT_PUBLIC_API_ORIGIN`. + +### 3. Start MySQL + +```bash +docker compose up -d mysql +``` + +(Or point `DATABASE_URL` at an existing MySQL 8 instance.) + +### 4. Create the schema + generate the Prisma client + +The schema is managed with `prisma db push` (no migration history committed): + +```bash +pnpm --filter @jorgecuadros/database exec prisma db push +pnpm --filter @jorgecuadros/database generate +``` + +### 5. Seed a sign-in user + +```bash +node apps/api/scripts/seed-user.mjs +``` + +Idempotent (upsert by email). Defaults — override with `SEED_EMAIL`, +`SEED_PASSWORD`, `SEED_NAME`: + +- email: `admin@jorgecuadros.local` +- password: `ChangeMe!2026` +- role: `ADMIN` + +### 6. Run the apps (two terminals) + +```bash +# API → http://localhost:3001 +pnpm --filter @jorgecuadros/api start:dev + +# Web → http://localhost:3000 +pnpm --filter @jorgecuadros/web dev +``` + +Root shortcuts also exist: `pnpm dev:api`, `pnpm dev:web`. + +### 7. Log in + +Open http://localhost:3000, sign in with the seeded credentials. +Sessions are cookie-based and last 8 hours. + +--- + +## Run it with Docker (full stack) + +Builds MySQL + API + web from `docker-compose.yml`: + +```bash +export SESSION_SECRET=$(openssl rand -hex 32) +docker compose up --build +``` + +Web on http://localhost:3000, API on http://localhost:3001. `SESSION_SECRET` +is required (compose fails without it). After first boot, push the schema and +seed a user against the container DB: + +```bash +docker compose exec api node apps/api/scripts/seed-user.mjs +``` + +--- + +## Common commands + +| Task | Command | +| ------------------------ | -------------------------------------------------------------- | +| Install | `pnpm install` | +| Dev — API | `pnpm dev:api` | +| Dev — Web | `pnpm dev:web` | +| Build all | `pnpm build` | +| Generate Prisma client | `pnpm prisma:generate` | +| Push schema (dev) | `pnpm --filter @jorgecuadros/database exec prisma db push` | +| Prisma Studio | `pnpm prisma:studio` | +| API tests | `pnpm --filter @jorgecuadros/api test` | +| Lint (web / api) | `pnpm --filter @jorgecuadros/web lint` · `... /api lint` | +| Seed admin user | `node apps/api/scripts/seed-user.mjs` | + +--- + +## Auth & roles + +Session auth via Passport local strategy; passwords hashed with Argon2 (no +plaintext, unlike the legacy app). Roles gate the UI and API — e.g. managing +`/catalogos` and `/usuarios` requires the appropriate ability (`ADMIN` / +`MANAGER`). New users are created by an admin in `/usuarios`; the first admin +comes from the seed script above. + +--- + +## Legacy data migration (optional) + +`migration/` holds the one-off Python ETL that lifts data out of the old +Microsoft Access database into MySQL. + +```bash +pip install -r migration/requirements.txt +python migration/run_all.py +``` + +> ⚠️ `run_all.py` truncates and reloads **all** downstream tables. Never run an +> individual `transform_*.py` in isolation — it orphans dependent tables. See +> `migration/RECONCILIATION.md` for details. + +--- + +## Production notes + +- Use `pnpm --filter @jorgecuadros/database exec prisma migrate deploy` if/when + a committed migration history is adopted; today dev uses `db push`. +- Set a strong `SESSION_SECRET` and a locked-down `DATABASE_URL`. +- The API expects `WEB_ORIGIN` to match the browser origin for session cookies. +- Documents are stored in MinIO in the deployed environment (see `RESUME.md`).