first commit: منصة Tripz — خطط كاملة + سكافولد باك إند NestJS/Docker

- docs/00-15: دراسة، بنية، محرك تعرفة، تسعير، نموذج استئجار، تكاملات، بيانات، realtime، خطة، devops، لاندنج، مخاطر، اصطلاحات سيرفر، تدفق نشر
- backend/: NestJS 11 على Docker (health + tenants + عزل tenant_id + بادئة tripz_ + Redis DB 3)
- apps/rider, apps/driver, dashboards/admin-web, dashboards/superadmin-web (هياكل)
- sync-to-server.sh + .gitignore

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-16 15:22:06 +03:00
co-authored by Claude Opus 4.8
commit 95fea546f5
49 changed files with 1881 additions and 0 deletions
@@ -0,0 +1,50 @@
import {
Column,
CreateDateColumn,
Entity,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
export type TenantMode = 'shared' | 'sovereign';
export type TenantPlan = 'launch' | 'brand' | 'fleet' | 'sovereign';
/**
* المستأجر = مكتب تكسي / أسطول / مشغّل. الجدول الفعلي: tripz_tenants
* (البادئة من entityPrefix). راجع docs/06 و docs/08.
*/
@Entity('tenants')
export class Tenant {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column()
name: string;
@Column({ unique: true })
slug: string;
@Column({ name: 'country_pack', default: 'jo' })
countryPack: string;
@Column({ type: 'varchar', default: 'launch' })
plan: TenantPlan;
@Column({ type: 'varchar', default: 'shared' })
mode: TenantMode;
@Column({ type: 'jsonb', default: {} })
branding: Record<string, any>;
@Column({ type: 'jsonb', default: {} })
features: Record<string, any>;
@Column({ default: 'active' })
status: string;
@CreateDateColumn({ name: 'created_at' })
createdAt: Date;
@UpdateDateColumn({ name: 'updated_at' })
updatedAt: Date;
}
@@ -0,0 +1,32 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
/**
* أول هجرة: جدول المستأجرين + تفعيل PostGIS.
* اسم الجدول الفعلي tripz_tenants (البادئة تُضاف عبر entityPrefix، لكن الهجرة
* تكتب الاسم صراحةً لأنها SQL خام).
*/
export class InitTenants1721145600000 implements MigrationInterface {
public async up(q: QueryRunner): Promise<void> {
await q.query(`CREATE EXTENSION IF NOT EXISTS postgis`);
await q.query(`CREATE EXTENSION IF NOT EXISTS "uuid-ossp"`);
await q.query(`
CREATE TABLE IF NOT EXISTS tripz_tenants (
id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
name varchar NOT NULL,
slug varchar NOT NULL UNIQUE,
country_pack varchar NOT NULL DEFAULT 'jo',
plan varchar NOT NULL DEFAULT 'launch',
mode varchar NOT NULL DEFAULT 'shared',
branding jsonb NOT NULL DEFAULT '{}',
features jsonb NOT NULL DEFAULT '{}',
status varchar NOT NULL DEFAULT 'active',
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now()
)
`);
}
public async down(q: QueryRunner): Promise<void> {
await q.query(`DROP TABLE IF EXISTS tripz_tenants`);
}
}