From dcba3335e26b859b6c8d3d9bd3e4f6cc7e964bbe Mon Sep 17 00:00:00 2001 From: Rajesh Jonnalagadda Date: Thu, 6 Jun 2024 14:43:44 +0530 Subject: [PATCH] feat: add stage integartion to the connector --- .../crm/services/close/close.service.ts | 5 +- .../utils/types/original/original.crm.ts | 10 ++- .../api/src/crm/stage/services/close/index.ts | 70 +++++++++++++++++++ .../src/crm/stage/services/close/mappers.ts | 54 ++++++++++++++ .../api/src/crm/stage/services/close/types.ts | 52 ++++++++++++++ packages/api/src/crm/stage/stage.module.ts | 2 + .../api/src/crm/stage/types/mappingsTypes.ts | 6 ++ 7 files changed, 193 insertions(+), 6 deletions(-) create mode 100644 packages/api/src/crm/stage/services/close/index.ts create mode 100644 packages/api/src/crm/stage/services/close/mappers.ts create mode 100644 packages/api/src/crm/stage/services/close/types.ts diff --git a/packages/api/src/@core/connections/crm/services/close/close.service.ts b/packages/api/src/@core/connections/crm/services/close/close.service.ts index 138c2bb08..1bfa284ac 100644 --- a/packages/api/src/@core/connections/crm/services/close/close.service.ts +++ b/packages/api/src/@core/connections/crm/services/close/close.service.ts @@ -85,10 +85,7 @@ export class CloseConnectionService implements ICrmConnectionService { }, ); const data: CloseOAuthResponse = res.data; - this.logger.log( - 'OAuth credentials : close ticketing ' + JSON.stringify(data), - ); - + this.logger.log('OAuth credentials : close CRM ' + JSON.stringify(data)); let db_res; const connection_token = uuidv4(); diff --git a/packages/api/src/@core/utils/types/original/original.crm.ts b/packages/api/src/@core/utils/types/original/original.crm.ts index 187d4c84d..3f06b1c10 100644 --- a/packages/api/src/@core/utils/types/original/original.crm.ts +++ b/packages/api/src/@core/utils/types/original/original.crm.ts @@ -82,6 +82,10 @@ import { ZohoStageInput, ZohoStageOutput, } from '@crm/stage/services/zoho/types'; +import { + CloseStageInput, + CloseStageOutput, +} from '@crm/stage/services/close/types'; import { HubspotTaskInput, HubspotTaskOutput, @@ -178,7 +182,8 @@ export type OriginalStageInput = | HubspotStageInput | ZohoStageInput | ZendeskStageInput - | PipedriveStageInput; + | PipedriveStageInput + | CloseStageInput; /* engagementType */ @@ -256,7 +261,8 @@ export type OriginalStageOutput = | HubspotStageOutput | ZohoStageOutput | ZendeskStageOutput - | PipedriveStageOutput; + | PipedriveStageOutput + | CloseStageOutput; /* engagementType */ diff --git a/packages/api/src/crm/stage/services/close/index.ts b/packages/api/src/crm/stage/services/close/index.ts new file mode 100644 index 000000000..d7d8b4eeb --- /dev/null +++ b/packages/api/src/crm/stage/services/close/index.ts @@ -0,0 +1,70 @@ +import { Injectable } from '@nestjs/common'; +import { IStageService } from '@crm/stage/types'; +import { CrmObject } from '@crm/@lib/@types'; +import { CloseStageOutput, commonStageCloseProperties } from './types'; +import axios from 'axios'; +import { PrismaService } from '@@core/prisma/prisma.service'; +import { LoggerService } from '@@core/logger/logger.service'; +import { ActionType, handleServiceError } from '@@core/utils/errors'; +import { EncryptionService } from '@@core/encryption/encryption.service'; +import { ApiResponse } from '@@core/utils/types'; +import { ServiceRegistry } from '../registry.service'; + +@Injectable() +export class CloseService implements IStageService { + constructor( + private prisma: PrismaService, + private logger: LoggerService, + private cryptoService: EncryptionService, + private registry: ServiceRegistry, + ) { + this.logger.setContext( + CrmObject.stage.toUpperCase() + ':' + CloseService.name, + ); + this.registry.registerService('close', this); + } + + async syncStages( + linkedUserId: string, + deal_id: string, + custom_properties?: string[], + ): Promise> { + try { + const connection = await this.prisma.connections.findFirst({ + where: { + id_linked_user: linkedUserId, + provider_slug: 'close', + vertical: 'crm', + }, + }); + + const res = await this.prisma.crm_deals.findUnique({ + where: { id_crm_deal: deal_id }, + }); + const baseURL = `${connection.account_url}/activity/status_change/opportunity/?opportunity_id=${res.remote_id}`; + + const resp = await axios.get(baseURL, { + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${this.cryptoService.decrypt( + connection.access_token, + )}`, + }, + }); + this.logger.log(`Synced close stages !`); + return { + data: resp?.data?.data, + message: 'Close stages retrieved', + statusCode: 200, + }; + } catch (error) { + handleServiceError( + error, + this.logger, + 'Close', + CrmObject.stage, + ActionType.GET, + ); + } + } +} diff --git a/packages/api/src/crm/stage/services/close/mappers.ts b/packages/api/src/crm/stage/services/close/mappers.ts new file mode 100644 index 000000000..c26e06354 --- /dev/null +++ b/packages/api/src/crm/stage/services/close/mappers.ts @@ -0,0 +1,54 @@ +import { CloseStageOutput, CloseStageInput } from './types'; +import { + UnifiedStageInput, + UnifiedStageOutput, +} from '@crm/stage/types/model.unified'; +import { IStageMapper } from '@crm/stage/types'; + +export class CloseStageMapper implements IStageMapper { + desunify( + source: UnifiedStageInput, + customFieldMappings?: { + slug: string; + remote_id: string; + }[], + ): CloseStageInput { + return {}; + } + + unify( + source: CloseStageOutput | CloseStageOutput[], + customFieldMappings?: { + slug: string; + remote_id: string; + }[], + ): UnifiedStageOutput | UnifiedStageOutput[] { + if (!Array.isArray(source)) { + return this.mapSingleStageToUnified(source, customFieldMappings); + } + // Handling array of CloseStageOutput + return source.map((stage) => + this.mapSingleStageToUnified(stage, customFieldMappings), + ); + } + + private mapSingleStageToUnified( + stage: CloseStageOutput, + customFieldMappings?: { + slug: string; + remote_id: string; + }[], + ): UnifiedStageOutput { + const field_mappings: { [key: string]: any } = {}; + if (customFieldMappings) { + for (const mapping of customFieldMappings) { + field_mappings[mapping.slug] = stage[mapping.remote_id]; + } + } + return { + remote_id: stage.id, + stage_name: stage.new_status_label, + field_mappings, + }; + } +} diff --git a/packages/api/src/crm/stage/services/close/types.ts b/packages/api/src/crm/stage/services/close/types.ts new file mode 100644 index 000000000..84868e02d --- /dev/null +++ b/packages/api/src/crm/stage/services/close/types.ts @@ -0,0 +1,52 @@ +export interface CloseStageInput { + email?: string; + firstname?: string; + phone?: string; + lastname?: string; + city?: string; + country?: string; + zip?: string; + state?: string; + address?: string; + mobilephone?: string; + close_owner_id?: string; + associatedcompanyid?: string; + fax?: string; + jobtitle?: string; + [key: string]: any; +} + +interface OpportunityStatusChange { + organization_id: string; + _type: string; + contact_id: string | null; + created_by: string; + created_by_name: string; + date_created: string; + date_updated: string; + lead_id: string; + new_status_id: string; + new_status_label: string; + new_status_type: string; + new_pipeline_id: string; + old_status_id: string; + old_status_label: string; + old_status_type: string; + old_pipeline_id: string; + opportunity_date_won: string; + opportunity_id: string; + opportunity_value: number; + opportunity_value_formatted: string | null; + opportunity_value_currency: string; + updated_by: string; + updated_by_name: string; + user_id: string; + user_name: string; + id: string; +} + +export type CloseStageOutput = Partial; + +export const commonStageCloseProperties = { + dealstage: '', +}; diff --git a/packages/api/src/crm/stage/stage.module.ts b/packages/api/src/crm/stage/stage.module.ts index 3105933f1..32bd79860 100644 --- a/packages/api/src/crm/stage/stage.module.ts +++ b/packages/api/src/crm/stage/stage.module.ts @@ -13,6 +13,7 @@ import { HubspotService } from './services/hubspot'; import { PipedriveService } from './services/pipedrive'; import { ZendeskService } from './services/zendesk'; import { ZohoService } from './services/zoho'; +import { CloseService } from './services/close'; @Module({ imports: [ @@ -38,6 +39,7 @@ import { ZohoService } from './services/zoho'; ZohoService, PipedriveService, HubspotService, + CloseService, ], exports: [ SyncService, diff --git a/packages/api/src/crm/stage/types/mappingsTypes.ts b/packages/api/src/crm/stage/types/mappingsTypes.ts index cf9ca7ef1..3b26a390f 100644 --- a/packages/api/src/crm/stage/types/mappingsTypes.ts +++ b/packages/api/src/crm/stage/types/mappingsTypes.ts @@ -2,11 +2,13 @@ import { HubspotStageMapper } from '../services/hubspot/mappers'; import { PipedriveStageMapper } from '../services/pipedrive/mappers'; import { ZendeskStageMapper } from '../services/zendesk/mappers'; import { ZohoStageMapper } from '../services/zoho/mappers'; +import { CloseStageMapper } from '../services/close/mappers'; const hubspotStageMapper = new HubspotStageMapper(); const zendeskStageMapper = new ZendeskStageMapper(); const zohoStageMapper = new ZohoStageMapper(); const pipedriveStageMapper = new PipedriveStageMapper(); +const closeStageMapper = new CloseStageMapper(); export const stageUnificationMapping = { hubspot: { @@ -25,4 +27,8 @@ export const stageUnificationMapping = { unify: zendeskStageMapper.unify.bind(zendeskStageMapper), desunify: zendeskStageMapper.desunify.bind(zendeskStageMapper), }, + close: { + unify: closeStageMapper.unify.bind(closeStageMapper), + desunify: closeStageMapper.desunify.bind(closeStageMapper), + }, };