Files
tripz-llc/backend/src/modules/documents/documents.controller.ts
T
HamzaandClaude Opus 4.8 04200db438 feat(documents): full regional doc set (front/back + criminal record) + CS data-entry + DB pool bump
- doc types with side (front/back/single): license, national_id, vehicle_registration (both sides), criminal_record, selfie, vehicle_photo
- fields: side, holder_name(encrypted), issue_date, extra jsonb; REQUIRED_DOCS checklist + /requirements
- CS/admin: POST /admin/drivers/:id/documents (upload for driver), list, review auto-approves when complete
- face-match endpoint stub (Gemini/Face provider later)
- DB pool extra.max=30 (raises concurrency ceiling); migration DocumentsFields

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 19:52:55 +03:00

105 lines
3.5 KiB
TypeScript

import {
Body,
Controller,
Get,
Param,
Patch,
Post,
UploadedFile,
UseGuards,
UseInterceptors,
} from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
import { DocumentsService } from './documents.service';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { RolesGuard } from '../auth/guards/roles.guard';
import { Roles } from '../auth/decorators/roles.decorator';
import { CurrentUser, AuthUser } from '../auth/decorators/current-user.decorator';
@ApiTags('documents')
@ApiBearerAuth()
@Controller()
export class DocumentsController {
constructor(private readonly documents: DocumentsService) {}
// ===== السائق نفسه =====
@UseGuards(JwtAuthGuard)
@Post('drivers/documents')
@UseInterceptors(FileInterceptor('file'))
upload(@CurrentUser() user: AuthUser, @UploadedFile() file: any, @Body() body: any) {
return this.documents.uploadSelf(user.tenantId, user.userId, file, body);
}
@UseGuards(JwtAuthGuard)
@Get('drivers/documents/mine')
mine(@CurrentUser() user: AuthUser) {
return this.documents.listMine(user.tenantId, user.userId);
}
// قائمة الوثائق المطلوبة وحالتها للسائق الحالي
@UseGuards(JwtAuthGuard)
@Get('drivers/documents/requirements')
async myRequirements(@CurrentUser() user: AuthUser) {
const list = await this.documents.listMine(user.tenantId, user.userId);
const driverId = list[0]?.driver_id;
return driverId
? this.documents.requirements(user.tenantId, driverId)
: this.documents.requirements(user.tenantId, '00000000-0000-0000-0000-000000000000');
}
// ===== خدمة العملاء / الأدمن =====
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin', 'dispatcher')
@Post('admin/drivers/:driverId/documents')
@UseInterceptors(FileInterceptor('file'))
uploadForDriver(
@Param('driverId') driverId: string,
@CurrentUser() user: AuthUser,
@UploadedFile() file: any,
@Body() body: any,
) {
return this.documents.uploadForDriver(user.tenantId, driverId, file, body);
}
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin', 'dispatcher')
@Get('admin/drivers/:driverId/documents')
driverDocs(@Param('driverId') driverId: string, @CurrentUser() user: AuthUser) {
return this.documents.listByDriver(user.tenantId, driverId);
}
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin', 'dispatcher')
@Get('admin/drivers/:driverId/documents/requirements')
driverRequirements(@Param('driverId') driverId: string, @CurrentUser() user: AuthUser) {
return this.documents.requirements(user.tenantId, driverId);
}
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin', 'dispatcher')
@Get('admin/documents/pending')
pending(@CurrentUser() user: AuthUser) {
return this.documents.pending(user.tenantId);
}
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin', 'dispatcher')
@Patch('admin/documents/:id/review')
review(
@CurrentUser() user: AuthUser,
@Param('id') id: string,
@Body('status') status: 'approved' | 'rejected',
@Body('note') note: string,
) {
return this.documents.review(user.tenantId, id, user.userId, status, note);
}
@UseGuards(JwtAuthGuard, RolesGuard)
@Roles('admin', 'dispatcher')
@Post('admin/drivers/:driverId/face-match')
faceMatch(@Param('driverId') driverId: string, @CurrentUser() user: AuthUser) {
return this.documents.faceMatch(user.tenantId, driverId);
}
}