template-saas-backend-v2/src/modules/sales/dto/lead.dto.ts
Adrian Flores Cortes eb6a83daba feat(sales,commissions): Add Sales and Commissions backend modules
Sales Module (SAAS-018):
- Entities: PipelineStage, Lead, Opportunity, Activity
- Services: LeadsService, OpportunitiesService, ActivitiesService, PipelineService, SalesDashboardService
- Controllers: 25 endpoints for leads, opportunities, activities, pipeline, dashboard
- DTOs: Complete CRUD and query DTOs
- Integration with DDL functions: convert_lead_to_opportunity, update_opportunity_stage, calculate_lead_score

Commissions Module (SAAS-020):
- Entities: CommissionScheme, CommissionAssignment, CommissionPeriod, CommissionEntry
- Services: SchemesService, AssignmentsService, EntriesService, PeriodsService, CommissionsDashboardService
- Controllers: 25 endpoints for schemes, assignments, entries, periods, dashboard
- DTOs: Complete CRUD and query DTOs
- Integration with DDL functions: calculate_commission, close_period, get_user_earnings

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 22:23:02 -06:00

274 lines
4.0 KiB
TypeScript

import {
IsString,
IsEmail,
IsOptional,
IsEnum,
IsInt,
IsUUID,
IsObject,
MaxLength,
Min,
Max,
IsNumber,
} from 'class-validator';
import { LeadStatus, LeadSource } from '../entities';
export class CreateLeadDto {
@IsString()
@MaxLength(100)
firstName: string;
@IsString()
@MaxLength(100)
lastName: string;
@IsEmail()
@IsOptional()
email?: string;
@IsString()
@MaxLength(50)
@IsOptional()
phone?: string;
@IsString()
@MaxLength(200)
@IsOptional()
company?: string;
@IsString()
@MaxLength(150)
@IsOptional()
jobTitle?: string;
@IsString()
@MaxLength(255)
@IsOptional()
website?: string;
@IsEnum(LeadSource)
@IsOptional()
source?: LeadSource;
@IsEnum(LeadStatus)
@IsOptional()
status?: LeadStatus;
@IsInt()
@Min(0)
@Max(100)
@IsOptional()
score?: number;
@IsUUID()
@IsOptional()
assignedTo?: string;
@IsString()
@IsOptional()
notes?: string;
@IsString()
@MaxLength(255)
@IsOptional()
addressLine1?: string;
@IsString()
@MaxLength(255)
@IsOptional()
addressLine2?: string;
@IsString()
@MaxLength(100)
@IsOptional()
city?: string;
@IsString()
@MaxLength(100)
@IsOptional()
state?: string;
@IsString()
@MaxLength(20)
@IsOptional()
postalCode?: string;
@IsString()
@MaxLength(100)
@IsOptional()
country?: string;
@IsObject()
@IsOptional()
customFields?: Record<string, any>;
}
export class UpdateLeadDto {
@IsString()
@MaxLength(100)
@IsOptional()
firstName?: string;
@IsString()
@MaxLength(100)
@IsOptional()
lastName?: string;
@IsEmail()
@IsOptional()
email?: string;
@IsString()
@MaxLength(50)
@IsOptional()
phone?: string;
@IsString()
@MaxLength(200)
@IsOptional()
company?: string;
@IsString()
@MaxLength(150)
@IsOptional()
jobTitle?: string;
@IsString()
@MaxLength(255)
@IsOptional()
website?: string;
@IsEnum(LeadSource)
@IsOptional()
source?: LeadSource;
@IsEnum(LeadStatus)
@IsOptional()
status?: LeadStatus;
@IsInt()
@Min(0)
@Max(100)
@IsOptional()
score?: number;
@IsUUID()
@IsOptional()
assignedTo?: string;
@IsString()
@IsOptional()
notes?: string;
@IsString()
@MaxLength(255)
@IsOptional()
addressLine1?: string;
@IsString()
@MaxLength(255)
@IsOptional()
addressLine2?: string;
@IsString()
@MaxLength(100)
@IsOptional()
city?: string;
@IsString()
@MaxLength(100)
@IsOptional()
state?: string;
@IsString()
@MaxLength(20)
@IsOptional()
postalCode?: string;
@IsString()
@MaxLength(100)
@IsOptional()
country?: string;
@IsObject()
@IsOptional()
customFields?: Record<string, any>;
}
export class ConvertLeadDto {
@IsString()
@MaxLength(255)
@IsOptional()
opportunityName?: string;
@IsNumber()
@Min(0)
@IsOptional()
amount?: number;
@IsOptional()
expectedCloseDate?: string;
}
export class LeadResponseDto {
id: string;
tenantId: string;
firstName: string;
lastName: string;
fullName: string;
email: string | null;
phone: string | null;
company: string | null;
jobTitle: string | null;
website: string | null;
source: LeadSource;
status: LeadStatus;
score: number;
assignedTo: string | null;
notes: string | null;
convertedAt: Date | null;
convertedToOpportunityId: string | null;
addressLine1: string | null;
addressLine2: string | null;
city: string | null;
state: string | null;
postalCode: string | null;
country: string | null;
customFields: Record<string, any>;
createdAt: Date;
updatedAt: Date;
createdBy: string | null;
}
export class LeadListQueryDto {
@IsEnum(LeadStatus)
@IsOptional()
status?: LeadStatus;
@IsEnum(LeadSource)
@IsOptional()
source?: LeadSource;
@IsUUID()
@IsOptional()
assignedTo?: string;
@IsString()
@IsOptional()
search?: string;
@IsOptional()
page?: number;
@IsOptional()
limit?: number;
}
export class PaginatedLeadsDto {
items: LeadResponseDto[];
total: number;
page: number;
limit: number;
totalPages: number;
}