From 4e4933de9df2786f2a3706ee42e27b71b10e050b Mon Sep 17 00:00:00 2001 From: tommaso1 Date: Thu, 19 Dec 2024 14:56:13 +0100 Subject: [PATCH] [DEV-1614] Add bulk import of contacts (#1273) * sync user wip * sync user * changeset * Update .changeset/cuddly-cats-retire.md Co-authored-by: Marco Ponchia * Update packages/active-campaign-client/src/index.ts Co-authored-by: Marco Ponchia * Update packages/active-campaign-client/src/index.ts Co-authored-by: Marco Ponchia * Update packages/active-campaign-client/src/helpers/resyncUser.ts Co-authored-by: Marco Ponchia * pr comments * bulk add contact * bulk add contact * resync user * changeset * Update packages/active-campaign-client/src/clients/activeCampaignClient.ts Co-authored-by: Marco Ponchia * Update packages/active-campaign-client/src/handlers/resyncUserHandler.ts Co-authored-by: Marco Ponchia * pr changes * Update packages/active-campaign-client/src/helpers/fetchSubscribedWebinarsFromDynamo.ts Co-authored-by: Marco Ponchia * Update packages/active-campaign-client/.env.example Co-authored-by: marcobottaro <39835990+marcobottaro@users.noreply.github.com> * Update packages/active-campaign-client/src/handlers/resyncUserHandler.ts Co-authored-by: Marco Ponchia * pr changes --------- Co-authored-by: t Co-authored-by: Marco Ponchia Co-authored-by: marcobottaro <39835990+marcobottaro@users.noreply.github.com> --- .changeset/loud-otters-unite.md | 5 ++ packages/active-campaign-client/.env.example | 1 + .../helpers/bulkAddContactToList.test.ts | 22 ++++++++ .../src/clients/activeCampaignClient.ts | 30 ++++++++++- .../src/helpers/bulkAddContactsToLists.ts | 52 +++++++++++++++++++ .../fetchSubscribedWebinarsFromDynamo.ts | 29 +++++++++++ .../src/types/bulkAddContactPayload.ts | 11 ++++ 7 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 .changeset/loud-otters-unite.md create mode 100644 packages/active-campaign-client/src/__tests__/helpers/bulkAddContactToList.test.ts create mode 100644 packages/active-campaign-client/src/helpers/bulkAddContactsToLists.ts create mode 100644 packages/active-campaign-client/src/helpers/fetchSubscribedWebinarsFromDynamo.ts create mode 100644 packages/active-campaign-client/src/types/bulkAddContactPayload.ts diff --git a/.changeset/loud-otters-unite.md b/.changeset/loud-otters-unite.md new file mode 100644 index 000000000..6b7b9d4d7 --- /dev/null +++ b/.changeset/loud-otters-unite.md @@ -0,0 +1,5 @@ +--- +"active-campaign-client": patch +--- + +Add bulk import of contacts diff --git a/packages/active-campaign-client/.env.example b/packages/active-campaign-client/.env.example index c9ffddf5e..3def88bca 100644 --- a/packages/active-campaign-client/.env.example +++ b/packages/active-campaign-client/.env.example @@ -7,3 +7,4 @@ COGNITO_USER_ID=66ae52a0-f051-7080-04a1-465b3a4f44cc LIST_NAME=test-webinar-1732097286071 AC_BASE_URL_PARAM='/ac/base_url' AC_API_KEY_PARAM='/ac/api_key' +TEST_AC_LIST_ID=28 diff --git a/packages/active-campaign-client/src/__tests__/helpers/bulkAddContactToList.test.ts b/packages/active-campaign-client/src/__tests__/helpers/bulkAddContactToList.test.ts new file mode 100644 index 000000000..18d5dc373 --- /dev/null +++ b/packages/active-campaign-client/src/__tests__/helpers/bulkAddContactToList.test.ts @@ -0,0 +1,22 @@ +import { bulkAddContactToList } from '../../helpers/bulkAddContactsToLists'; +import { User } from '../../types/user'; + +const user: User = { + username: '466e0280-9061-7007-c3e0-beb6be672f68', + email: `test@example${new Date().getTime()}e.com`, + given_name: 'Giovanni', + family_name: 'Doe', + 'custom:mailinglist_accepted': 'true', + 'custom:company_type': 'Test Co', + 'custom:job_role': 'Developer', +}; + +describe.skip('Active campaign integration contact flow', () => { + it('should bulk add contacts to a list', async () => { + const response = await bulkAddContactToList( + [user], + [[Number(process.env.TEST_AC_LIST_ID)]] + ); + expect(response.statusCode).toBe(200); + }); +}); diff --git a/packages/active-campaign-client/src/clients/activeCampaignClient.ts b/packages/active-campaign-client/src/clients/activeCampaignClient.ts index 7b3c12492..e09f70bc3 100644 --- a/packages/active-campaign-client/src/clients/activeCampaignClient.ts +++ b/packages/active-campaign-client/src/clients/activeCampaignClient.ts @@ -3,6 +3,7 @@ import { SSMClient, GetParameterCommand } from '@aws-sdk/client-ssm'; import { ContactPayload } from '../types/contactPayload'; import { ListPayload } from '../types/listPayload'; import { ListStatusPayload } from '../types/listStatusPayload'; +import { BulkAddContactPayload } from '../types/bulkAddContactPayload'; async function getParameter( paramName: string, @@ -43,7 +44,11 @@ export class ActiveCampaignClient { private async makeRequest( method: string, path: string, - data?: ContactPayload | ListPayload | ListStatusPayload, + data?: + | ContactPayload + | ListPayload + | ListStatusPayload + | BulkAddContactPayload, params?: Record ): Promise { const [apiKey, baseUrl] = await Promise.all([ @@ -137,6 +142,29 @@ export class ActiveCampaignClient { return this.makeRequest('DELETE', `/api/3/lists/${id}`); } + async bulkAddContactToList( + contacts: readonly (ContactPayload & { + readonly listIds: readonly number[]; + })[] + ) { + const body = { + contacts: contacts.map((payload) => ({ + email: payload.contact.email, + first_name: payload.contact.firstName, + last_name: payload.contact.lastName, + phone: payload.contact.phone, + customer_acct_name: payload.contact.lastName, + fields: payload.contact.fieldValues.map((field) => ({ + id: Number(field.field), + value: field.value, + })), + subscribe: payload.listIds.map((listId) => ({ listid: listId })), + })), + }; + + return this.makeRequest('POST', `/api/3/import/bulk_import`, body); + } + async addContactToList(contactId: string, listId: number) { return this.makeRequest('POST', `/api/3/contactLists`, { contactList: { diff --git a/packages/active-campaign-client/src/helpers/bulkAddContactsToLists.ts b/packages/active-campaign-client/src/helpers/bulkAddContactsToLists.ts new file mode 100644 index 000000000..fe1d6e2ab --- /dev/null +++ b/packages/active-campaign-client/src/helpers/bulkAddContactsToLists.ts @@ -0,0 +1,52 @@ +import { APIGatewayProxyResult } from 'aws-lambda'; +import { acClient } from '../clients/activeCampaignClient'; +import { ContactPayload } from '../types/contactPayload'; +import { User } from '../types/user'; + +export async function bulkAddContactToList( + users: readonly User[], + listIds: readonly (readonly number[])[] +): Promise { + try { + // Transform to AC payload + const acPayload: readonly (ContactPayload & { + readonly listIds: readonly number[]; + })[] = users.map((user, index) => ({ + contact: { + email: user.email, + firstName: user.given_name, + lastName: user.family_name, + phone: `cognito:${user.username}`, + fieldValues: [ + { + field: '2', + value: user['custom:company_type'], + }, + { + field: '1', + value: user['custom:job_role'], + }, + { + field: '3', + value: + user['custom:mailinglist_accepted'] === 'true' ? 'TRUE' : 'FALSE', + }, + ], + }, + listIds: listIds[index], + })); + + const response = await acClient.bulkAddContactToList(acPayload); + + return { + statusCode: 200, + body: JSON.stringify(response), + }; + } catch (error) { + console.error('Error:', error); + return { + statusCode: 500, + body: JSON.stringify({ message: 'Internal server error' }), + }; + } +} diff --git a/packages/active-campaign-client/src/helpers/fetchSubscribedWebinarsFromDynamo.ts b/packages/active-campaign-client/src/helpers/fetchSubscribedWebinarsFromDynamo.ts new file mode 100644 index 000000000..ff17598ae --- /dev/null +++ b/packages/active-campaign-client/src/helpers/fetchSubscribedWebinarsFromDynamo.ts @@ -0,0 +1,29 @@ +import { DynamoDBClient, QueryCommand } from '@aws-sdk/client-dynamodb'; +import { APIGatewayProxyResult } from 'aws-lambda'; + +export async function fetchSubscribedWebinarsFromDynamo( + username: string +): Promise { + try { + const dynamoClient = new DynamoDBClient({ region: process.env.AWS_REGION }); + const command = new QueryCommand({ + TableName: process.env.DYNAMO_WEBINARS_TABLE_NAME, + KeyConditionExpression: 'username = :username', + ExpressionAttributeValues: { + ':username': { S: username }, + }, + }); + + const response = await dynamoClient.send(command); + console.log('getWebinarSubscriptions', response); + return { + statusCode: 200, + body: JSON.stringify(response.Items), + }; + } catch (error) { + return { + statusCode: 500, + body: JSON.stringify({ message: 'Internal server error' }), + }; + } +} diff --git a/packages/active-campaign-client/src/types/bulkAddContactPayload.ts b/packages/active-campaign-client/src/types/bulkAddContactPayload.ts new file mode 100644 index 000000000..dea49a5db --- /dev/null +++ b/packages/active-campaign-client/src/types/bulkAddContactPayload.ts @@ -0,0 +1,11 @@ +export type BulkAddContactPayload = { + readonly contacts: readonly { + readonly email: string; + readonly first_name: string; + readonly last_name: string; + readonly phone: string | undefined; + readonly customer_acct_name: string; + readonly fields: readonly { readonly id: number; readonly value: string }[]; + readonly subscribe: readonly { readonly listid: number }[]; + }[]; +};