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:
Ricardo Espinoza
2021-10-26 23:45:26 -04:00
committed by GitHub
parent 15d05c7f01
commit 3e1fb3e0c9
6 changed files with 745 additions and 55 deletions

View File

@@ -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') {