Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: big update custom fields #101

Merged
merged 1 commit into from
Nov 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,4 @@ export class MapFieldToProviderDto {
source_custom_field_id: string;
source_provider: string;
linked_user_id: string;
data: any;
}
16 changes: 13 additions & 3 deletions packages/api/src/@core/field-mapping/field-mapping.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import {
} from './dto/create-custom-field.dto';
import { StandardObject } from '../utils/types';

interface StandardObjectDto {
standardObjectName: string;
}
@Controller('field-mapping')
export class FieldMappingController {
constructor(
Expand All @@ -17,17 +20,24 @@ export class FieldMappingController {
}

@Post('addObjectEntity')
addStandardObjectEntity(@Body() standardObjectName: string) {
return this.fieldMappingService.addStandardObjectEntity(standardObjectName);
addStandardObjectEntity(@Body() dto: StandardObjectDto) {
return this.fieldMappingService.addStandardObjectEntity(
dto.standardObjectName,
);
}

@Get('getObjectEntity')
getStandardObjectEntity(@Query() standardObjectName: string) {
getStandardObjectEntity(@Query('object') standardObjectName: string) {
return this.fieldMappingService.getEntityId(
standardObjectName as StandardObject,
);
}

@Get('entities')
getEntities() {
return this.fieldMappingService.getEntities();
}

@Get('attribute')
getAttributes() {
return this.fieldMappingService.getAttributes();
Expand Down
36 changes: 32 additions & 4 deletions packages/api/src/@core/field-mapping/field-mapping.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export class FieldMappingService {
ressource_owner_id: standardObjectName,
},
});
return entity;
}

async getAttributes() {
Expand All @@ -33,8 +34,12 @@ export class FieldMappingService {
return await this.prisma.value.findMany();
}

async getEntities() {
return await this.prisma.entity.findMany();
}

// and then retrieve them by their name
async getEntityId(standardObject: StandardObject): Promise<string> {
async getEntityId(standardObject: StandardObject) {
const res = await this.prisma.entity.findFirst({
where: {
ressource_owner_id: standardObject as string,
Expand All @@ -43,9 +48,30 @@ export class FieldMappingService {
return res.id_entity;
}

async getCustomFieldMappings(
integrationId: string,
linkedUserId: string,
standard_object: string,
) {
return await this.prisma.attribute.findMany({
where: {
source: integrationId,
id_consumer: linkedUserId,
entity: {
ressource_owner_id: standard_object,
},
},
select: {
remote_id: true,
slug: true,
},
});
}

async defineTargetField(dto: DefineTargetFieldDto) {
// Create a new attribute in your system representing the target field
const id_entity = await this.getEntityId(dto.object_type_owner);
this.logger.log('id entity is ' + id_entity);
const attribute = await this.prisma.attribute.create({
data: {
id_attribute: uuidv4(),
Expand All @@ -59,7 +85,7 @@ export class FieldMappingService {
source: '',
id_entity: id_entity,
scope: 'user', // [user | org] wide
id_consumer: '',
id_consumer: '00000000-0000-0000-0000-000000000000', //default
},
});

Expand All @@ -80,9 +106,11 @@ export class FieldMappingService {
},
});

return updatedAttribute;

//insert inside the table value

const valueInserted = await this.prisma.value.create({
/*const valueInserted = await this.prisma.value.create({
data: {
id_value: uuidv4(),
data: dto.data,
Expand All @@ -91,6 +119,6 @@ export class FieldMappingService {
},
});

return updatedAttribute;
return updatedAttribute;*/
}
}
24 changes: 22 additions & 2 deletions packages/api/src/@core/utils/unification/crm/hubspot/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,21 @@ import { UnifiedContactInput } from '@contact/types/model.unified';
export async function desunifyHubspot<T extends Unified>({
sourceObject,
targetType_,
customFieldMappings,
}: {
sourceObject: T;
targetType_: CrmObject;
customFieldMappings?: {
slug: string;
remote_id: string;
}[];
}): Promise<CrmObjectInput> {
switch (targetType_) {
case CrmObject.contact:
return mapToHubspotContact(sourceObject as UnifiedContactInput);
return mapToHubspotContact(
sourceObject as UnifiedContactInput,
customFieldMappings,
);
case CrmObject.deal:
//return mapToHubspotDeal(sourceObject);
case CrmObject.company:
Expand All @@ -24,11 +32,23 @@ export async function desunifyHubspot<T extends Unified>({
}
export async function unifyHubspot<
T extends UnifySourceType | UnifySourceType[],
>({ sourceObject, targetType_ }: { sourceObject: T; targetType_: CrmObject }) {
>({
sourceObject,
targetType_,
customFieldMappings,
}: {
sourceObject: T;
targetType_: CrmObject;
customFieldMappings?: {
slug: string;
remote_id: string;
}[];
}) {
switch (targetType_) {
case CrmObject.contact:
return mapToUnifiedContact(
sourceObject as HubspotContactOutput | HubspotContactOutput[],
customFieldMappings,
);
case CrmObject.deal:
//return mapToHubspotDeal(sourceObject);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,66 @@ import {

export function mapToHubspotContact(
source: UnifiedContactInput,
customFieldMappings?: {
slug: string;
remote_id: string;
}[],
): HubspotContactInput {
// Assuming 'email_addresses' array contains at least one email and 'phone_numbers' array contains at least one phone number
const primaryEmail = source.email_addresses?.[0]?.email_address;
const primaryPhone = source.phone_numbers?.[0]?.phone_number;

return {
const result: HubspotContactInput = {
firstname: source.first_name,
lastname: source.last_name,
email: primaryEmail,
phone: primaryPhone,
};

if (customFieldMappings && source.field_mappings) {
for (const fieldMapping of source.field_mappings) {
for (const key in fieldMapping) {
const mapping = customFieldMappings.find(
(mapping) => mapping.slug === key,
);
if (mapping) {
result[mapping.remote_id] = fieldMapping[key];
}
}
}
}
return result;
}

export function mapToUnifiedContact(
source: HubspotContactOutput | HubspotContactOutput[],
customFieldMappings?: {
slug: string;
remote_id: string;
}[],
): UnifiedContactOutput | UnifiedContactOutput[] {
if (!Array.isArray(source)) {
return _mapSingleContact(source);
}

console.log('hhddhdhdhdh');
console.log(JSON.stringify(customFieldMappings));
// Handling array of HubspotContactOutput
return source.map(_mapSingleContact);
return source.map((contact) =>
_mapSingleContact(contact, customFieldMappings),
);
}

function _mapSingleContact(
contact: HubspotContactOutput,
customFieldMappings?: {
slug: string;
remote_id: string;
}[],
): UnifiedContactOutput {
//TODO: check for field mappings
const field_mappings = customFieldMappings.map((mapping) => ({
[mapping.slug]: contact.properties[mapping.remote_id],
}));
return {
first_name: contact.properties.firstname,
last_name: contact.properties.lastname,
Expand All @@ -45,5 +78,6 @@ function _mapSingleContact(
phone_numbers: [
{ phone_number: '' /*contact.properties.*/, phone_type: 'primary' },
],
field_mappings: field_mappings,
};
}
18 changes: 16 additions & 2 deletions packages/api/src/@core/utils/unification/crm/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,23 @@ export async function desunifyCrm<T extends Unified>({
sourceObject,
targetType_,
providerName,
customFieldMappings,
}: {
sourceObject: T;
targetType_: CrmObject;
providerName: string;
customFieldMappings?: {
slug: string;
remote_id: string;
}[];
}): Promise<CrmObjectInput> {
switch (providerName) {
case 'hubspot':
return desunifyHubspot({ sourceObject, targetType_ });
return desunifyHubspot({
sourceObject,
targetType_,
customFieldMappings,
});
case 'pipedrive':
return desunifyPipedrive({ sourceObject, targetType_ });
case 'zoho':
Expand All @@ -39,14 +48,19 @@ export async function unifyCrm<T extends UnifySourceType | UnifySourceType[]>({
sourceObject,
targetType_,
providerName,
customFieldMappings,
}: {
sourceObject: T;
targetType_: CrmObject;
providerName: string;
customFieldMappings?: {
slug: string;
remote_id: string;
}[];
}): Promise<UnifyReturnType> {
switch (providerName) {
case 'hubspot':
return unifyHubspot({ sourceObject, targetType_ });
return unifyHubspot({ sourceObject, targetType_, customFieldMappings });
case 'pipedrive':
return unifyPipedrive({ sourceObject, targetType_ });
case 'zoho':
Expand Down
12 changes: 11 additions & 1 deletion packages/api/src/@core/utils/unification/desunify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,25 @@ export async function desunify<T extends Unified>({
sourceObject,
targetType,
providerName,
customFieldMappings,
}: {
sourceObject: T;
targetType: TargetObject;
providerName: string;
customFieldMappings?: {
slug: string;
remote_id: string;
}[];
}): Promise<DesunifyReturnType> {
switch (getProviderVertical(providerName)) {
case ProviderVertical.CRM:
const targetType_ = targetType as CrmObject;
return desunifyCrm({ sourceObject, targetType_, providerName });
return desunifyCrm({
sourceObject,
targetType_,
providerName,
customFieldMappings,
});
case ProviderVertical.ATS:
break;
case ProviderVertical.Accounting:
Expand Down
12 changes: 11 additions & 1 deletion packages/api/src/@core/utils/unification/unify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,26 @@ export async function unify<T extends UnifySourceType | UnifySourceType[]>({
sourceObject,
targetType,
providerName,
customFieldMappings,
}: {
sourceObject: T;
targetType: TargetObject;
providerName: string;
customFieldMappings: {
slug: string;
remote_id: string;
}[];
}): Promise<UnifyReturnType> {
if (sourceObject == null) return [];
switch (getProviderVertical(providerName)) {
case ProviderVertical.CRM:
const targetType_ = targetType as CrmObject;
return unifyCrm({ sourceObject, targetType_, providerName });
return unifyCrm({
sourceObject,
targetType_,
providerName,
customFieldMappings,
});
case ProviderVertical.ATS:
break;
case ProviderVertical.Accounting:
Expand Down
5 changes: 5 additions & 0 deletions packages/api/src/crm/contact/contact.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ export class ContactController {
this.logger.setContext(ContactController.name);
}

@Get('properties')
getCustomProperties(@Query('linkedUserId') linkedUserId: string) {
return this.contactService.getCustomProperties(linkedUserId);
}

@Get()
getContacts(
@Query('integrationId') integrationId: string,
Expand Down
2 changes: 2 additions & 0 deletions packages/api/src/crm/contact/contact.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ZohoService } from './services/zoho';
import { PipedriveService } from './services/pipedrive';
import { HubspotService } from './services/hubspot';
import { LoggerService } from '@@core/logger/logger.service';
import { FieldMappingService } from '@@core/field-mapping/field-mapping.service';

@Module({
controllers: [ContactController],
Expand All @@ -20,6 +21,7 @@ import { LoggerService } from '@@core/logger/logger.service';
PipedriveService,
HubspotService,
LoggerService,
FieldMappingService,
],
})
export class ContactModule {}
Loading
Loading