Add vendor resource

This commit is contained in:
Iván Ovejero 2021-05-10 12:22:53 +02:00
parent 9d192620b4
commit a02a008c00
5 changed files with 400 additions and 37 deletions

View file

@ -24,6 +24,7 @@ import {
LocationType, LocationType,
NameType, NameType,
ProductDetails, ProductDetails,
ResourceItems,
ZohoOAuth2ApiCredentials, ZohoOAuth2ApiCredentials,
} from './types'; } from './types';
@ -58,7 +59,6 @@ export async function zohoApiRequest(
} }
try { try {
console.log(JSON.stringify(options, null, 2));
return await this.helpers.requestOAuth2?.call(this, 'zohoOAuth2Api', options); return await this.helpers.requestOAuth2?.call(this, 'zohoOAuth2Api', options);
} catch (error) { } catch (error) {
throw new NodeApiError(this.getNode(), error); throw new NodeApiError(this.getNode(), error);
@ -118,7 +118,7 @@ export async function handleListing(
} }
// ---------------------------------------- // ----------------------------------------
// field adjusters // required field adjusters
// ---------------------------------------- // ----------------------------------------
/** /**
@ -133,6 +133,10 @@ export const adjustProductDetails = (productDetails: ProductDetails) => {
}); });
}; };
// ----------------------------------------
// additional field adjusters
// ----------------------------------------
/** /**
* Place a location field's contents at the top level of the payload. * Place a location field's contents at the top level of the payload.
*/ */
@ -191,20 +195,24 @@ const adjustAccountIdField = adjustIdField('accountId', 'Account_Name');
const adjustContactIdField = adjustIdField('contactId', 'Full_Name'); const adjustContactIdField = adjustIdField('contactId', 'Full_Name');
const adjustDealIdField = adjustIdField('dealId', 'Deal_Name'); const adjustDealIdField = adjustIdField('dealId', 'Deal_Name');
export const adjustAccountFields = flow( // ----------------------------------------
// payload adjusters
// ----------------------------------------
export const adjustAccountPayload = flow(
adjustBillingAddressFields, adjustBillingAddressFields,
adjustShippingAddressFields, adjustShippingAddressFields,
); );
export const adjustContactFields = flow( export const adjustContactPayload = flow(
adjustMailingAddressFields, adjustMailingAddressFields,
adjustOtherAddressFields, adjustOtherAddressFields,
adjustDateOfBirthField, adjustDateOfBirthField,
); );
export const adjustDealFields = adjustClosingDateField; export const adjustDealPayload = adjustClosingDateField;
export const adjustInvoiceFields = flow( export const adjustInvoicePayload = flow(
adjustBillingAddressFields, adjustBillingAddressFields,
adjustShippingAddressFields, adjustShippingAddressFields,
adjustInvoiceDateField, adjustInvoiceDateField,
@ -212,22 +220,22 @@ export const adjustInvoiceFields = flow(
adjustAccountIdField, adjustAccountIdField,
); );
export const adjustLeadFields = adjustAddressFields; export const adjustLeadPayload = adjustAddressFields;
export const adjustPurchaseOrderFields = flow( export const adjustPurchaseOrderPayload = flow(
adjustBillingAddressFields, adjustBillingAddressFields,
adjustShippingAddressFields, adjustShippingAddressFields,
adjustDueDateField, adjustDueDateField,
adjustPurchaseOrderDateField, adjustPurchaseOrderDateField,
); );
export const adjustQuoteFields = flow( export const adjustQuotePayload = flow(
adjustBillingAddressFields, adjustBillingAddressFields,
adjustShippingAddressFields, adjustShippingAddressFields,
adjustValidTillField, adjustValidTillField,
); );
export const adjustSalesOrderFields = flow( export const adjustSalesOrderPayload = flow(
adjustBillingAddressFields, adjustBillingAddressFields,
adjustShippingAddressFields, adjustShippingAddressFields,
adjustDueDateField, adjustDueDateField,
@ -236,11 +244,19 @@ export const adjustSalesOrderFields = flow(
adjustDealIdField, adjustDealIdField,
); );
export const adjustVendorPayload = adjustAddressFields;
// ---------------------------------------- // ----------------------------------------
// helpers // helpers
// ---------------------------------------- // ----------------------------------------
const omit = (keyToOmit: string, { [keyToOmit]: _, ...omittedPropObj }) => omittedPropObj; /**
* Create a copy of an object without a specific property.
*/
const omit = (propertyToOmit: string, { [propertyToOmit]: _, ...remainingObject }) => remainingObject;
export const toLoadOptions = (resourceItems: Array<{ [key: string]: string }>, nameProperty: NameType) => /**
resourceItems.map((item) => ({ name: item[nameProperty], value: item.id })); * Convert items in a Zoho CRM API response into n8n load options.
*/
export const toLoadOptions = (items: ResourceItems, nameProperty: NameType) =>
items.map((item) => ({ name: item[nameProperty], value: item.id }));

View file

@ -11,15 +11,16 @@ import {
} from 'n8n-workflow'; } from 'n8n-workflow';
import { import {
adjustAccountFields, adjustAccountPayload,
adjustContactFields, adjustContactPayload,
adjustDealFields, adjustDealPayload,
adjustInvoiceFields, adjustInvoicePayload,
adjustLeadFields, adjustLeadPayload,
adjustProductDetails, adjustProductDetails,
adjustPurchaseOrderFields, adjustPurchaseOrderPayload,
adjustQuoteFields, adjustQuotePayload,
adjustSalesOrderFields, adjustSalesOrderPayload,
adjustVendorPayload,
handleListing, handleListing,
toLoadOptions, toLoadOptions,
zohoApiRequest, zohoApiRequest,
@ -54,6 +55,8 @@ import {
quoteOperations, quoteOperations,
salesOrderFields, salesOrderFields,
salesOrderOperations, salesOrderOperations,
vendorFields,
vendorOperations,
} from './descriptions'; } from './descriptions';
export class ZohoCrm implements INodeType { export class ZohoCrm implements INodeType {
@ -119,6 +122,10 @@ export class ZohoCrm implements INodeType {
name: 'Sales Order', name: 'Sales Order',
value: 'salesOrder', value: 'salesOrder',
}, },
{
name: 'Vendor',
value: 'vendor',
},
], ],
default: 'account', default: 'account',
description: 'Resource to consume', description: 'Resource to consume',
@ -141,6 +148,8 @@ export class ZohoCrm implements INodeType {
...quoteFields, ...quoteFields,
...salesOrderOperations, ...salesOrderOperations,
...salesOrderFields, ...salesOrderFields,
...vendorOperations,
...vendorFields,
], ],
}; };
@ -210,7 +219,7 @@ export class ZohoCrm implements INodeType {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) { if (Object.keys(additionalFields).length) {
Object.assign(body, adjustAccountFields(additionalFields)); Object.assign(body, adjustAccountPayload(additionalFields));
} }
responseData = await zohoApiRequest.call(this, 'POST', '/accounts', body); responseData = await zohoApiRequest.call(this, 'POST', '/accounts', body);
@ -255,7 +264,7 @@ export class ZohoCrm implements INodeType {
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
if (Object.keys(updateFields).length) { if (Object.keys(updateFields).length) {
Object.assign(body, adjustAccountFields(updateFields)); Object.assign(body, adjustAccountPayload(updateFields));
} }
const accountId = this.getNodeParameter('accountId', i); const accountId = this.getNodeParameter('accountId', i);
@ -286,7 +295,7 @@ export class ZohoCrm implements INodeType {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) { if (Object.keys(additionalFields).length) {
Object.assign(body, adjustContactFields(additionalFields)); Object.assign(body, adjustContactPayload(additionalFields));
} }
responseData = await zohoApiRequest.call(this, 'POST', '/contacts', body); responseData = await zohoApiRequest.call(this, 'POST', '/contacts', body);
@ -331,7 +340,7 @@ export class ZohoCrm implements INodeType {
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
if (Object.keys(updateFields).length) { if (Object.keys(updateFields).length) {
Object.assign(body, adjustContactFields(updateFields)); Object.assign(body, adjustContactPayload(updateFields));
} }
const contactId = this.getNodeParameter('contactId', i); const contactId = this.getNodeParameter('contactId', i);
@ -363,7 +372,7 @@ export class ZohoCrm implements INodeType {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) { if (Object.keys(additionalFields).length) {
Object.assign(body, adjustDealFields(additionalFields)); Object.assign(body, adjustDealPayload(additionalFields));
} }
responseData = await zohoApiRequest.call(this, 'POST', '/deals', body); responseData = await zohoApiRequest.call(this, 'POST', '/deals', body);
@ -406,7 +415,7 @@ export class ZohoCrm implements INodeType {
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
if (Object.keys(updateFields).length) { if (Object.keys(updateFields).length) {
Object.assign(body, adjustDealFields(updateFields)); Object.assign(body, adjustDealPayload(updateFields));
} }
const dealId = this.getNodeParameter('dealId', i); const dealId = this.getNodeParameter('dealId', i);
@ -439,7 +448,7 @@ export class ZohoCrm implements INodeType {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) { if (Object.keys(additionalFields).length) {
Object.assign(body, adjustInvoiceFields(additionalFields)); Object.assign(body, adjustInvoicePayload(additionalFields));
} }
responseData = await zohoApiRequest.call(this, 'POST', '/invoices', body); responseData = await zohoApiRequest.call(this, 'POST', '/invoices', body);
@ -484,7 +493,7 @@ export class ZohoCrm implements INodeType {
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
if (Object.keys(updateFields).length) { if (Object.keys(updateFields).length) {
Object.assign(body, adjustInvoiceFields(updateFields)); Object.assign(body, adjustInvoicePayload(updateFields));
} }
const invoiceId = this.getNodeParameter('invoiceId', i); const invoiceId = this.getNodeParameter('invoiceId', i);
@ -516,7 +525,7 @@ export class ZohoCrm implements INodeType {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) { if (Object.keys(additionalFields).length) {
Object.assign(body, adjustLeadFields(additionalFields)); Object.assign(body, adjustLeadPayload(additionalFields));
} }
responseData = await zohoApiRequest.call(this, 'POST', '/leads', body); responseData = await zohoApiRequest.call(this, 'POST', '/leads', body);
@ -559,7 +568,7 @@ export class ZohoCrm implements INodeType {
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
if (Object.keys(updateFields).length) { if (Object.keys(updateFields).length) {
Object.assign(body, adjustLeadFields(updateFields)); Object.assign(body, adjustLeadPayload(updateFields));
} }
const leadId = this.getNodeParameter('leadId', i); const leadId = this.getNodeParameter('leadId', i);
@ -669,7 +678,7 @@ export class ZohoCrm implements INodeType {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) { if (Object.keys(additionalFields).length) {
Object.assign(body, adjustPurchaseOrderFields(additionalFields)); Object.assign(body, adjustPurchaseOrderPayload(additionalFields));
} }
responseData = await zohoApiRequest.call(this, 'POST', '/purchase_orders', body); responseData = await zohoApiRequest.call(this, 'POST', '/purchase_orders', body);
@ -714,7 +723,7 @@ export class ZohoCrm implements INodeType {
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
if (Object.keys(updateFields).length) { if (Object.keys(updateFields).length) {
Object.assign(body, adjustPurchaseOrderFields(updateFields)); Object.assign(body, adjustPurchaseOrderPayload(updateFields));
} }
const purchaseOrderId = this.getNodeParameter('purchaseOrderId', i); const purchaseOrderId = this.getNodeParameter('purchaseOrderId', i);
@ -748,7 +757,7 @@ export class ZohoCrm implements INodeType {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) { if (Object.keys(additionalFields).length) {
Object.assign(body, adjustQuoteFields(additionalFields)); Object.assign(body, adjustQuotePayload(additionalFields));
} }
responseData = await zohoApiRequest.call(this, 'POST', '/quotes', body); responseData = await zohoApiRequest.call(this, 'POST', '/quotes', body);
@ -791,7 +800,7 @@ export class ZohoCrm implements INodeType {
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
if (Object.keys(updateFields).length) { if (Object.keys(updateFields).length) {
Object.assign(body, adjustQuoteFields(updateFields)); Object.assign(body, adjustQuotePayload(updateFields));
} }
const quoteId = this.getNodeParameter('quoteId', i); const quoteId = this.getNodeParameter('quoteId', i);
@ -825,7 +834,7 @@ export class ZohoCrm implements INodeType {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) { if (Object.keys(additionalFields).length) {
Object.assign(body, adjustSalesOrderFields(additionalFields)); Object.assign(body, adjustSalesOrderPayload(additionalFields));
} }
responseData = await zohoApiRequest.call(this, 'POST', '/sales_orders', body); responseData = await zohoApiRequest.call(this, 'POST', '/sales_orders', body);
@ -870,7 +879,7 @@ export class ZohoCrm implements INodeType {
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
if (Object.keys(updateFields).length) { if (Object.keys(updateFields).length) {
Object.assign(body, adjustSalesOrderFields(updateFields)); Object.assign(body, adjustSalesOrderPayload(updateFields));
} }
const salesOrderId = this.getNodeParameter('salesOrderId', i); const salesOrderId = this.getNodeParameter('salesOrderId', i);
@ -880,6 +889,82 @@ export class ZohoCrm implements INodeType {
} }
} else if (resource === 'vendor') {
// **********************************************************************
// vendor
// **********************************************************************
// https://www.zoho.com/crm/developer/docs/api/v2/vendors-response.html
if (operation === 'create') {
// ----------------------------------------
// vendor: create
// ----------------------------------------
const body: IDataObject = {
Vendor_Name: this.getNodeParameter('vendorName', i),
};
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) {
Object.assign(body, adjustVendorPayload(additionalFields));
}
responseData = await zohoApiRequest.call(this, 'POST', '/vendors', body);
} else if (operation === 'delete') {
// ----------------------------------------
// vendor: delete
// ----------------------------------------
const vendorId = this.getNodeParameter('vendorId', i);
const endpoint = `/vendors/${vendorId}`;
responseData = await zohoApiRequest.call(this, 'DELETE', endpoint);
} else if (operation === 'get') {
// ----------------------------------------
// vendor: get
// ----------------------------------------
const vendorId = this.getNodeParameter('vendorId', i);
const endpoint = `/vendors/${vendorId}`;
responseData = await zohoApiRequest.call(this, 'GET', endpoint);
} else if (operation === 'getAll') {
// ----------------------------------------
// vendor: getAll
// ----------------------------------------
responseData = await handleListing.call(this, 'GET', '/vendors');
} else if (operation === 'update') {
// ----------------------------------------
// vendor: update
// ----------------------------------------
const body: IDataObject = {};
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
if (Object.keys(updateFields).length) {
Object.assign(body, adjustVendorPayload(updateFields));
}
const vendorId = this.getNodeParameter('vendorId', i);
const endpoint = `/vendors/${vendorId}`;
responseData = await zohoApiRequest.call(this, 'PUT', endpoint, body);
}
} }
Array.isArray(responseData) Array.isArray(responseData)

View file

@ -0,0 +1,259 @@
import {
INodeProperties,
} from 'n8n-workflow';
import {
address,
makeGetAllFields,
} from './SharedFields';
export const vendorOperations = [
{
displayName: 'Operation',
name: 'operation',
type: 'options',
displayOptions: {
show: {
resource: [
'vendor',
],
},
},
options: [
{
name: 'Create',
value: 'create',
},
{
name: 'Delete',
value: 'delete',
},
{
name: 'Get',
value: 'get',
},
{
name: 'Get All',
value: 'getAll',
},
{
name: 'Update',
value: 'update',
},
],
default: 'create',
description: 'Operation to perform',
},
] as INodeProperties[];
export const vendorFields = [
// ----------------------------------------
// vendor: create
// ----------------------------------------
{
displayName: 'Vendor Name',
name: 'vendorName',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: [
'vendor',
],
operation: [
'create',
],
},
},
},
{
displayName: 'Additional Fields',
name: 'additionalFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: [
'vendor',
],
operation: [
'create',
],
},
},
options: [
address,
{
displayName: 'Category',
name: 'Category',
type: 'string',
default: '',
},
{
displayName: 'Currency',
name: 'Currency',
type: 'string',
default: '',
},
{
displayName: 'Description',
name: 'Description',
type: 'string',
default: '',
},
{
displayName: 'Email',
name: 'Email',
type: 'string',
default: '',
},
{
displayName: 'Phone',
name: 'Phone',
type: 'string',
default: '',
},
{
displayName: 'Website',
name: 'Website',
type: 'string',
default: '',
},
],
},
// ----------------------------------------
// vendor: delete
// ----------------------------------------
{
displayName: 'Vendor ID',
name: 'vendorId',
description: 'ID of the vendor to delete.',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: [
'vendor',
],
operation: [
'delete',
],
},
},
},
// ----------------------------------------
// vendor: get
// ----------------------------------------
{
displayName: 'Vendor ID',
name: 'vendorId',
description: 'ID of the vendor to retrieve.',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: [
'vendor',
],
operation: [
'get',
],
},
},
},
// ----------------------------------------
// vendor: getAll
// ----------------------------------------
...makeGetAllFields('vendor'),
// ----------------------------------------
// vendor: update
// ----------------------------------------
{
displayName: 'Vendor ID',
name: 'vendorId',
description: 'ID of the vendor to update.',
type: 'string',
required: true,
default: '',
displayOptions: {
show: {
resource: [
'vendor',
],
operation: [
'update',
],
},
},
},
{
displayName: 'Update Fields',
name: 'updateFields',
type: 'collection',
placeholder: 'Add Field',
default: {},
displayOptions: {
show: {
resource: [
'vendor',
],
operation: [
'update',
],
},
},
options: [
address,
{
displayName: 'Category',
name: 'Category',
type: 'string',
default: '',
},
{
displayName: 'Currency',
name: 'Currency',
type: 'string',
default: '',
},
{
displayName: 'Description',
name: 'Description',
type: 'string',
default: '',
},
{
displayName: 'Email',
name: 'Email',
type: 'string',
default: '',
},
{
displayName: 'Phone',
name: 'Phone',
type: 'string',
default: '',
},
{
displayName: 'Vendor Name',
name: 'Vendor_Name',
type: 'string',
default: '',
},
{
displayName: 'Website',
name: 'Website',
type: 'string',
default: '',
},
],
},
] as INodeProperties[];

View file

@ -7,3 +7,4 @@ export * from './ProductDescription';
export * from './PurchaseOrderDescription'; export * from './PurchaseOrderDescription';
export * from './QuoteDescription'; export * from './QuoteDescription';
export * from './SalesOrderDescription'; export * from './SalesOrderDescription';
export * from './VendorDescription';

View file

@ -31,6 +31,8 @@ export type AllFields =
export type ProductDetails = Array<{ id: string, quantity: number }>; export type ProductDetails = Array<{ id: string, quantity: number }>;
export type ResourceItems = Array<{ [key: string]: string }>;
// ---------------------------------------- // ----------------------------------------
// for resource loaders // for resource loaders
// ---------------------------------------- // ----------------------------------------