import { Body, Controller, Get, Post, Put, Query, UseGuards, } from '@nestjs/common'; import { RemoteTenant } from '../auth/remote-tenant.decorator'; import { RemoteSmsAuthGuard } from '../auth/remote-sms-auth.guard'; import { RemoteSmsBlockDto, RemoteSmsChargeDto, RemoteSmsChargeInfoDto, RemoteSmsConsumeDto, RemoteSmsPriceDto, SmsTableQueryDto, } from './dto/sms-account.dto'; import { SmsService } from './sms.service'; type RemoteTenantInfo = { id: string; nameFa: string; domain: string | null; product: string; isActive: boolean; }; /** * Product apps → SuperAdmin SMS wallet + panel sync. * * Auth (preferred): shared HMAC * X-Abshode-Domain, X-Abshode-Timestamp, X-Abshode-Signature * Fallback: Authorization Bearer {Tenant.remoteApiToken} * * Gate: GET /api/remote/sms/status * Consume: POST /api/remote/sms/consume * Panel: overview / charge-info / charge / price / block / logs / ledger / report */ @Controller('remote/sms') @UseGuards(RemoteSmsAuthGuard) export class RemoteSmsController { constructor(private readonly smsService: SmsService) {} @Get('status') status( @RemoteTenant() tenant: RemoteTenantInfo, @Query('parts') parts?: string, @Query('isAlert') isAlert?: string, ) { const n = Math.max(1, Math.min(50, Number(parts) || 1)); const alert = isAlert === '1' || isAlert === 'true'; return this.smsService.remoteStatus(tenant.id, n, alert); } @Post('consume') consume( @RemoteTenant() tenant: RemoteTenantInfo, @Body() dto: RemoteSmsConsumeDto, ) { return this.smsService.remoteConsume(tenant.id, dto); } @Get('overview') overview(@RemoteTenant() tenant: RemoteTenantInfo) { return this.smsService.remoteOverview(tenant.id); } @Get('balance') balance(@RemoteTenant() tenant: RemoteTenantInfo) { return this.smsService.remoteBalance(tenant.id); } @Get('charge-info') chargeInfo(@RemoteTenant() tenant: RemoteTenantInfo) { return this.smsService.remoteChargeInfo(tenant.id); } @Put('charge-info') updateChargeInfo( @RemoteTenant() tenant: RemoteTenantInfo, @Body() dto: RemoteSmsChargeInfoDto, ) { return this.smsService.remoteUpdateChargeInfo(tenant.id, dto); } @Post('charge') charge( @RemoteTenant() tenant: RemoteTenantInfo, @Body() dto: RemoteSmsChargeDto, ) { return this.smsService.remoteCharge(tenant.id, dto); } @Put('price') updatePrice( @RemoteTenant() tenant: RemoteTenantInfo, @Body() dto: RemoteSmsPriceDto, ) { return this.smsService.remoteUpdatePrice(tenant.id, dto.price_per_part); } @Put('block') updateBlock( @RemoteTenant() tenant: RemoteTenantInfo, @Body() dto: RemoteSmsBlockDto, ) { return this.smsService.remoteSetBlocked(tenant.id, dto.is_blocked); } @Post('logs/table') logsTable( @RemoteTenant() tenant: RemoteTenantInfo, @Body() body: Record, ) { return this.smsService.remoteLogsTable( tenant.id, this.toTableQuery(body), body, ); } @Post('ledger/table') ledgerTable( @RemoteTenant() tenant: RemoteTenantInfo, @Body() body: Record, ) { return this.smsService.remoteLedgerTable( tenant.id, this.toTableQuery(body), body, ); } @Get('report') report( @RemoteTenant() tenant: RemoteTenantInfo, @Query('from_date') fromDate?: string, @Query('to_date') toDate?: string, @Query('fromDate') fromDateCamel?: string, @Query('toDate') toDateCamel?: string, ) { return this.smsService.remotePeriodReport( tenant.id, fromDate || fromDateCamel, toDate || toDateCamel, ); } @Get('report/charges') chargeReport( @RemoteTenant() tenant: RemoteTenantInfo, @Query('from_date') fromDate?: string, @Query('to_date') toDate?: string, @Query('fromDate') fromDateCamel?: string, @Query('toDate') toDateCamel?: string, ) { return this.smsService.remoteChargeReport( tenant.id, fromDate || fromDateCamel, toDate || toDateCamel, ); } private toTableQuery(body: Record): SmsTableQueryDto { const page = Number(body.page) || 1; const pageSize = Number(body.pageSize) || Number(body.limit) || 20; const search = (typeof body.search === 'string' && body.search) || (typeof body.text_search === 'string' && body.text_search) || undefined; const fromDate = (typeof body.from_date === 'string' && body.from_date) || (typeof body.fromDate === 'string' && body.fromDate) || undefined; const toDate = (typeof body.to_date === 'string' && body.to_date) || (typeof body.toDate === 'string' && body.toDate) || undefined; return { page: Math.max(1, page), pageSize: Math.min(100, Math.max(1, pageSize)), search, fromDate, toDate, }; } }