mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 04:04:06 -08:00
⚡ Add search filters to contacts and companies (AgileCRM) (#2373)
* Added search options for the AgileCRM node * Adjusting AgileCRM getAll operation (using Magento 2 node as a reference) * ⚡ Small improvements to #2238 Co-authored-by: Valentina <valentina.lilova98@gmail.com>
This commit is contained in:
parent
15d05c7f01
commit
3e1fb3e0c9
|
@ -1,4 +1,7 @@
|
|||
import { IExecuteFunctions } from 'n8n-core';
|
||||
import {
|
||||
IExecuteFunctions,
|
||||
} from 'n8n-core';
|
||||
|
||||
import {
|
||||
IDataObject,
|
||||
INodeExecutionData,
|
||||
|
@ -22,16 +25,34 @@ import {
|
|||
dealOperations
|
||||
} from './DealDescription';
|
||||
|
||||
import { IContact, IContactUpdate } from './ContactInterface';
|
||||
import { agileCrmApiRequest, agileCrmApiRequestUpdate, validateJSON } from './GenericFunctions';
|
||||
import { IDeal } from './DealInterface';
|
||||
import {
|
||||
IContact,
|
||||
IContactUpdate,
|
||||
} from './ContactInterface';
|
||||
|
||||
import {
|
||||
agileCrmApiRequest, agileCrmApiRequestAllItems,
|
||||
agileCrmApiRequestUpdate,
|
||||
getFilterRules,
|
||||
simplifyResponse,
|
||||
validateJSON,
|
||||
} from './GenericFunctions';
|
||||
|
||||
import {
|
||||
IDeal,
|
||||
} from './DealInterface';
|
||||
|
||||
import {
|
||||
IFilter,
|
||||
ISearchConditions,
|
||||
} from './FilterInterface';
|
||||
|
||||
export class AgileCrm implements INodeType {
|
||||
description: INodeTypeDescription = {
|
||||
displayName: 'Agile CRM',
|
||||
name: 'agileCrm',
|
||||
icon: 'file:agilecrm.png',
|
||||
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
||||
group: ['transform'],
|
||||
version: 1,
|
||||
description: 'Consume Agile CRM API',
|
||||
|
@ -86,7 +107,6 @@ export class AgileCrm implements INodeType {
|
|||
|
||||
};
|
||||
|
||||
|
||||
async execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]> {
|
||||
|
||||
const items = this.getInputData();
|
||||
|
@ -113,26 +133,59 @@ export class AgileCrm implements INodeType {
|
|||
responseData = await agileCrmApiRequest.call(this, 'DELETE', endpoint, {});
|
||||
|
||||
} else if (operation === 'getAll') {
|
||||
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
|
||||
const simple = this.getNodeParameter('simple', 0) as boolean;
|
||||
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
|
||||
const filterType = this.getNodeParameter('filterType', i) as string;
|
||||
const sort = this.getNodeParameter('options.sort.sort', i, {}) as { direction: string, field: string };
|
||||
const body: IDataObject = {};
|
||||
const filterJson: IFilter = {};
|
||||
|
||||
let contactType = '';
|
||||
if (resource === 'contact') {
|
||||
if (returnAll) {
|
||||
const endpoint = 'api/contacts';
|
||||
responseData = await agileCrmApiRequest.call(this, 'GET', endpoint, {});
|
||||
} else {
|
||||
const limit = this.getNodeParameter('limit', i) as number;
|
||||
const endpoint = `api/contacts?page_size=${limit}`;
|
||||
responseData = await agileCrmApiRequest.call(this, 'GET', endpoint, {});
|
||||
}
|
||||
contactType = 'PERSON';
|
||||
} else {
|
||||
if (returnAll) {
|
||||
const endpoint = 'api/contacts/companies/list';
|
||||
responseData = await agileCrmApiRequest.call(this, 'POST', endpoint, {});
|
||||
contactType = 'COMPANY';
|
||||
}
|
||||
filterJson.contact_type = contactType;
|
||||
|
||||
if (filterType === 'manual') {
|
||||
const conditions = this.getNodeParameter('filters.conditions', i, []) as ISearchConditions[];
|
||||
const matchType = this.getNodeParameter('matchType', i) as string;
|
||||
let rules;
|
||||
if (conditions.length !== 0) {
|
||||
rules = getFilterRules(conditions, matchType);
|
||||
Object.assign(filterJson, rules);
|
||||
} else {
|
||||
const limit = this.getNodeParameter('limit', i) as number;
|
||||
const endpoint = `api/contacts/companies/list?page_size=${limit}`;
|
||||
responseData = await agileCrmApiRequest.call(this, 'POST', endpoint, {});
|
||||
throw new NodeOperationError(this.getNode(), 'At least one condition must be added.');
|
||||
}
|
||||
} else if (filterType === 'json') {
|
||||
const filterJsonRules = this.getNodeParameter('filterJson', i) as string;
|
||||
if (validateJSON(filterJsonRules) !== undefined) {
|
||||
Object.assign(filterJson, JSON.parse(filterJsonRules) as IFilter);
|
||||
} else {
|
||||
throw new NodeOperationError(this.getNode(), 'Filter (JSON) must be a valid json');
|
||||
}
|
||||
}
|
||||
body.filterJson = JSON.stringify(filterJson);
|
||||
|
||||
if (sort) {
|
||||
if (sort.direction === 'ASC') {
|
||||
body.global_sort_key = sort.field;
|
||||
} else if (sort.direction === 'DESC') {
|
||||
body.global_sort_key = `-${sort.field}`;
|
||||
}
|
||||
}
|
||||
|
||||
if (returnAll) {
|
||||
body.page_size = 100;
|
||||
responseData = await agileCrmApiRequestAllItems.call(this, 'POST', `api/filters/filter/dynamic-filter`, body, undefined, undefined, true);
|
||||
} else {
|
||||
body.page_size = this.getNodeParameter('limit', 0) as number;
|
||||
responseData = await agileCrmApiRequest.call(this, 'POST', `api/filters/filter/dynamic-filter`, body, undefined, undefined, true);
|
||||
}
|
||||
|
||||
if (simple) {
|
||||
responseData = simplifyResponse(responseData);
|
||||
}
|
||||
|
||||
} else if (operation === 'create') {
|
||||
|
@ -461,15 +514,15 @@ export class AgileCrm implements INodeType {
|
|||
responseData = await agileCrmApiRequest.call(this, 'DELETE', endpoint, {});
|
||||
|
||||
} else if (operation === 'getAll') {
|
||||
const returnAll = this.getNodeParameter('returnAll', i) as boolean;
|
||||
const returnAll = this.getNodeParameter('returnAll', 0) as boolean;
|
||||
const endpoint = 'api/opportunity';
|
||||
|
||||
if (returnAll) {
|
||||
const endpoint = 'api/opportunity';
|
||||
responseData = await agileCrmApiRequest.call(this, 'GET', endpoint, {});
|
||||
const limit = 100;
|
||||
responseData = await agileCrmApiRequestAllItems.call(this, 'GET', endpoint, undefined, { page_size: limit });
|
||||
} else {
|
||||
const limit = this.getNodeParameter('limit', i) as number;
|
||||
const endpoint = `api/opportunity?page_size=${limit}`;
|
||||
responseData = await agileCrmApiRequest.call(this, 'GET', endpoint, {});
|
||||
const limit = this.getNodeParameter('limit', 0) as number;
|
||||
responseData = await agileCrmApiRequest.call(this, 'GET', endpoint, undefined, { page_size: limit });
|
||||
}
|
||||
|
||||
} else if (operation === 'create') {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {
|
||||
INodeProperties,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
export const companyOperations = [
|
||||
{
|
||||
displayName: 'Operation',
|
||||
|
@ -44,6 +45,7 @@ export const companyOperations = [
|
|||
description: 'The operation to perform.',
|
||||
},
|
||||
] as INodeProperties[];
|
||||
|
||||
export const companyFields = [
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* company:get */
|
||||
|
@ -91,7 +93,6 @@ export const companyFields = [
|
|||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
default: 20,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
|
@ -105,7 +106,280 @@ export const companyFields = [
|
|||
],
|
||||
},
|
||||
},
|
||||
default: 20,
|
||||
description: 'Number of results to fetch.',
|
||||
},
|
||||
|
||||
{
|
||||
displayName: 'Filter',
|
||||
name: 'filterType',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'None',
|
||||
value: 'none',
|
||||
},
|
||||
{
|
||||
name: 'Build Manually',
|
||||
value: 'manual',
|
||||
},
|
||||
{
|
||||
name: 'JSON',
|
||||
value: 'json',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'company',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: 'none',
|
||||
},
|
||||
{
|
||||
displayName: 'Must Match',
|
||||
name: 'matchType',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Any filter',
|
||||
value: 'anyFilter',
|
||||
},
|
||||
{
|
||||
name: 'All Filters',
|
||||
value: 'allFilters',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'company',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
filterType: [
|
||||
'manual',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: 'anyFilter',
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify Response',
|
||||
name: 'simple',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'company',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Return a simplified version of the response instead of the raw data.',
|
||||
},
|
||||
{
|
||||
displayName: 'Filters',
|
||||
name: 'filters',
|
||||
type: 'fixedCollection',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'company',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
filterType: [
|
||||
'manual',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
placeholder: 'Add Condition',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Conditions',
|
||||
name: 'conditions',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Field',
|
||||
name: 'field',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Any searchable field.',
|
||||
},
|
||||
{
|
||||
displayName: 'Condition Type',
|
||||
name: 'condition_type',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Equals',
|
||||
value: 'EQUALS',
|
||||
},
|
||||
{
|
||||
name: 'Not Equal',
|
||||
value: 'NOTEQUALS',
|
||||
},
|
||||
{
|
||||
name: 'Last',
|
||||
value: 'LAST',
|
||||
},
|
||||
{
|
||||
name: 'Between',
|
||||
value: 'BETWEEN',
|
||||
},
|
||||
{
|
||||
name: 'On',
|
||||
value: 'ON',
|
||||
},
|
||||
{
|
||||
name: 'Before',
|
||||
value: 'BEFORE',
|
||||
},
|
||||
{
|
||||
name: 'After',
|
||||
value: 'AFTER',
|
||||
},
|
||||
],
|
||||
default: 'EQUALS',
|
||||
},
|
||||
{
|
||||
displayName: 'Value',
|
||||
name: 'value',
|
||||
type: 'string',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Value 2',
|
||||
name: 'value2',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
condition_type: [
|
||||
'BETWEEN',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'See <a href="https://github.com/agilecrm/rest-api#121-get-contacts-by-dynamic-filter" target="_blank">Agile CRM guide</a> to creating filters',
|
||||
name: 'jsonNotice',
|
||||
type: 'notice',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'company',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
filterType: [
|
||||
'json',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Filters (JSON)',
|
||||
name: 'filterJson',
|
||||
type: 'string',
|
||||
typeOptions: {
|
||||
alwaysOpenEditWindow: true,
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'company',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
filterType: [
|
||||
'json',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Option',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'company',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Sort',
|
||||
name: 'sort',
|
||||
type: 'fixedCollection',
|
||||
placeholder: 'Add Sort',
|
||||
default: [],
|
||||
options: [
|
||||
{
|
||||
displayName: 'Sort',
|
||||
name: 'sort',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Direction',
|
||||
name: 'direction',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Ascending',
|
||||
value: 'ASC',
|
||||
},
|
||||
{
|
||||
name: 'Descending',
|
||||
value: 'DESC',
|
||||
},
|
||||
],
|
||||
default: 'ASC',
|
||||
description: 'The sorting direction',
|
||||
},
|
||||
{
|
||||
displayName: 'Field',
|
||||
name: 'field',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: `The sorting field`,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* company:create */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
@ -657,4 +931,5 @@ export const companyFields = [
|
|||
},
|
||||
],
|
||||
},
|
||||
|
||||
] as INodeProperties[];
|
||||
|
|
|
@ -71,25 +71,7 @@ export const contactFields = [
|
|||
/* -------------------------------------------------------------------------- */
|
||||
/* contact:get all */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
default: 20,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'contact',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
returnAll: [
|
||||
false,
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
displayName: 'Return All',
|
||||
name: 'returnAll',
|
||||
|
@ -107,6 +89,296 @@ export const contactFields = [
|
|||
default: false,
|
||||
description: 'If all results should be returned or only up to a given limit.',
|
||||
},
|
||||
{
|
||||
displayName: 'Limit',
|
||||
name: 'limit',
|
||||
type: 'number',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'contact',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
returnAll: [
|
||||
false,
|
||||
],
|
||||
},
|
||||
},
|
||||
default: 20,
|
||||
description: 'Number of results to fetch.',
|
||||
},
|
||||
|
||||
{
|
||||
displayName: 'Filter',
|
||||
name: 'filterType',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'None',
|
||||
value: 'none',
|
||||
},
|
||||
{
|
||||
name: 'Build Manually',
|
||||
value: 'manual',
|
||||
},
|
||||
{
|
||||
name: 'JSON',
|
||||
value: 'json',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'contact',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: 'none',
|
||||
},
|
||||
{
|
||||
displayName: 'Must Match',
|
||||
name: 'matchType',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Any filter',
|
||||
value: 'anyFilter',
|
||||
},
|
||||
{
|
||||
name: 'All Filters',
|
||||
value: 'allFilters',
|
||||
},
|
||||
],
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'contact',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
filterType: [
|
||||
'manual',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: 'anyFilter',
|
||||
},
|
||||
{
|
||||
displayName: 'Simplify Response',
|
||||
name: 'simple',
|
||||
type: 'boolean',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'contact',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: false,
|
||||
description: 'Return a simplified version of the response instead of the raw data.',
|
||||
},
|
||||
{
|
||||
displayName: 'Filters',
|
||||
name: 'filters',
|
||||
type: 'fixedCollection',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'contact',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
filterType: [
|
||||
'manual',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
placeholder: 'Add Condition',
|
||||
options: [
|
||||
{
|
||||
displayName: 'Conditions',
|
||||
name: 'conditions',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Field',
|
||||
name: 'field',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: 'Any searchable field.',
|
||||
},
|
||||
{
|
||||
displayName: 'Condition Type',
|
||||
name: 'condition_type',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Equals',
|
||||
value: 'EQUALS',
|
||||
},
|
||||
{
|
||||
name: 'Not Equal',
|
||||
value: 'NOTEQUALS',
|
||||
},
|
||||
{
|
||||
name: 'Last',
|
||||
value: 'LAST',
|
||||
},
|
||||
{
|
||||
name: 'Between',
|
||||
value: 'BETWEEN',
|
||||
},
|
||||
{
|
||||
name: 'On',
|
||||
value: 'ON',
|
||||
},
|
||||
{
|
||||
name: 'Before',
|
||||
value: 'BEFORE',
|
||||
},
|
||||
{
|
||||
name: 'After',
|
||||
value: 'AFTER',
|
||||
},
|
||||
],
|
||||
default: 'EQUALS',
|
||||
},
|
||||
{
|
||||
displayName: 'Value',
|
||||
name: 'value',
|
||||
type: 'string',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Value 2',
|
||||
name: 'value2',
|
||||
type: 'string',
|
||||
displayOptions: {
|
||||
show: {
|
||||
condition_type: [
|
||||
'BETWEEN',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
displayName: 'See <a href="https://github.com/agilecrm/rest-api#121-get-contacts-by-dynamic-filter" target="_blank">Agile CRM guide</a> to creating filters',
|
||||
name: 'jsonNotice',
|
||||
type: 'notice',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'contact',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
filterType: [
|
||||
'json',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Filters (JSON)',
|
||||
name: 'filterJson',
|
||||
type: 'string',
|
||||
typeOptions: {
|
||||
alwaysOpenEditWindow: true,
|
||||
},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'contact',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
filterType: [
|
||||
'json',
|
||||
],
|
||||
},
|
||||
},
|
||||
default: '',
|
||||
description: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Options',
|
||||
name: 'options',
|
||||
type: 'collection',
|
||||
placeholder: 'Add Option',
|
||||
default: {},
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'contact',
|
||||
],
|
||||
operation: [
|
||||
'getAll',
|
||||
],
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'Sort',
|
||||
name: 'sort',
|
||||
type: 'fixedCollection',
|
||||
placeholder: 'Add Sort',
|
||||
default: [],
|
||||
options: [
|
||||
{
|
||||
displayName: 'Sort',
|
||||
name: 'sort',
|
||||
values: [
|
||||
{
|
||||
displayName: 'Direction',
|
||||
name: 'direction',
|
||||
type: 'options',
|
||||
options: [
|
||||
{
|
||||
name: 'Ascending',
|
||||
value: 'ASC',
|
||||
},
|
||||
{
|
||||
name: 'Descending',
|
||||
value: 'DESC',
|
||||
},
|
||||
],
|
||||
default: 'ASC',
|
||||
description: 'The sorting direction',
|
||||
},
|
||||
{
|
||||
displayName: 'Field',
|
||||
name: 'field',
|
||||
type: 'string',
|
||||
default: '',
|
||||
description: `The sorting field`,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* contact:create */
|
||||
|
@ -988,4 +1260,5 @@ export const contactFields = [
|
|||
},
|
||||
],
|
||||
},
|
||||
|
||||
] as INodeProperties[];
|
||||
|
|
|
@ -110,8 +110,6 @@ export const dealFields = [
|
|||
default: false,
|
||||
description: 'If all results should be returned or only up to a given limit.',
|
||||
},
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/* deal:create */
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
|
19
packages/nodes-base/nodes/AgileCrm/FilterInterface.ts
Normal file
19
packages/nodes-base/nodes/AgileCrm/FilterInterface.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
export interface ISearchConditions {
|
||||
field?: string;
|
||||
condition_type?: string;
|
||||
value?: string;
|
||||
value2?: string;
|
||||
}
|
||||
|
||||
export interface IFilterRules {
|
||||
LHS?: string;
|
||||
CONDITION?: string;
|
||||
RHS?: string;
|
||||
RHS_NEW?: string;
|
||||
}
|
||||
|
||||
export interface IFilter {
|
||||
or_rules?: IFilterRules;
|
||||
rules?: IFilterRules;
|
||||
contact_type?: string;
|
||||
}
|
|
@ -1,6 +1,4 @@
|
|||
import {
|
||||
OptionsWithUri
|
||||
} from 'request';
|
||||
import { OptionsWithUri } from 'request';
|
||||
|
||||
import {
|
||||
IExecuteFunctions,
|
||||
|
@ -10,12 +8,21 @@ import {
|
|||
} from 'n8n-core';
|
||||
|
||||
import {
|
||||
IDataObject, NodeApiError,
|
||||
IDataObject,
|
||||
NodeApiError,
|
||||
} from 'n8n-workflow';
|
||||
import { IContactUpdate } from './ContactInterface';
|
||||
|
||||
import {
|
||||
IContactUpdate,
|
||||
} from './ContactInterface';
|
||||
|
||||
export async function agileCrmApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, endpoint: string, body: any = {}, query: IDataObject = {}, uri?: string): Promise<any> { // tslint:disable-line:no-any
|
||||
import {
|
||||
IFilterRules,
|
||||
ISearchConditions,
|
||||
} from './FilterInterface';
|
||||
|
||||
export async function agileCrmApiRequest(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions,
|
||||
method: string, endpoint: string, body: any = {}, query: IDataObject = {}, uri?: string, sendAsForm?: boolean): Promise<any> { // tslint:disable-line:no-any
|
||||
|
||||
const credentials = await this.getCredentials('agileCrmApi');
|
||||
const options: OptionsWithUri = {
|
||||
|
@ -27,12 +34,18 @@ export async function agileCrmApiRequest(this: IHookFunctions | IExecuteFunction
|
|||
username: credentials!.email as string,
|
||||
password: credentials!.apiKey as string,
|
||||
},
|
||||
qs: query,
|
||||
uri: uri || `https://${credentials!.subdomain}.agilecrm.com/dev/${endpoint}`,
|
||||
json: true,
|
||||
};
|
||||
|
||||
// To send the request as 'content-type': 'application/x-www-form-urlencoded' add form to options instead of body
|
||||
if(sendAsForm) {
|
||||
options.form = body;
|
||||
}
|
||||
// Only add Body property if method not GET or DELETE to avoid 400 response
|
||||
if (method !== 'GET' && method !== 'DELETE') {
|
||||
// And when not sending a form
|
||||
else if (method !== 'GET' && method !== 'DELETE') {
|
||||
options.body = body;
|
||||
}
|
||||
|
||||
|
@ -41,7 +54,30 @@ export async function agileCrmApiRequest(this: IHookFunctions | IExecuteFunction
|
|||
} catch (error) {
|
||||
throw new NodeApiError(this.getNode(), error);
|
||||
}
|
||||
}
|
||||
|
||||
export async function agileCrmApiRequestAllItems(this: IHookFunctions | ILoadOptionsFunctions | IExecuteFunctions,
|
||||
method: string, resource: string, body: any = {}, query: IDataObject = {}, uri?: string, sendAsForm?: boolean): Promise<any> { // tslint:disable-line:no-any
|
||||
// https://github.com/agilecrm/rest-api#11-listing-contacts-
|
||||
|
||||
const returnData: IDataObject[] = [];
|
||||
let responseData;
|
||||
do {
|
||||
responseData = await agileCrmApiRequest.call(this, method, resource, body, query, uri, sendAsForm);
|
||||
if (responseData.length !== 0) {
|
||||
returnData.push.apply(returnData, responseData);
|
||||
if (sendAsForm) {
|
||||
body.cursor = responseData[responseData.length-1].cursor;
|
||||
} else {
|
||||
query.cursor = responseData[responseData.length-1].cursor;
|
||||
}
|
||||
}
|
||||
} while (
|
||||
responseData.length !== 0 &&
|
||||
responseData[responseData.length-1].hasOwnProperty('cursor')
|
||||
);
|
||||
|
||||
return returnData;
|
||||
}
|
||||
|
||||
export async function agileCrmApiRequestUpdate(this: IHookFunctions | IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method = 'PUT', endpoint?: string, body: any = {}, query: IDataObject = {}, uri?: string): Promise<any> { // tslint:disable-line:no-any
|
||||
|
@ -131,3 +167,39 @@ export function validateJSON(json: string | undefined): any { // tslint:disable-
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getFilterRules(conditions: ISearchConditions[], matchType: string): IDataObject { // tslint:disable-line:no-any
|
||||
const rules = [];
|
||||
|
||||
for (const key in conditions) {
|
||||
if (conditions.hasOwnProperty(key)) {
|
||||
const searchConditions: ISearchConditions = conditions[key] as ISearchConditions;
|
||||
const rule: IFilterRules = {
|
||||
LHS: searchConditions.field,
|
||||
CONDITION: searchConditions.condition_type,
|
||||
RHS: searchConditions.value as string,
|
||||
RHS_NEW: searchConditions.value2 as string,
|
||||
};
|
||||
rules.push(rule);
|
||||
}
|
||||
}
|
||||
|
||||
if (matchType === 'anyFilter') {
|
||||
return {
|
||||
or_rules: rules,
|
||||
};
|
||||
}
|
||||
else {
|
||||
return {
|
||||
rules,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export function simplifyResponse(records: [{ id: string, properties: [{ name: string, value: string }] } ]) {
|
||||
const results = [];
|
||||
for (const record of records) {
|
||||
results.push(record.properties.reduce((obj, value) => Object.assign(obj, { [`${value.name}`]: value.value }), { id: record.id }));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue