All files / src/domains/crm/services lead-capture.service.ts

0% Statements 0/43
0% Branches 0/24
0% Functions 0/5
0% Lines 0/41

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121                                                                                                                                                                                                                                                 
import { Injectable, Logger, BadRequestException } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model, Types } from 'mongoose';
import {
  WebToLeadForm,
  WebToLeadSubmission,
} from '../schemas/automation-import.schema';
import { LeadService } from './lead.service';
 
@Injectable()
export class LeadCaptureService {
  private readonly logger = new Logger(LeadCaptureService.name);
 
  constructor(
    @InjectModel(WebToLeadForm.name)
    private readonly formModel: Model<WebToLeadForm>,
    @InjectModel(WebToLeadSubmission.name)
    private readonly submissionModel: Model<WebToLeadSubmission>,
    private readonly leadService: LeadService,
  ) {}
 
  async createForm(
    tenantId: Types.ObjectId,
    data: Partial<WebToLeadForm>,
  ): Promise<WebToLeadForm> {
    return this.formModel.create({ ...data, tenantId });
  }
 
  async getFormByCode(
    tenantId: Types.ObjectId,
    formCode: string,
  ): Promise<WebToLeadForm | null> {
    return this.formModel.findOne({ tenantId, formCode, active: true }).exec();
  }
 
  async submitLead(
    tenantId: Types.ObjectId,
    formCode: string,
    payload: any,
    ipAddress?: string,
    userAgent?: string,
    referrer?: string,
  ): Promise<WebToLeadSubmission> {
    const form = await this.getFormByCode(tenantId, formCode);
    if (!form) {
      throw new BadRequestException('Form not found or inactive');
    }
 
    // Capture submission log
    const submission = await this.submissionModel.create({
      tenantId,
      formId: form._id,
      rawPayload: payload,
      ipAddress,
      userAgent,
      referrer,
      processingStatus: 'pending',
    });
 
    try {
      // Basic validation of fields
      const mappedLead: any = {};
      for (const field of form.fields) {
        const val = payload[field.fieldName];
        if (
          field.required &&
          (val === undefined || val === null || val === '')
        ) {
          throw new BadRequestException(`Field ${field.fieldName} is required`);
        }
        if (val !== undefined && field.mapToLeadField) {
          mappedLead[field.mapToLeadField] = val;
        }
      }
 
      // Default tags/sources from form config
      mappedLead.leadSourceId = form.leadSourceId;
      mappedLead.campaignId = form.campaignId;
 
      // Create lead via leadService
      const lead = await this.leadService.createLead(tenantId, mappedLead);
 
      submission.processingStatus = 'processed';
      submission.createdLeadId = lead._id as any;
      submission.mappedPayload = mappedLead;
      submission.processedAt = new Date();
      await submission.save();
 
      // Update form submission count
      await this.formModel
        .updateOne(
          { _id: form._id },
          { $inc: { submissionCount: 1, conversionCount: 1 } },
        )
        .exec();
    } catch (err: any) {
      submission.processingStatus = 'failed';
      submission.errorMessage = err.message;
      submission.processedAt = new Date();
      await submission.save();
 
      await this.formModel
        .updateOne({ _id: form._id }, { $inc: { submissionCount: 1 } })
        .exec();
      throw err;
    }
 
    return submission;
  }
 
  async getSubmissions(
    tenantId: Types.ObjectId,
    formId: string,
  ): Promise<WebToLeadSubmission[]> {
    return this.submissionModel
      .find({ tenantId, formId: new Types.ObjectId(formId) })
      .sort({ createdAt: -1 })
      .exec();
  }
}