diff --git a/packages/backend/src/apps/pipedrive/actions/create-deal/index.ts b/packages/backend/src/apps/pipedrive/actions/create-deal/index.ts new file mode 100644 index 00000000..958ca0a5 --- /dev/null +++ b/packages/backend/src/apps/pipedrive/actions/create-deal/index.ts @@ -0,0 +1,245 @@ +import defineAction from '../../../../helpers/define-action'; + +function filterProvidedFields(body: Record) { + return Object.keys(body).reduce>((result, key) => { + if (body[key]) { + result[key] = body[key]; + } + return result; + }, {}); +} + +export default defineAction({ + name: 'Create deal', + key: 'createDeal', + description: 'Creates a new deal.', + arguments: [ + { + label: 'Title', + key: 'title', + type: 'string' as const, + required: true, + description: '', + variables: true, + }, + { + label: 'Creation Date', + key: 'addTime', + type: 'string' as const, + required: false, + description: + 'Requires admin access to Pipedrive account. Format: YYYY-MM-DD HH:MM:SS', + variables: true, + }, + { + label: 'Status', + key: 'status', + type: 'dropdown' as const, + required: false, + description: '', + options: [ + { + label: 'Open', + value: 'open', + }, + { + label: 'Won', + value: 'won', + }, + { + label: 'Lost', + value: 'lost', + }, + { + label: 'Deleted', + value: 'deleted', + }, + ], + }, + { + label: 'Lost Reason', + key: 'lostReason', + type: 'string' as const, + required: false, + description: '', + variables: true, + }, + { + label: 'Stage', + key: 'stageId', + type: 'dropdown' as const, + required: false, + value: '1', + description: + 'The ID of the stage this deal will be added to. If omitted, the deal will be placed in the first stage of the default pipeline.', + options: [ + { + label: 'Qualified (Pipeline)', + value: 1, + }, + { + label: 'Contact Made (Pipeline)', + value: 2, + }, + { + label: 'Prospect Qualified (Pipeline)', + value: 3, + }, + { + label: 'Needs Defined (Pipeline)', + value: 4, + }, + { + label: 'Proposal Made (Pipeline)', + value: 5, + }, + { + label: 'Negotiations Started (Pipeline)', + value: 6, + }, + ], + }, + { + label: 'Owner', + key: 'userId', + type: 'dropdown' as const, + required: false, + description: + 'Select user who will be marked as the owner of this deal. If omitted, the authorized user will be used.', + variables: true, + source: { + type: 'query', + name: 'getDynamicData', + arguments: [ + { + name: 'key', + value: 'listUsers', + }, + ], + }, + }, + { + label: 'Organization', + key: 'organizationId', + type: 'dropdown' as const, + required: false, + description: 'Organization this deal will be associated with.', + variables: true, + source: { + type: 'query', + name: 'getDynamicData', + arguments: [ + { + name: 'key', + value: 'listOrganizations', + }, + ], + }, + }, + { + label: 'Person', + key: 'personId', + type: 'dropdown' as const, + required: false, + description: 'Person this deal will be associated with.', + variables: true, + source: { + type: 'query', + name: 'getDynamicData', + arguments: [ + { + name: 'key', + value: 'listPersons', + }, + ], + }, + }, + { + label: 'Probability', + key: 'probability', + type: 'string' as const, + required: false, + description: + 'The success probability percentage of the deal. Used/shown only when deal_probability for the pipeline of the deal is enabled.', + variables: true, + }, + { + label: 'Expected Close Date', + key: 'expectedCloseDate', + type: 'string' as const, + required: false, + description: + 'The expected close date of the deal. In ISO 8601 format: YYYY-MM-DD.', + variables: true, + }, + { + label: 'Value', + key: 'value', + type: 'string' as const, + required: false, + description: 'The value of the deal. If omitted, value will be set to 0.', + variables: true, + }, + { + label: 'Currency', + key: 'currency', + type: 'dropdown' as const, + required: false, + description: + 'The currency of the deal. Accepts a 3-character currency code. If omitted, currency will be set to the default currency of the authorized user.', + variables: true, + source: { + type: 'query', + name: 'getDynamicData', + arguments: [ + { + name: 'key', + value: 'listCurrencies', + }, + ], + }, + }, + ], + + async run($) { + const { + title, + addTime, + status, + lostReason, + stageId, + userId, + organizationId, + personId, + probability, + expectedCloseDate, + value, + currency, + } = $.step.parameters; + + const fields = { + title: title as string, + value: value as string, + add_time: addTime as string, + status: status as string, + lost_reason: lostReason as string, + stage_id: stageId as number, + user_id: userId as number, + org_id: organizationId as number, + person_id: personId as number, + probability: probability as number, + expected_close_date: expectedCloseDate as string, + currency: currency as string, + }; + + const body = filterProvidedFields(fields); + + const { + data: { data }, + } = await $.http.post(`${$.auth.data.apiDomain}/api/v1/deals`, body); + + $.setActionItem({ + raw: data, + }); + }, +}); diff --git a/packages/backend/src/apps/pipedrive/actions/index.ts b/packages/backend/src/apps/pipedrive/actions/index.ts new file mode 100644 index 00000000..04bb1d37 --- /dev/null +++ b/packages/backend/src/apps/pipedrive/actions/index.ts @@ -0,0 +1,3 @@ +import createDeal from './create-deal'; + +export default [createDeal]; diff --git a/packages/backend/src/apps/pipedrive/dynamic-data/index.ts b/packages/backend/src/apps/pipedrive/dynamic-data/index.ts new file mode 100644 index 00000000..78a520fe --- /dev/null +++ b/packages/backend/src/apps/pipedrive/dynamic-data/index.ts @@ -0,0 +1,6 @@ +import listCurrencies from './list-currencies'; +import listOrganizations from './list-organizations'; +import listPersons from './list-persons'; +import listUsers from './list-users'; + +export default [listCurrencies, listOrganizations, listPersons, listUsers]; diff --git a/packages/backend/src/apps/pipedrive/dynamic-data/list-currencies/index.ts b/packages/backend/src/apps/pipedrive/dynamic-data/list-currencies/index.ts new file mode 100644 index 00000000..f18b9c39 --- /dev/null +++ b/packages/backend/src/apps/pipedrive/dynamic-data/list-currencies/index.ts @@ -0,0 +1,29 @@ +import { IGlobalVariable, IJSONObject } from '@automatisch/types'; + +export default { + name: 'List currencies', + key: 'listCurrencies', + + async run($: IGlobalVariable) { + const currencies: { + data: IJSONObject[]; + } = { + data: [], + }; + + const { data } = await $.http.get( + `${$.auth.data.apiDomain}/api/v1/currencies` + ); + + if (data.data.length) { + for (const currency of data.data) { + currencies.data.push({ + value: currency.code, + name: currency.name, + }); + } + } + + return currencies; + }, +}; diff --git a/packages/backend/src/apps/pipedrive/dynamic-data/list-organizations/index.ts b/packages/backend/src/apps/pipedrive/dynamic-data/list-organizations/index.ts new file mode 100644 index 00000000..789b998f --- /dev/null +++ b/packages/backend/src/apps/pipedrive/dynamic-data/list-organizations/index.ts @@ -0,0 +1,33 @@ +import { IGlobalVariable, IJSONObject } from '@automatisch/types'; + +export default { + name: 'List organizations', + key: 'listOrganizations', + + async run($: IGlobalVariable) { + const organizations: { + data: IJSONObject[]; + } = { + data: [], + }; + + const { data } = await $.http.get( + `${$.auth.data.apiDomain}/api/v1/organizations` + ); + + if (!data?.data) { + return { data: [] }; + } + + if (data.data.length) { + for (const organization of data.data) { + organizations.data.push({ + value: organization.id, + name: organization.name, + }); + } + } + + return organizations; + }, +}; diff --git a/packages/backend/src/apps/pipedrive/dynamic-data/list-persons/index.ts b/packages/backend/src/apps/pipedrive/dynamic-data/list-persons/index.ts new file mode 100644 index 00000000..a1d08da9 --- /dev/null +++ b/packages/backend/src/apps/pipedrive/dynamic-data/list-persons/index.ts @@ -0,0 +1,37 @@ +import { IGlobalVariable, IJSONObject } from '@automatisch/types'; + +export default { + name: 'List persons', + key: 'listPersons', + + async run($: IGlobalVariable) { + const persons: { + data: IJSONObject[]; + } = { + data: [], + }; + + const params = { + start: 0, + limit: 100, + }; + + do { + const { data } = await $.http.get( + `${$.auth.data.apiDomain}/api/v1/persons`, + { params } + ); + params.start = data.additional_data?.pagination?.next_start; + + if (data.data.length) { + for (const person of data.data) { + persons.data.push({ + value: person.id, + name: person.name, + }); + } + } + } while (params.start); + return persons; + }, +}; diff --git a/packages/backend/src/apps/pipedrive/dynamic-data/list-users/index.ts b/packages/backend/src/apps/pipedrive/dynamic-data/list-users/index.ts new file mode 100644 index 00000000..1b39d650 --- /dev/null +++ b/packages/backend/src/apps/pipedrive/dynamic-data/list-users/index.ts @@ -0,0 +1,27 @@ +import { IGlobalVariable, IJSONObject } from '@automatisch/types'; + +export default { + name: 'List users', + key: 'listUsers', + + async run($: IGlobalVariable) { + const users: { + data: IJSONObject[]; + } = { + data: [], + }; + + const { data } = await $.http.get(`${$.auth.data.apiDomain}/api/v1/users`); + + if (data.data.length) { + for (const user of data.data) { + users.data.push({ + value: user.id, + name: user.name, + }); + } + } + + return users; + }, +}; diff --git a/packages/backend/src/apps/pipedrive/index.ts b/packages/backend/src/apps/pipedrive/index.ts index 3e01bfa7..538cd7a8 100644 --- a/packages/backend/src/apps/pipedrive/index.ts +++ b/packages/backend/src/apps/pipedrive/index.ts @@ -2,6 +2,8 @@ import defineApp from '../../helpers/define-app'; import addAuthHeader from './common/add-auth-header'; import auth from './auth'; import triggers from './triggers'; +import actions from './actions'; +import dynamicData from './dynamic-data'; export default defineApp({ name: 'Pipedrive', @@ -15,4 +17,6 @@ export default defineApp({ beforeRequest: [addAuthHeader], auth, triggers, + actions, + dynamicData, }); diff --git a/packages/docs/pages/.vitepress/config.js b/packages/docs/pages/.vitepress/config.js index df3daac3..1e1c0c60 100644 --- a/packages/docs/pages/.vitepress/config.js +++ b/packages/docs/pages/.vitepress/config.js @@ -230,6 +230,7 @@ export default defineConfig({ collapsed: true, items: [ { text: 'Triggers', link: '/apps/pipedrive/triggers' }, + { text: 'Actions', link: '/apps/pipedrive/actions' }, { text: 'Connection', link: '/apps/pipedrive/connection' }, ], }, diff --git a/packages/docs/pages/apps/pipedrive/actions.md b/packages/docs/pages/apps/pipedrive/actions.md new file mode 100644 index 00000000..1a135b02 --- /dev/null +++ b/packages/docs/pages/apps/pipedrive/actions.md @@ -0,0 +1,12 @@ +--- +favicon: /favicons/pipedrive.svg +items: + - name: Create deal + desc: Creates a new deal. +--- + + + +