import { Body, Controller, Get, Post, Query, UseGuards } from '@nestjs/common'; import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; import { TenantWalletService } from './tenant-wallet.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'; /** * محفظة المستأجر — يقرأها **أدمن المستأجر** لا السوبر-أدمن (docs/24). * النطاق من التوكن دائماً: `user.tenantId`، فلا يمكن لأدمن مستأجر قراءة * أرقام مستأجر آخر بتمرير معرّف في الطلب. */ @ApiTags('tenant-wallet') @ApiBearerAuth() @UseGuards(JwtAuthGuard, RolesGuard) @Roles('admin') @Controller('admin/wallet') export class TenantWalletController { constructor(private readonly wallet: TenantWalletService) {} /** الأرباح القابلة للسحب مقابل الأمانات المحتفَظ بها. */ @Get('summary') summary(@CurrentUser() user: AuthUser, @Query('currency') currency?: string) { return this.wallet.summary(user.tenantId, currency || 'JOD'); } /** من أين جاء الإيراد: شحن سائقين · عمولات · رسوم. */ @Get('revenue-by-reason') byReason( @CurrentUser() user: AuthUser, @Query('days') days?: string, @Query('currency') currency?: string, ) { const n = Number(days); return this.wallet.revenueByReason( user.tenantId, Number.isFinite(n) && n > 0 ? Math.min(n, 365) : 30, currency || 'JOD', ); } /** كشف حساب تفصيلي للدفتر. book يمكن أن يكون 'revenue' أو 'pending' */ @Get('statement') statement( @CurrentUser() user: AuthUser, @Query('book') book: 'revenue' | 'pending', @Query('currency') currency?: string, @Query('limit') limit?: string, @Query('offset') offset?: string, ) { return this.wallet.statement( book || 'revenue', user.tenantId, currency || 'JOD', limit ? parseInt(limit, 10) : 100, offset ? parseInt(offset, 10) : 0, ); } /** سحب أرباح المستأجر (من دفتر الإيرادات حصراً) */ @Post('withdraw') withdraw( @CurrentUser() user: AuthUser, @Body() body: { amount: number; currency?: string }, ) { return this.wallet.withdraw( user.tenantId, Number(body.amount), body.currency || 'JOD', ); } // ─── تقارير المستأجر (P4) ─────────────────────────────────────── /** إيراد حسب مزوّد الدفع (cash / cliq / syriatel / mtn / ...). */ @Get('report/by-provider') reportByProvider( @CurrentUser() user: AuthUser, @Query('days') days?: string, ) { const n = Number(days); return this.wallet.revenueByProvider( user.tenantId, Number.isFinite(n) && n > 0 ? Math.min(n, 365) : 30, ); } /** إيراد يومي — سلسلة زمنية. */ @Get('report/by-day') reportByDay( @CurrentUser() user: AuthUser, @Query('days') days?: string, @Query('currency') currency?: string, ) { const n = Number(days); return this.wallet.revenueByDay( user.tenantId, Number.isFinite(n) && n > 0 ? Math.min(n, 365) : 30, currency || 'JOD', ); } /** ملخّص الرحلات المالي (GMV + عمولة + خصومات). */ @Get('report/trips') reportTrips( @CurrentUser() user: AuthUser, @Query('days') days?: string, ) { const n = Number(days); return this.wallet.tripRevenueSummary( user.tenantId, Number.isFinite(n) && n > 0 ? Math.min(n, 365) : 30, ); } /** ملخّص سحوبات السائقين. */ @Get('report/payouts') reportPayouts( @CurrentUser() user: AuthUser, @Query('days') days?: string, ) { const n = Number(days); return this.wallet.payoutSummary( user.tenantId, Number.isFinite(n) && n > 0 ? Math.min(n, 365) : 30, ); } /** التقرير الشامل — يجمع كل شيء في طلب واحد. */ @Get('report/full') reportFull( @CurrentUser() user: AuthUser, @Query('days') days?: string, @Query('currency') currency?: string, ) { const n = Number(days); return this.wallet.fullReport( user.tenantId, Number.isFinite(n) && n > 0 ? Math.min(n, 365) : 30, currency || 'JOD', ); } }