diff --git a/packages/backend/src/apps/vtiger-crm/actions/create-opportunity/fields.js b/packages/backend/src/apps/vtiger-crm/actions/create-opportunity/fields.js new file mode 100644 index 00000000..557a62a6 --- /dev/null +++ b/packages/backend/src/apps/vtiger-crm/actions/create-opportunity/fields.js @@ -0,0 +1,244 @@ +export const fields = [ + { + label: 'Deal Name', + key: 'dealName', + type: 'string', + required: true, + description: '', + variables: true, + }, + { + label: 'Amount', + key: 'amount', + type: 'string', + required: false, + description: '', + variables: true, + }, + { + label: 'Organization Name', + key: 'organizationName', + type: 'dropdown', + required: false, + description: '', + variables: true, + source: { + type: 'query', + name: 'getDynamicData', + arguments: [ + { + name: 'key', + value: 'listOrganizations', + }, + ], + }, + }, + { + label: 'Contact Name', + key: 'contactName', + type: 'dropdown', + required: false, + description: '', + variables: true, + source: { + type: 'query', + name: 'getDynamicData', + arguments: [ + { + name: 'key', + value: 'listContacts', + }, + ], + }, + }, + { + label: 'Expected Close Date', + key: 'expectedCloseDate', + type: 'string', + required: true, + description: 'Format: yyyy-mm-dd', + variables: true, + }, + { + label: 'Pipeline', + key: 'pipeline', + type: 'dropdown', + required: true, + value: 'Standart', + description: '', + variables: true, + options: [{ label: 'Standart', value: 'Standart' }], + }, + { + label: 'Sales Stage', + key: 'salesStage', + type: 'dropdown', + required: false, + description: '', + variables: true, + source: { + type: 'query', + name: 'getDynamicData', + arguments: [ + { + name: 'key', + value: 'listOpportunityOptions', + }, + { + name: 'parameters.salesStage', + value: 'sales_stage', + }, + ], + }, + }, + { + label: 'Assigned To', + key: 'assignedTo', + type: 'string', + required: false, + description: 'Default is the id of the account connected to Automatisch.', + variables: true, + }, + { + label: 'Lead Source', + key: 'leadSource', + type: 'dropdown', + required: false, + description: '', + variables: true, + source: { + type: 'query', + name: 'getDynamicData', + arguments: [ + { + name: 'key', + value: 'listOpportunityOptions', + }, + { + name: 'parameters.leadSource', + value: 'leadsource', + }, + ], + }, + }, + { + label: 'Next Step', + key: 'nextStep', + type: 'string', + required: false, + description: '', + variables: true, + }, + { + label: 'Type', + key: 'type', + type: 'dropdown', + required: false, + description: '', + variables: true, + source: { + type: 'query', + name: 'getDynamicData', + arguments: [ + { + name: 'key', + value: 'listOpportunityOptions', + }, + { + name: 'parameters.type', + value: 'opportunity_type', + }, + ], + }, + }, + { + label: 'Probability', + key: 'probability', + type: 'string', + required: false, + description: '', + variables: true, + }, + { + label: 'Campaign Source', + key: 'campaignSource', + type: 'dropdown', + required: false, + description: '', + variables: true, + source: { + type: 'query', + name: 'getDynamicData', + arguments: [ + { + name: 'key', + value: 'listCampaignSources', + }, + ], + }, + }, + { + label: 'Weighted Revenue', + key: 'weightedRevenue', + type: 'string', + required: false, + description: '', + variables: true, + }, + { + label: 'Adjusted Amount', + key: 'adjustedAmount', + type: 'string', + required: false, + description: '', + variables: true, + }, + { + label: 'Lost Reason', + key: 'lostReason', + type: 'dropdown', + required: false, + description: '', + variables: true, + source: { + type: 'query', + name: 'getDynamicData', + arguments: [ + { + name: 'key', + value: 'listOpportunityOptions', + }, + { + name: 'parameters.lostReason', + value: 'lost_reason', + }, + ], + }, + }, + { + label: 'Record Currency', + key: 'recordCurrency', + type: 'dropdown', + required: false, + description: '', + variables: true, + source: { + type: 'query', + name: 'getDynamicData', + arguments: [ + { + name: 'key', + value: 'listRecordCurrencies', + }, + ], + }, + }, + { + label: 'Description', + key: 'description', + type: 'string', + required: false, + description: '', + variables: true, + }, +]; diff --git a/packages/backend/src/apps/vtiger-crm/actions/create-opportunity/index.js b/packages/backend/src/apps/vtiger-crm/actions/create-opportunity/index.js new file mode 100644 index 00000000..4a2e8571 --- /dev/null +++ b/packages/backend/src/apps/vtiger-crm/actions/create-opportunity/index.js @@ -0,0 +1,64 @@ +import defineAction from '../../../../helpers/define-action.js'; +import { fields } from './fields.js'; + +export default defineAction({ + name: 'Create opportunity', + key: 'createOpportunity', + description: 'Create a new opportunity.', + arguments: fields, + + async run($) { + const { + dealName, + amount, + organizationName, + contactName, + expectedCloseDate, + pipeline, + salesStage, + assignedTo, + leadSource, + nextStep, + type, + probability, + campaignSource, + weightedRevenue, + adjustedAmount, + lostReason, + recordCurrency, + description, + } = $.step.parameters; + + const elementData = { + potentialname: dealName, + amount, + related_to: organizationName, + contact_id: contactName, + closingdate: expectedCloseDate, + pipeline, + sales_stage: salesStage, + assigned_user_id: assignedTo || $.auth.data.userId, + leadsource: leadSource, + nextstep: nextStep, + opportunity_type: type, + probability: probability, + campaignid: campaignSource, + forecast_amount: weightedRevenue, + adjusted_amount: adjustedAmount, + lost_reason: lostReason, + record_currency_id: recordCurrency, + description, + }; + + const body = { + operation: 'create', + sessionName: $.auth.data.sessionName, + element: JSON.stringify(elementData), + elementType: 'Potentials', + }; + + const response = await $.http.post('/webservice.php', body); + + $.setActionItem({ raw: response.data }); + }, +}); diff --git a/packages/backend/src/apps/vtiger-crm/actions/index.js b/packages/backend/src/apps/vtiger-crm/actions/index.js new file mode 100644 index 00000000..3b7b0a62 --- /dev/null +++ b/packages/backend/src/apps/vtiger-crm/actions/index.js @@ -0,0 +1,3 @@ +import createOpportunity from './create-opportunity/index.js'; + +export default [createOpportunity]; diff --git a/packages/backend/src/apps/vtiger-crm/dynamic-data/index.js b/packages/backend/src/apps/vtiger-crm/dynamic-data/index.js new file mode 100644 index 00000000..3cdc6a58 --- /dev/null +++ b/packages/backend/src/apps/vtiger-crm/dynamic-data/index.js @@ -0,0 +1,13 @@ +import listCampaignSources from './list-campaign-sources/index.js'; +import listContacts from './list-contacts/index.js'; +import listOpportunityOptions from './list-opportunity-options/index.js'; +import listOrganizations from './list-organizations/index.js'; +import listRecordCurrencies from './list-record-currencies/index.js'; + +export default [ + listCampaignSources, + listContacts, + listOpportunityOptions, + listOrganizations, + listRecordCurrencies, +]; diff --git a/packages/backend/src/apps/vtiger-crm/dynamic-data/list-campaign-sources/index.js b/packages/backend/src/apps/vtiger-crm/dynamic-data/list-campaign-sources/index.js new file mode 100644 index 00000000..e2551278 --- /dev/null +++ b/packages/backend/src/apps/vtiger-crm/dynamic-data/list-campaign-sources/index.js @@ -0,0 +1,29 @@ +export default { + name: 'List campaign sources', + key: 'listCampaignSources', + + async run($) { + const campaignSources = { + data: [], + }; + + const params = { + operation: 'query', + sessionName: $.auth.data.sessionName, + query: 'SELECT * FROM Campaigns ORDER BY createdtime DESC;', + }; + + const { data } = await $.http.get(`/webservice.php`, { params }); + + if (data.result?.length) { + for (const campaignSource of data.result) { + campaignSources.data.push({ + value: campaignSource.id, + name: campaignSource.campaignname, + }); + } + } + + return campaignSources; + }, +}; diff --git a/packages/backend/src/apps/vtiger-crm/dynamic-data/list-contacts/index.js b/packages/backend/src/apps/vtiger-crm/dynamic-data/list-contacts/index.js new file mode 100644 index 00000000..c2d8c6ff --- /dev/null +++ b/packages/backend/src/apps/vtiger-crm/dynamic-data/list-contacts/index.js @@ -0,0 +1,29 @@ +export default { + name: 'List contacts', + key: 'listContacts', + + async run($) { + const contacts = { + data: [], + }; + + const params = { + operation: 'query', + sessionName: $.auth.data.sessionName, + query: 'SELECT * FROM Contacts ORDER BY createdtime DESC;', + }; + + const { data } = await $.http.get(`/webservice.php`, { params }); + + if (data.result?.length) { + for (const contact of data.result) { + contacts.data.push({ + value: contact.id, + name: `${contact.firstname} ${contact.lastname}`, + }); + } + } + + return contacts; + }, +}; diff --git a/packages/backend/src/apps/vtiger-crm/dynamic-data/list-opportunity-options/index.js b/packages/backend/src/apps/vtiger-crm/dynamic-data/list-opportunity-options/index.js new file mode 100644 index 00000000..b86cd731 --- /dev/null +++ b/packages/backend/src/apps/vtiger-crm/dynamic-data/list-opportunity-options/index.js @@ -0,0 +1,38 @@ +export default { + name: 'List opportunity options', + key: 'listOpportunityOptions', + + async run($) { + const opportunityOptions = { + data: [], + }; + const leadSource = $.step.parameters.leadSource; + const lostReason = $.step.parameters.lostReason; + const type = $.step.parameters.type; + const salesStage = $.step.parameters.salesStage; + const picklistFields = [leadSource, lostReason, type, salesStage]; + + const params = { + operation: 'describe', + sessionName: $.auth.data.sessionName, + elementType: 'Potentials', + }; + + const { data } = await $.http.get(`/webservice.php`, { params }); + + if (data.result.fields?.length) { + for (const field of data.result.fields) { + if (picklistFields.includes(field.name)) { + field.type.picklistValues.map((item) => + opportunityOptions.data.push({ + value: item.value, + name: item.label, + }) + ); + } + } + } + + return opportunityOptions; + }, +}; diff --git a/packages/backend/src/apps/vtiger-crm/dynamic-data/list-organizations/index.js b/packages/backend/src/apps/vtiger-crm/dynamic-data/list-organizations/index.js new file mode 100644 index 00000000..77b60302 --- /dev/null +++ b/packages/backend/src/apps/vtiger-crm/dynamic-data/list-organizations/index.js @@ -0,0 +1,29 @@ +export default { + name: 'List organizations', + key: 'listOrganizations', + + async run($) { + const organizations = { + data: [], + }; + + const params = { + operation: 'query', + sessionName: $.auth.data.sessionName, + query: 'SELECT * FROM Accounts ORDER BY createdtime DESC;', + }; + + const { data } = await $.http.get(`/webservice.php`, { params }); + + if (data.result?.length) { + for (const organization of data.result) { + organizations.data.push({ + value: organization.id, + name: organization.accountname, + }); + } + } + + return organizations; + }, +}; diff --git a/packages/backend/src/apps/vtiger-crm/dynamic-data/list-record-currencies/index.js b/packages/backend/src/apps/vtiger-crm/dynamic-data/list-record-currencies/index.js new file mode 100644 index 00000000..b416a650 --- /dev/null +++ b/packages/backend/src/apps/vtiger-crm/dynamic-data/list-record-currencies/index.js @@ -0,0 +1,29 @@ +export default { + name: 'List record currencies', + key: 'listRecordCurrencies', + + async run($) { + const recordCurrencies = { + data: [], + }; + + const params = { + operation: 'query', + sessionName: $.auth.data.sessionName, + query: 'SELECT * FROM Currency;', + }; + + const { data } = await $.http.get(`/webservice.php`, { params }); + + if (data.result?.length) { + for (const recordCurrency of data.result) { + recordCurrencies.data.push({ + value: recordCurrency.id, + name: recordCurrency.currency_code, + }); + } + } + + return recordCurrencies; + }, +}; diff --git a/packages/backend/src/apps/vtiger-crm/index.js b/packages/backend/src/apps/vtiger-crm/index.js index f1f6fceb..9a706039 100644 --- a/packages/backend/src/apps/vtiger-crm/index.js +++ b/packages/backend/src/apps/vtiger-crm/index.js @@ -3,6 +3,8 @@ import addAuthHeader from './common/add-auth-header.js'; import setBaseUrl from './common/set-base-url.js'; import auth from './auth/index.js'; import triggers from './triggers/index.js'; +import actions from './actions/index.js'; +import dynamicData from './dynamic-data/index.js'; export default defineApp({ name: 'Vtiger CRM', @@ -16,4 +18,6 @@ export default defineApp({ beforeRequest: [setBaseUrl, addAuthHeader], auth, triggers, + actions, + dynamicData, }); diff --git a/packages/docs/pages/.vitepress/config.js b/packages/docs/pages/.vitepress/config.js index 1bbb537e..490bf6ee 100644 --- a/packages/docs/pages/.vitepress/config.js +++ b/packages/docs/pages/.vitepress/config.js @@ -454,6 +454,7 @@ export default defineConfig({ collapsed: true, items: [ { text: 'Triggers', link: '/apps/vtiger-crm/triggers' }, + { text: 'Actions', link: '/apps/vtiger-crm/actions' }, { text: 'Connection', link: '/apps/vtiger-crm/connection' }, ], }, diff --git a/packages/docs/pages/apps/vtiger-crm/actions.md b/packages/docs/pages/apps/vtiger-crm/actions.md new file mode 100644 index 00000000..cd5f1ee0 --- /dev/null +++ b/packages/docs/pages/apps/vtiger-crm/actions.md @@ -0,0 +1,12 @@ +--- +favicon: /favicons/vtiger-crm.svg +items: + - name: Create opportunity + desc: Create a new opportunity. +--- + + + +