Skip to content

Commit

Permalink
Merge pull request #679 from mit-27/add-microsoft-dynamics-365-sales-crm
Browse files Browse the repository at this point in the history
Feat: Add integration with Microsoft Dynamics 365 Sales (CRM)
  • Loading branch information
naelob authored Sep 3, 2024
2 parents 1886b8f + 8732445 commit e8c1bd4
Show file tree
Hide file tree
Showing 35 changed files with 3,636 additions and 24 deletions.
2 changes: 1 addition & 1 deletion apps/magic-link/src/lib/ProviderModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ interface IBasicAuthFormData {
}

const domainFormats: { [key: string]: string } = {
microsoftdynamicssales: 'YOURORGNAME.api.crm12.dynamics.com',
microsoftdynamicssales: 'YOURORGNAME.api.crm3.dynamics.com',
bigcommerce: 'If your api domain is https://api.bigcommerce.com/stores/eubckcvkzg/v3 then store_hash is eubckcvkzg',
};

Expand Down
3 changes: 2 additions & 1 deletion packages/api/scripts/init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,8 @@ CREATE TABLE connector_sets
ecom_amazon boolean NULL,
ecom_squarespace boolean NULL,
ats_ashby boolean NULL,
CONSTRAINT PK_project_connector PRIMARY KEY ( id_connector_set )
crm_microsoftdynamicssales boolean NULL,
CONSTRAINT PK_project_connector PRIMARY KEY ( id_connector_set )
);


Expand Down
8 changes: 4 additions & 4 deletions packages/api/scripts/seed.sql
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
INSERT INTO users (id_user, identification_strategy, email, password_hash, first_name, last_name) VALUES
('0ce39030-2901-4c56-8db0-5e326182ec6b', 'b2c','local@panora.dev', '$2b$10$Y7Q8TWGyGuc5ecdIASbBsuXMo3q/Rs3/cnY.mLZP4tUgfGUOCUBlG', 'local', 'Panora');

INSERT INTO connector_sets (id_connector_set, crm_hubspot, crm_zoho, crm_pipedrive, crm_attio, crm_zendesk, crm_close, tcg_zendesk, tcg_gorgias, tcg_front, tcg_jira, tcg_gitlab, fs_box, tcg_github, hris_deel, hris_sage, ats_ashby) VALUES
('1709da40-17f7-4d3a-93a0-96dc5da6ddd7', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
('852dfff8-ab63-4530-ae49-e4b2924407f8', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
('aed0f856-f802-4a79-8640-66d441581a99', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
INSERT INTO connector_sets (id_connector_set, crm_hubspot, crm_zoho, crm_pipedrive, crm_attio, crm_zendesk, crm_close, tcg_zendesk, tcg_gorgias, tcg_front, tcg_jira, tcg_gitlab, fs_box, tcg_github, hris_deel, hris_sage, ats_ashby, crm_microsoftdynamicssales) VALUES
('1709da40-17f7-4d3a-93a0-96dc5da6ddd7', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
('852dfff8-ab63-4530-ae49-e4b2924407f8', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
('aed0f856-f802-4a79-8640-66d441581a99', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);

INSERT INTO projects (id_project, name, sync_mode, id_user, id_connector_set) VALUES
('1e468c15-aa57-4448-aa2b-7fed640d1e3d', 'Project 1', 'pull', '0ce39030-2901-4c56-8db0-5e326182ec6b', '1709da40-17f7-4d3a-93a0-96dc5da6ddd7'),
Expand Down
42 changes: 28 additions & 14 deletions packages/api/src/@core/utils/types/original/original.crm.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
import { MicrosoftdynamicssalesEngagementInput, MicrosoftdynamicssalesEngagementOutput } from '@crm/engagement/services/microsoftdynamicssales/types';

import { MicrosoftdynamicssalesTaskInput, MicrosoftdynamicssalesTaskOutput } from '@crm/task/services/microsoftdynamicssales/types';

import { MicrosoftdynamicssalesNoteInput, MicrosoftdynamicssalesNoteOutput } from '@crm/note/services/microsoftdynamicssales/types';

import { MicrosoftdynamicssalesDealInput, MicrosoftdynamicssalesDealOutput } from '@crm/deal/services/microsoftdynamicssales/types';

import { MicrosoftdynamicssalesContactInput, MicrosoftdynamicssalesContactOutput } from '@crm/contact/services/microsoftdynamicssales/types';

import { MicrosoftdynamicssalesCompanyInput, MicrosoftdynamicssalesCompanyOutput } from '@crm/company/services/microsoftdynamicssales/types';

import { MicrosoftdynamicssalesUserInput, MicrosoftdynamicssalesUserOutput } from '@crm/user/services/microsoftdynamicssales/types';

import { AttioCompanyOutput } from '@crm/company/services/attio/types';
import { HubspotCompanyOutput } from '@crm/company/services/hubspot/types';
import { PipedriveCompanyOutput } from '@crm/company/services/pipedrive/types';
Expand Down Expand Up @@ -148,7 +162,7 @@ export type OriginalContactInput =
| ZendeskContactInput
| PipedriveContactInput
| AttioContactInput
| CloseContactInput;
| CloseContactInput | MicrosoftdynamicssalesContactInput;

/* deal */
export type OriginalDealInput =
Expand All @@ -157,7 +171,7 @@ export type OriginalDealInput =
| ZendeskDealOutput
| PipedriveDealOutput
| CloseDealOutput
| AttioDealInput;
| AttioDealInput | MicrosoftdynamicssalesDealInput;

/* company */
export type OriginalCompanyInput =
Expand All @@ -166,15 +180,15 @@ export type OriginalCompanyInput =
| ZendeskCompanyOutput
| PipedriveCompanyOutput
| AttioCompanyOutput
| CloseCompanyOutput;
| CloseCompanyOutput | MicrosoftdynamicssalesCompanyInput;

/* engagement */
export type OriginalEngagementInput =
| HubspotEngagementInput
| ZohoEngagementInput
| ZendeskEngagementInput
| PipedriveEngagementInput
| CloseEngagementInput;
| CloseEngagementInput | MicrosoftdynamicssalesEngagementInput;

/* note */
export type OriginalNoteInput =
Expand All @@ -183,7 +197,7 @@ export type OriginalNoteInput =
| ZendeskNoteInput
| PipedriveNoteInput
| CloseNoteInput
| AttioNoteInput;
| AttioNoteInput | MicrosoftdynamicssalesNoteInput;

/* task */
export type OriginalTaskInput =
Expand All @@ -192,7 +206,7 @@ export type OriginalTaskInput =
| ZendeskTaskInput
| PipedriveTaskInput
| CloseTaskInput
| AttioTaskInput;
| AttioTaskInput | MicrosoftdynamicssalesTaskInput;

/* stage */
export type OriginalStageInput =
Expand All @@ -210,7 +224,7 @@ export type OriginalUserInput =
| ZohoUserInput
| ZendeskUserInput
| PipedriveUserInput
| CloseUserOutput;
| CloseUserOutput | MicrosoftdynamicssalesUserInput;

export type CrmObjectInput =
| OriginalContactInput
Expand All @@ -230,7 +244,7 @@ export type OriginalContactOutput =
| ZendeskContactOutput
| PipedriveContactOutput
| AttioContactOutput
| CloseContactOutput;
| CloseContactOutput | MicrosoftdynamicssalesContactOutput;

/* deal */
export type OriginalDealOutput =
Expand All @@ -239,7 +253,7 @@ export type OriginalDealOutput =
| ZendeskDealOutput
| PipedriveDealOutput
| CloseDealOutput
| AttioDealOutput;
| AttioDealOutput | MicrosoftdynamicssalesDealOutput;

/* company */
export type OriginalCompanyOutput =
Expand All @@ -248,15 +262,15 @@ export type OriginalCompanyOutput =
| ZendeskCompanyOutput
| PipedriveCompanyOutput
| AttioCompanyOutput
| CloseCompanyOutput;
| CloseCompanyOutput | MicrosoftdynamicssalesCompanyOutput;

/* engagement */
export type OriginalEngagementOutput =
| HubspotEngagementOutput
| ZohoEngagementOutput
| ZendeskEngagementOutput
| PipedriveEngagementOutput
| CloseEngagementOutput;
| CloseEngagementOutput | MicrosoftdynamicssalesEngagementOutput;

/* note */
export type OriginalNoteOutput =
Expand All @@ -265,7 +279,7 @@ export type OriginalNoteOutput =
| ZendeskNoteOutput
| PipedriveNoteOutput
| CloseNoteOutput
| AttioNoteOutput;
| AttioNoteOutput | MicrosoftdynamicssalesNoteOutput;

/* task */
export type OriginalTaskOutput =
Expand All @@ -274,7 +288,7 @@ export type OriginalTaskOutput =
| ZendeskTaskOutput
| PipedriveTaskOutput
| CloseTaskOutput
| AttioTaskOutput;
| AttioTaskOutput | MicrosoftdynamicssalesTaskOutput;

/* stage */
export type OriginalStageOutput =
Expand All @@ -293,7 +307,7 @@ export type OriginalUserOutput =
| ZendeskUserOutput
| PipedriveUserOutput
| CloseUserInput
| AttioUserOutput;
| AttioUserOutput | MicrosoftdynamicssalesUserOutput;

export type CrmObjectOutput =
| OriginalContactOutput
Expand Down
4 changes: 4 additions & 0 deletions packages/api/src/crm/company/company.module.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { MicrosoftdynamicssalesCompanyMapper } from './services/microsoftdynamicssales/mappers';
import { MicrosoftdynamicssalesService } from './services/microsoftdynamicssales';
import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
import { LoggerService } from '@@core/@core-services/logger/logger.service';
import { BullQueueModule } from '@@core/@core-services/queues/queue.module';
Expand Down Expand Up @@ -52,6 +54,8 @@ import { SyncService } from './sync/sync.service';
PipedriveCompanyMapper,
ZendeskCompanyMapper,
ZohoCompanyMapper,
MicrosoftdynamicssalesService,
MicrosoftdynamicssalesCompanyMapper,
],
exports: [SyncService, ServiceRegistry, WebhookService],
})
Expand Down
111 changes: 111 additions & 0 deletions packages/api/src/crm/company/services/microsoftdynamicssales/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { Injectable } from '@nestjs/common';
import axios from 'axios';
import { CrmObject } from '@crm/@lib/@types';
import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
import { LoggerService } from '@@core/@core-services/logger/logger.service';
import { ActionType, handle3rdPartyServiceError } from '@@core/utils/errors';
import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
import { ApiResponse } from '@@core/utils/types';
import { ICompanyService } from '@crm/company/types';
import { ServiceRegistry } from '../registry.service';
import { MicrosoftdynamicssalesCompanyInput, MicrosoftdynamicssalesCompanyOutput } from './types';
import { SyncParam } from '@@core/utils/types/interface';
import { OriginalCompanyOutput } from '@@core/utils/types/original/original.crm';

@Injectable()
export class MicrosoftdynamicssalesService implements ICompanyService {
constructor(
private prisma: PrismaService,
private logger: LoggerService,
private cryptoService: EncryptionService,
private registry: ServiceRegistry,
) {
this.logger.setContext(
CrmObject.company.toUpperCase() + ':' + MicrosoftdynamicssalesService.name,
);
this.registry.registerService('microsoftdynamicssales', this);
}
async addCompany(
companyData: MicrosoftdynamicssalesCompanyInput,
linkedUserId: string,
): Promise<ApiResponse<MicrosoftdynamicssalesCompanyOutput>> {
try {
const connection = await this.prisma.connections.findFirst({
where: {
id_linked_user: linkedUserId,
provider_slug: 'microsoftdynamicssales',
vertical: 'crm',
},
});

const respToPost = await axios.post(
`${connection.account_url}/api/data/v9.2/accounts`,
JSON.stringify(companyData),
{
headers: {
Authorization: `Bearer ${this.cryptoService.decrypt(
connection.access_token,
)}`,
'Content-Type': 'application/json',
},
},
);

const postCompanyId = respToPost.headers['location'].split("/").pop();
// console.log(res.headers['location'].split('(')[1].split(')')[0])

const resp = await axios.get(
`${connection.account_url}/api/data/v9.2/${postCompanyId}`,
{
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.cryptoService.decrypt(
connection.access_token,
)}`,
},
},
);

return {
data: resp.data,
message: 'Microsoftdynamicssales company created',
statusCode: 201,
};
} catch (error) {
throw error;
}
}

async sync(data: SyncParam): Promise<ApiResponse<MicrosoftdynamicssalesCompanyOutput[]>> {
try {
const { linkedUserId } = data;

const connection = await this.prisma.connections.findFirst({
where: {
id_linked_user: linkedUserId,
provider_slug: 'microsoftdynamicssales',
vertical: 'crm',
},
});
const resp = await axios.get(
`${connection.account_url}/api/data/v9.2/accounts`,
{
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${this.cryptoService.decrypt(
connection.access_token,
)}`,
},
},
);
return {
data: resp.data.value,
message: 'Microsoftdynamicssales companies retrieved',
statusCode: 200,
};
} catch (error) {
throw error;
}
}
}
Loading

0 comments on commit e8c1bd4

Please sign in to comment.