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.
+---
+
+
+
+