Muluhabt ERP modules

This commit is contained in:
Mulu Mehari
2026-08-25 00:11:39 +03:00
parent 5c2100e76d
commit 70171fa9d8
441 changed files with 68587 additions and 214 deletions

View File

@@ -129,6 +129,101 @@ node server.js
Next.js reads `PORT` from the runtime environment (supplied via `env_file` in docker-compose). The standalone output bundles only the required `node_modules`, producing a significantly smaller image than a full `pnpm deploy`.
## Database consolidation runbook (single schema-separated database)
The platform runs on **one** Postgres database, separated by schema — `iam`, `freight`,
`passenger`, `edr_payment`, `audit`. This is the production topology (the
`dump-smart_office_prod-*.sql` dump is the `freight` schema of a Smart Office database),
and dev/local configs now match it.
Environments that predate this ran freight on its own server (`5433`, database
`edr_freight`) with a **second copy of the `iam` schema**, while passenger and payment used
another database. Use this sequence to collapse them. It is a data move — the config
changes alone do not migrate a single row.
**Authoritative copy: `edr_freight`'s `iam`.** It is the copy freight-api's
`iam:migration:run|show|revert` scripts have been applying migrations to, so its schema is
the most current. The other copy's rows are backfilled into it, never the reverse.
### 1. Snapshot both sources
```bash
pg_dump -Fc -h <old-freight-host> -p 5433 -d edr_freight -f pre-consolidation-freight.dump
pg_dump -Fc -h <old-shared-host> -p 5432 -d edr_database -f pre-consolidation-shared.dump
```
### 2. Create the target database and schemas
Under compose this is automatic (`infrastructure/docker/initdb/01-schemas.sql`). Against an
existing server:
```sql
CREATE DATABASE edr_database;
\connect edr_database
CREATE SCHEMA IF NOT EXISTS iam;
CREATE SCHEMA IF NOT EXISTS freight;
CREATE SCHEMA IF NOT EXISTS passenger;
CREATE SCHEMA IF NOT EXISTS edr_payment;
CREATE SCHEMA IF NOT EXISTS audit;
```
### 3. Restore the authoritative IAM first, then freight
```bash
# iam — including iam.typeorm_migrations, so freight-api does not re-run applied migrations
pg_restore -d edr_database -n iam pre-consolidation-freight.dump
# freight — including freight.migrations
pg_restore -d edr_database -n freight pre-consolidation-freight.dump
```
### 4. Restore the other domains
```bash
pg_restore -d edr_database -n passenger pre-consolidation-shared.dump
pg_restore -d edr_database -n edr_payment pre-consolidation-shared.dump
```
Do **not** restore the second `iam` schema over the first. Back its rows in instead:
`iam.users.username`, `.email` and `.phone_number` are all `UNIQUE`, so the two copies
reconcile on those columns. Insert only users present in the secondary copy and absent from
the authoritative one, and record the old→new id mapping — anything that stored the
secondary copy's user ids (audit rows, `*_user_id` columns in `passenger`) must be remapped
with it. Cross-schema references are soft UUIDs with no FK to catch a miss.
### 5. Repoint the applications
| App | Variables | Value |
| --- | --- | --- |
| `edr-freight-api` | `DB_HOST` `DB_PORT` `DB_USER` `DB_PASSWORD` `DB_NAME` | the consolidated database |
| `edr-gps-tracker` | same `DB_*` | same |
| `edr-payment-api` | same `DB_*` (+ `DB_SCHEMA=edr_payment`) | same |
| `edr-passenger-api` | `DATABASE_URL` (`?schema=passenger`) **and** `DATABASE_HOST/PORT/NAME/USER/PASSWORD` (+ `DATABASE_SCHEMA=iam`) | same |
Both of passenger-api's connections must resolve to this one database — its Prisma URL and
its read-only TypeORM IAM connection are configured separately and can silently diverge.
### 6. Verify before opening traffic
```sql
-- every expected schema present
SELECT nspname FROM pg_namespace WHERE nspname IN
('iam','freight','passenger','edr_payment','audit');
-- migration histories carried over: no re-runs, no gaps
SELECT count(*) FROM iam.typeorm_migrations; -- matches the source count
SELECT count(*) FROM freight.migrations; -- matches the source count
-- no duplicate humans after the IAM backfill
SELECT username, count(*) FROM iam.users GROUP BY username HAVING count(*) > 1;
```
Then run freight-api's migration step (`docker build --target migration`) and confirm it
applies **zero** new migrations — a non-zero count means step 3 dropped a history table.
### Out of scope
The e2e harnesses stay hermetic and are deliberately untouched: `edr_freight_e2e` on 5533
(`e2e/freight/`) and the passenger test database on 5544 (`e2e/docker-compose.yml`,
`apps/edr-passenger-api/.env.test`).
## Rollback Procedure
Each build is tagged with the short git SHA (`${COMPOSE_PROJECT_NAME}-<service>:<sha8>`).