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,
NameType,
ProductDetails,
ResourceItems,
ZohoOAuth2ApiCredentials,
} from './types';
@ -58,7 +59,6 @@ export async function zohoApiRequest(
}
try {
console.log(JSON.stringify(options, null, 2));
return await this.helpers.requestOAuth2?.call(this, 'zohoOAuth2Api', options);
} catch (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.
*/
@ -191,20 +195,24 @@ const adjustAccountIdField = adjustIdField('accountId', 'Account_Name');
const adjustContactIdField = adjustIdField('contactId', 'Full_Name');
const adjustDealIdField = adjustIdField('dealId', 'Deal_Name');
export const adjustAccountFields = flow(
// ----------------------------------------
// payload adjusters
// ----------------------------------------
export const adjustAccountPayload = flow(
adjustBillingAddressFields,
adjustShippingAddressFields,
);
export const adjustContactFields = flow(
export const adjustContactPayload = flow(
adjustMailingAddressFields,
adjustOtherAddressFields,
adjustDateOfBirthField,
);
export const adjustDealFields = adjustClosingDateField;
export const adjustDealPayload = adjustClosingDateField;
export const adjustInvoiceFields = flow(
export const adjustInvoicePayload = flow(
adjustBillingAddressFields,
adjustShippingAddressFields,
adjustInvoiceDateField,
@ -212,22 +220,22 @@ export const adjustInvoiceFields = flow(
adjustAccountIdField,
);
export const adjustLeadFields = adjustAddressFields;
export const adjustLeadPayload = adjustAddressFields;
export const adjustPurchaseOrderFields = flow(
export const adjustPurchaseOrderPayload = flow(
adjustBillingAddressFields,
adjustShippingAddressFields,
adjustDueDateField,
adjustPurchaseOrderDateField,
);
export const adjustQuoteFields = flow(
export const adjustQuotePayload = flow(
adjustBillingAddressFields,
adjustShippingAddressFields,
adjustValidTillField,
);
export const adjustSalesOrderFields = flow(
export const adjustSalesOrderPayload = flow(
adjustBillingAddressFields,
adjustShippingAddressFields,
adjustDueDateField,
@ -236,11 +244,19 @@ export const adjustSalesOrderFields = flow(
adjustDealIdField,
);
export const adjustVendorPayload = adjustAddressFields;
// ----------------------------------------
// 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';
import {
adjustAccountFields,
adjustContactFields,
adjustDealFields,
adjustInvoiceFields,
adjustLeadFields,
adjustAccountPayload,
adjustContactPayload,
adjustDealPayload,
adjustInvoicePayload,
adjustLeadPayload,
adjustProductDetails,
adjustPurchaseOrderFields,
adjustQuoteFields,
adjustSalesOrderFields,
adjustPurchaseOrderPayload,
adjustQuotePayload,
adjustSalesOrderPayload,
adjustVendorPayload,
handleListing,
toLoadOptions,
zohoApiRequest,
@ -54,6 +55,8 @@ import {
quoteOperations,
salesOrderFields,
salesOrderOperations,
vendorFields,
vendorOperations,
} from './descriptions';
export class ZohoCrm implements INodeType {
@ -119,6 +122,10 @@ export class ZohoCrm implements INodeType {
name: 'Sales Order',
value: 'salesOrder',
},
{
name: 'Vendor',
value: 'vendor',
},
],
default: 'account',
description: 'Resource to consume',
@ -141,6 +148,8 @@ export class ZohoCrm implements INodeType {
...quoteFields,
...salesOrderOperations,
...salesOrderFields,
...vendorOperations,
...vendorFields,
],
};
@ -210,7 +219,7 @@ export class ZohoCrm implements INodeType {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) {
Object.assign(body, adjustAccountFields(additionalFields));
Object.assign(body, adjustAccountPayload(additionalFields));
}
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;
if (Object.keys(updateFields).length) {
Object.assign(body, adjustAccountFields(updateFields));
Object.assign(body, adjustAccountPayload(updateFields));
}
const accountId = this.getNodeParameter('accountId', i);
@ -286,7 +295,7 @@ export class ZohoCrm implements INodeType {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) {
Object.assign(body, adjustContactFields(additionalFields));
Object.assign(body, adjustContactPayload(additionalFields));
}
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;
if (Object.keys(updateFields).length) {
Object.assign(body, adjustContactFields(updateFields));
Object.assign(body, adjustContactPayload(updateFields));
}
const contactId = this.getNodeParameter('contactId', i);
@ -363,7 +372,7 @@ export class ZohoCrm implements INodeType {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) {
Object.assign(body, adjustDealFields(additionalFields));
Object.assign(body, adjustDealPayload(additionalFields));
}
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;
if (Object.keys(updateFields).length) {
Object.assign(body, adjustDealFields(updateFields));
Object.assign(body, adjustDealPayload(updateFields));
}
const dealId = this.getNodeParameter('dealId', i);
@ -439,7 +448,7 @@ export class ZohoCrm implements INodeType {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) {
Object.assign(body, adjustInvoiceFields(additionalFields));
Object.assign(body, adjustInvoicePayload(additionalFields));
}
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;
if (Object.keys(updateFields).length) {
Object.assign(body, adjustInvoiceFields(updateFields));
Object.assign(body, adjustInvoicePayload(updateFields));
}
const invoiceId = this.getNodeParameter('invoiceId', i);
@ -516,7 +525,7 @@ export class ZohoCrm implements INodeType {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) {
Object.assign(body, adjustLeadFields(additionalFields));
Object.assign(body, adjustLeadPayload(additionalFields));
}
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;
if (Object.keys(updateFields).length) {
Object.assign(body, adjustLeadFields(updateFields));
Object.assign(body, adjustLeadPayload(updateFields));
}
const leadId = this.getNodeParameter('leadId', i);
@ -669,7 +678,7 @@ export class ZohoCrm implements INodeType {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) {
Object.assign(body, adjustPurchaseOrderFields(additionalFields));
Object.assign(body, adjustPurchaseOrderPayload(additionalFields));
}
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;
if (Object.keys(updateFields).length) {
Object.assign(body, adjustPurchaseOrderFields(updateFields));
Object.assign(body, adjustPurchaseOrderPayload(updateFields));
}
const purchaseOrderId = this.getNodeParameter('purchaseOrderId', i);
@ -748,7 +757,7 @@ export class ZohoCrm implements INodeType {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) {
Object.assign(body, adjustQuoteFields(additionalFields));
Object.assign(body, adjustQuotePayload(additionalFields));
}
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;
if (Object.keys(updateFields).length) {
Object.assign(body, adjustQuoteFields(updateFields));
Object.assign(body, adjustQuotePayload(updateFields));
}
const quoteId = this.getNodeParameter('quoteId', i);
@ -825,7 +834,7 @@ export class ZohoCrm implements INodeType {
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
if (Object.keys(additionalFields).length) {
Object.assign(body, adjustSalesOrderFields(additionalFields));
Object.assign(body, adjustSalesOrderPayload(additionalFields));
}
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;
if (Object.keys(updateFields).length) {
Object.assign(body, adjustSalesOrderFields(updateFields));
Object.assign(body, adjustSalesOrderPayload(updateFields));
}
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)

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 './QuoteDescription';
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 ResourceItems = Array<{ [key: string]: string }>;
// ----------------------------------------
// for resource loaders
// ----------------------------------------