import { IsString, IsEnum, IsOptional, IsBoolean, IsNumber, IsArray, ValidateNested, Min } from 'class-validator'; import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { BillingCycle, PricingResourceType, AppRuntime, InvoiceStatus, ProductType } from '../../common/enums'; import { OptionalServiceResourcesDto } from './optional-service-resources.dto'; export class CreatePricingRuleDto { @ApiProperty({ enum: PricingResourceType }) @IsEnum(PricingResourceType) resourceType: PricingResourceType; @ApiProperty({ example: 5000, description: 'Unit price in Toman' }) @IsNumber() @Min(0) unitPrice: number; @ApiPropertyOptional({ example: 'CPU per core per hour' }) @IsOptional() @IsString() description?: string; } export class CreateServicePlanDto { @ApiProperty({ example: 'Node.js Standard' }) @IsString() name: string; @ApiProperty({ enum: AppRuntime, example: 'nodejs' }) @IsEnum(AppRuntime) runtime: AppRuntime; @ApiPropertyOptional({ example: 'Standard plan for Node.js applications' }) @IsOptional() @IsString() description?: string; @ApiProperty({ enum: BillingCycle }) @IsEnum(BillingCycle) billingCycle: BillingCycle; @ApiProperty({ type: [CreatePricingRuleDto] }) @IsArray() @ValidateNested({ each: true }) @Type(() => CreatePricingRuleDto) pricingRules: CreatePricingRuleDto[]; } export class UpdateServicePlanDto { @ApiPropertyOptional() @IsOptional() @IsString() name?: string; @ApiPropertyOptional({ enum: AppRuntime }) @IsOptional() @IsEnum(AppRuntime) runtime?: AppRuntime; @ApiPropertyOptional() @IsOptional() @IsString() description?: string; @ApiPropertyOptional({ enum: BillingCycle }) @IsOptional() @IsEnum(BillingCycle) billingCycle?: BillingCycle; @ApiPropertyOptional() @IsOptional() @IsBoolean() isActive?: boolean; @ApiPropertyOptional({ type: [CreatePricingRuleDto] }) @IsOptional() @IsArray() @ValidateNested({ each: true }) @Type(() => CreatePricingRuleDto) pricingRules?: CreatePricingRuleDto[]; } export class ChargeWalletDto { @ApiProperty({ example: 50000, description: 'Amount to charge in Toman' }) @IsNumber() @Min(1000) amount: number; @ApiPropertyOptional({ example: 'Manual top-up' }) @IsOptional() @IsString() description?: string; } export class CalculateCostDto { @ApiPropertyOptional({ enum: ProductType, default: ProductType.APPLICATION }) @IsOptional() @IsEnum(ProductType) productType?: ProductType; @ApiProperty({ example: 'nodejs' }) @IsString() runtime: string; @ApiProperty({ example: 'postgresql' }) @IsString() databaseType: string; @ApiProperty({ example: '500m', description: 'CPU limit' }) @IsString() cpuLimit: string; @ApiProperty({ example: '512Mi', description: 'Memory limit' }) @IsString() memoryLimit: string; @ApiPropertyOptional({ example: 1, description: 'Number of replicas (0 for managed services)' }) @IsOptional() @IsNumber() @Min(0) replicas?: number; @ApiProperty({ example: '1Gi', description: 'Database storage size' }) @IsOptional() @IsString() dbStorageSize?: string; @ApiProperty({ example: '2Gi', description: 'App storage size for uploads/wp-content' }) @IsOptional() @IsString() appStorageSize?: string; @ApiPropertyOptional({ example: false, description: 'Enable Redis caching' }) @IsOptional() @IsBoolean() enableRedis?: boolean; @ApiPropertyOptional({ example: false, description: 'Enable RabbitMQ message broker' }) @IsOptional() @IsBoolean() enableRabbitmq?: boolean; @ApiPropertyOptional({ example: false, description: 'Enable Elasticsearch logging' }) @IsOptional() @IsBoolean() enableElasticsearch?: boolean; @ApiPropertyOptional({ type: OptionalServiceResourcesDto, description: 'Per-database CPU/RAM/storage limits' }) @IsOptional() @ValidateNested() @Type(() => OptionalServiceResourcesDto) databaseResources?: OptionalServiceResourcesDto; @ApiPropertyOptional({ type: OptionalServiceResourcesDto }) @IsOptional() @ValidateNested() @Type(() => OptionalServiceResourcesDto) redisResources?: OptionalServiceResourcesDto; @ApiPropertyOptional({ type: OptionalServiceResourcesDto }) @IsOptional() @ValidateNested() @Type(() => OptionalServiceResourcesDto) rabbitmqResources?: OptionalServiceResourcesDto; @ApiPropertyOptional({ example: false, description: 'Enable custom domain with SSL' }) @IsOptional() @IsBoolean() enableCustomDomain?: boolean; } export class CalculateDeployCostDto extends CalculateCostDto { @ApiProperty({ enum: BillingCycle, example: 'monthly' }) @IsEnum(BillingCycle) cycle: BillingCycle; @ApiPropertyOptional({ example: 'NOWRUZ1403', description: 'Coupon discount code' }) @IsOptional() @IsString() couponCode?: string; } export class PayApplicationDto { @ApiProperty({ enum: BillingCycle, example: 'monthly' }) @IsEnum(BillingCycle) cycle: BillingCycle; @ApiPropertyOptional({ example: 'NOWRUZ1403', description: 'Coupon discount code' }) @IsOptional() @IsString() couponCode?: string; } // ─── Renewal & Upgrade DTOs ───────────────────────────────────────── export class RenewApplicationDto { @ApiProperty({ enum: BillingCycle, example: 'monthly' }) @IsEnum(BillingCycle) cycle: BillingCycle; @ApiPropertyOptional({ example: 'NOWRUZ1403', description: 'Coupon discount code' }) @IsOptional() @IsString() couponCode?: string; } export class UpgradeResourcesDto { @ApiPropertyOptional({ example: '500m', description: 'New CPU request' }) @IsOptional() @IsString() cpuRequest?: string; @ApiPropertyOptional({ example: '1000m', description: 'New CPU limit' }) @IsOptional() @IsString() cpuLimit?: string; @ApiPropertyOptional({ example: '256Mi', description: 'New memory request' }) @IsOptional() @IsString() memoryRequest?: string; @ApiPropertyOptional({ example: '1Gi', description: 'New memory limit' }) @IsOptional() @IsString() memoryLimit?: string; @ApiPropertyOptional({ example: 2, description: 'New replica count' }) @IsOptional() @IsNumber() @Min(1) replicas?: number; @ApiPropertyOptional({ example: '5Gi', description: 'New database storage size' }) @IsOptional() @IsString() dbStorageSize?: string; @ApiPropertyOptional({ example: '5Gi', description: 'New app storage size for uploads/wp-content' }) @IsOptional() @IsString() appStorageSize?: string; @ApiPropertyOptional({ type: OptionalServiceResourcesDto, description: 'Database resource limits' }) @IsOptional() @ValidateNested() @Type(() => OptionalServiceResourcesDto) databaseResources?: OptionalServiceResourcesDto; @ApiPropertyOptional({ type: OptionalServiceResourcesDto, description: 'Managed Redis resource limits' }) @IsOptional() @ValidateNested() @Type(() => OptionalServiceResourcesDto) redisResources?: OptionalServiceResourcesDto; @ApiPropertyOptional({ type: OptionalServiceResourcesDto, description: 'Managed RabbitMQ resource limits' }) @IsOptional() @ValidateNested() @Type(() => OptionalServiceResourcesDto) rabbitmqResources?: OptionalServiceResourcesDto; @ApiPropertyOptional({ example: 'NOWRUZ1403', description: 'Coupon discount code' }) @IsOptional() @IsString() couponCode?: string; } export class CalculateUpgradeCostDto extends UpgradeResourcesDto {} // ─── Invoice DTOs ─────────────────────────────────────────────────── export class InitiateInvoicePaymentDto { @ApiProperty({ example: 'https://app.example.com/dashboard/invoices' }) @IsString() callbackUrl: string; } export class VerifyInvoiceGatewayDto { @ApiProperty({ example: 'INV-1710000000000-ABC123' }) @IsString() trackingCode: string; @ApiProperty({ example: 50000 }) @IsNumber() @Min(1) amount: number; } export class UpdateInvoiceStatusDto { @ApiProperty({ enum: InvoiceStatus }) @IsEnum(InvoiceStatus) status: InvoiceStatus; @ApiProperty({ example: 'Manual reconciliation by finance team' }) @IsString() reason: string; } // ─── Platform optional services pricing (Admin) ───────────────────── export class OptionalServiceCyclePricesDto { @ApiProperty({ example: 500 }) @IsNumber() @Min(0) hourly: number; @ApiProperty({ example: 50000 }) @IsNumber() @Min(0) monthly: number; @ApiProperty({ example: 500000 }) @IsNumber() @Min(0) yearly: number; } export class SetOptionalServicesPricingDto { @ApiProperty({ type: OptionalServiceCyclePricesDto }) @ValidateNested() @Type(() => OptionalServiceCyclePricesDto) redis: OptionalServiceCyclePricesDto; @ApiProperty({ type: OptionalServiceCyclePricesDto }) @ValidateNested() @Type(() => OptionalServiceCyclePricesDto) rabbitmq: OptionalServiceCyclePricesDto; @ApiProperty({ type: OptionalServiceCyclePricesDto }) @ValidateNested() @Type(() => OptionalServiceCyclePricesDto) elasticsearch: OptionalServiceCyclePricesDto; }