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:
@@ -0,0 +1,15 @@
|
||||
import { Controller, Get } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
|
||||
@ApiTags('health')
|
||||
@Controller('health')
|
||||
export class HealthController {
|
||||
@Get()
|
||||
check() {
|
||||
return {
|
||||
status: 'ok',
|
||||
service: 'tripz-api',
|
||||
time: new Date().toISOString(),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { HealthController } from './health.controller';
|
||||
|
||||
@Module({ controllers: [HealthController] })
|
||||
export class HealthModule {}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { Body, Controller, Get, Param, Post } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { TenantsService } from './tenants.service';
|
||||
import { Tenant } from '../../database/entities/tenant.entity';
|
||||
|
||||
@ApiTags('tenants')
|
||||
@Controller()
|
||||
export class TenantsController {
|
||||
constructor(private readonly tenants: TenantsService) {}
|
||||
|
||||
// للتطبيق: إعداد المستأجر الحالي عند الإقلاع.
|
||||
@Get('tenant/config/:slug')
|
||||
config(@Param('slug') slug: string) {
|
||||
return this.tenants.config(slug);
|
||||
}
|
||||
|
||||
// للسوبر-آدمن: إدارة كل المستأجرين (يُحمى بحارس دور لاحقاً).
|
||||
@Get('admin/tenants')
|
||||
list() {
|
||||
return this.tenants.findAll();
|
||||
}
|
||||
|
||||
@Post('admin/tenants')
|
||||
create(@Body() body: Partial<Tenant>) {
|
||||
return this.tenants.create(body);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { Tenant } from '../../database/entities/tenant.entity';
|
||||
import { TenantsService } from './tenants.service';
|
||||
import { TenantsController } from './tenants.controller';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([Tenant])],
|
||||
controllers: [TenantsController],
|
||||
providers: [TenantsService],
|
||||
exports: [TenantsService],
|
||||
})
|
||||
export class TenantsModule {}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { Tenant } from '../../database/entities/tenant.entity';
|
||||
|
||||
@Injectable()
|
||||
export class TenantsService {
|
||||
constructor(
|
||||
@InjectRepository(Tenant)
|
||||
private readonly repo: Repository<Tenant>,
|
||||
) {}
|
||||
|
||||
findAll(): Promise<Tenant[]> {
|
||||
return this.repo.find();
|
||||
}
|
||||
|
||||
findBySlug(slug: string): Promise<Tenant | null> {
|
||||
return this.repo.findOne({ where: { slug } });
|
||||
}
|
||||
|
||||
create(data: Partial<Tenant>): Promise<Tenant> {
|
||||
return this.repo.save(this.repo.create(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* الإعداد الديناميكي الذي يجلبه تطبيق فلاتر عند الإقلاع (GET /tenant/config).
|
||||
* كل ما يمكن جعله ديناميكياً (نصوص، ميزات، ألوان، دفع) يأتي من هنا — راجع docs/06.
|
||||
*/
|
||||
async config(slug: string) {
|
||||
const t = await this.findBySlug(slug);
|
||||
if (!t) return null;
|
||||
return {
|
||||
slug: t.slug,
|
||||
name: t.name,
|
||||
countryPack: t.countryPack,
|
||||
plan: t.plan,
|
||||
branding: t.branding,
|
||||
features: t.features,
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user