Files
api/src/sms/remote-sms.controller.ts
T

192 lines
4.8 KiB
TypeScript

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<string, unknown>,
) {
return this.smsService.remoteLogsTable(
tenant.id,
this.toTableQuery(body),
body,
);
}
@Post('ledger/table')
ledgerTable(
@RemoteTenant() tenant: RemoteTenantInfo,
@Body() body: Record<string, unknown>,
) {
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<string, unknown>): 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,
};
}
}