Files
tripz-llc/backend/src/modules/tenant-wallet/tenant-wallet.controller.ts
T

145 lines
4.5 KiB
TypeScript

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',
);
}
}