Adjust sales orders params

This commit is contained in:
Iván Ovejero 2021-05-10 11:11:11 +02:00
parent 9f8921e48e
commit a61e5bb4d4
9 changed files with 278 additions and 278 deletions

View file

@ -17,6 +17,16 @@ import {
flow,
} from 'lodash';
import {
AllFields,
DateType,
IdType,
LocationType,
NameType,
ProductDetails,
ZohoOAuth2ApiCredentials,
} from './types';
export async function zohoApiRequest(
this: IExecuteFunctions | IHookFunctions | ILoadOptionsFunctions,
method: string,
@ -25,7 +35,7 @@ export async function zohoApiRequest(
qs: IDataObject = {},
uri?: string,
) {
const { oauthTokenData: { api_domain } } = this.getCredentials('zohoOAuth2Api') as ZohoOAuth2ApiCredentials;
const { oauthTokenData } = this.getCredentials('zohoOAuth2Api') as ZohoOAuth2ApiCredentials;
const options: OptionsWithUri = {
body: {
@ -35,7 +45,7 @@ export async function zohoApiRequest(
},
method,
qs,
uri: uri ?? `${api_domain}/crm/v2${endpoint}`,
uri: uri ?? `${oauthTokenData.api_domain}/crm/v2${endpoint}`,
json: true,
};
@ -164,17 +174,23 @@ const adjustPurchaseOrderDateField = adjustDateField('PO_Date');
const adjustValidTillField = adjustDateField('Valid_Till');
/**
* Place an account field's subfields at the top level of the payload.
* Place an ID field's value nested inside the payload.
*/
const adjustAccountField = (allFields: AllFields) => {
if (!allFields.Account) return allFields;
const adjustIdField = (idType: IdType, nameProperty: NameType) => (allFields: AllFields) => {
const idValue = allFields[idType];
if (!idValue) return allFields;
return {
...omit('Account', allFields),
...allFields.Account.subfields,
...omit(idType, allFields),
[nameProperty]: { id: idValue },
};
};
const adjustAccountIdField = adjustIdField('accountId', 'Account_Name');
const adjustContactIdField = adjustIdField('contactId', 'Full_Name');
const adjustDealIdField = adjustIdField('dealId', 'Deal_Name');
export const adjustAccountFields = flow(
adjustBillingAddressFields,
adjustShippingAddressFields,
@ -193,7 +209,7 @@ export const adjustInvoiceFields = flow(
adjustShippingAddressFields,
adjustInvoiceDateField,
adjustDueDateField,
adjustAccountField,
adjustAccountIdField,
);
export const adjustLeadFields = adjustAddressFields;
@ -211,7 +227,14 @@ export const adjustQuoteFields = flow(
adjustValidTillField,
);
export const adjustSalesOrderFields = adjustInvoiceFields;
export const adjustSalesOrderFields = flow(
adjustBillingAddressFields,
adjustShippingAddressFields,
adjustDueDateField,
adjustAccountIdField,
adjustContactIdField,
adjustDealIdField,
);
// ----------------------------------------
// helpers
@ -219,34 +242,5 @@ export const adjustSalesOrderFields = adjustInvoiceFields;
const omit = (keyToOmit: string, { [keyToOmit]: _, ...omittedPropObj }) => omittedPropObj;
// ----------------------------------------
// types
// ----------------------------------------
type LocationType = 'Address' | 'Billing_Address' | 'Mailing_Address' | 'Shipping_Address' | 'Other_Address';
type DateType = 'Date_of_Birth' | 'Closing_Date' | 'Due_Date' | 'Invoice_Date' | 'PO_Date' | 'Valid_Till';
export type AllFields =
{ [Date in DateType]?: string } &
{ [Location in LocationType]?: { address_fields: { [key: string]: string } } } &
{ Account?: { subfields: { id: string; name: string; } } } &
IDataObject;
export type ProductDetails = Array<{ id: string, quantity: number }>;
type ZohoOAuth2ApiCredentials = {
oauthTokenData: {
api_domain: string;
};
};
export type LoadedProducts = Array<{
Product_Name: string;
id: string;
}>;
export type LoadedVendors = Array<{
Vendor_Name: string;
id: string;
}>;
export const toLoadOptions = (resourceItems: Array<{ [key: string]: string }>, nameProperty: NameType) =>
resourceItems.map((item) => ({ name: item[nameProperty], value: item.id }));

View file

@ -21,13 +21,20 @@ import {
adjustQuoteFields,
adjustSalesOrderFields,
handleListing,
LoadedProducts,
LoadedVendors,
ProductDetails,
toLoadOptions,
zohoApiRequest,
zohoApiRequestAllItems,
} from './GenericFunctions';
import {
LoadedAccounts,
LoadedContacts,
LoadedDeals,
LoadedProducts,
LoadedVendors,
ProductDetails,
} from './types';
import {
accountFields,
accountOperations,
@ -139,14 +146,29 @@ export class ZohoCrm implements INodeType {
methods = {
loadOptions: {
async getAccounts(this: ILoadOptionsFunctions) {
const accounts = await zohoApiRequestAllItems.call(this, 'GET', '/accounts') as LoadedAccounts;
return toLoadOptions(accounts, 'Account_Name');
},
async getContacts(this: ILoadOptionsFunctions) {
const contacts = await zohoApiRequestAllItems.call(this, 'GET', '/contacts') as LoadedContacts;
return toLoadOptions(contacts, 'Full_Name');
},
async getDeals(this: ILoadOptionsFunctions) {
const deals = await zohoApiRequestAllItems.call(this, 'GET', '/deals') as LoadedDeals;
return toLoadOptions(deals, 'Deal_Name');
},
async getProducts(this: ILoadOptionsFunctions) {
const products = await zohoApiRequestAllItems.call(this, 'GET', '/products') as LoadedProducts;
return products.map((p) => ({ name: p.Product_Name, value: p.id }));
return toLoadOptions(products, 'Product_Name');
},
async getVendors(this: ILoadOptionsFunctions) {
const vendors = await zohoApiRequestAllItems.call(this, 'GET', '/vendors') as LoadedVendors;
return vendors.map((v) => ({ name: v.Vendor_Name, value: v.id }));
return toLoadOptions(vendors, 'Vendor_Name');
},
},
};
@ -410,8 +432,8 @@ export class ZohoCrm implements INodeType {
const productDetails = this.getNodeParameter('Product_Details', i) as ProductDetails;
const body: IDataObject = {
Product_Details: adjustProductDetails(productDetails),
Subject: this.getNodeParameter('subject', i),
Product_Details: adjustProductDetails(productDetails),
};
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
@ -639,9 +661,9 @@ export class ZohoCrm implements INodeType {
const productDetails = this.getNodeParameter('Product_Details', i) as ProductDetails;
const body: IDataObject = {
Product_Details: adjustProductDetails(productDetails),
Subject: this.getNodeParameter('subject', i),
Vendor_Name: { id: this.getNodeParameter('vendorId', i) },
Product_Details: adjustProductDetails(productDetails),
};
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
@ -719,8 +741,8 @@ export class ZohoCrm implements INodeType {
const productDetails = this.getNodeParameter('Product_Details', i) as ProductDetails;
const body: IDataObject = {
Product_Details: adjustProductDetails(productDetails),
Subject: this.getNodeParameter('subject', i),
Product_Details: adjustProductDetails(productDetails),
};
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
@ -792,9 +814,12 @@ export class ZohoCrm implements INodeType {
// salesOrder: create
// ----------------------------------------
const productDetails = this.getNodeParameter('Product_Details', i) as ProductDetails;
const body: IDataObject = {
Account_Name: this.getNodeParameter('Account_Name', i),
Subject: this.getNodeParameter('Subject', i),
Account_Name: { id: this.getNodeParameter('accountId', i) },
Subject: this.getNodeParameter('subject', i),
Product_Details: adjustProductDetails(productDetails),
};
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
@ -803,7 +828,7 @@ export class ZohoCrm implements INodeType {
Object.assign(body, adjustSalesOrderFields(additionalFields));
}
responseData = await zohoApiRequest.call(this, 'POST', '/salesorders', body);
responseData = await zohoApiRequest.call(this, 'POST', '/sales_orders', body);
} else if (operation === 'delete') {
@ -813,7 +838,7 @@ export class ZohoCrm implements INodeType {
const salesOrderId = this.getNodeParameter('salesOrderId', i);
const endpoint = `/salesorders/${salesOrderId}`;
const endpoint = `/sales_orders/${salesOrderId}`;
responseData = await zohoApiRequest.call(this, 'DELETE', endpoint);
} else if (operation === 'get') {
@ -824,7 +849,7 @@ export class ZohoCrm implements INodeType {
const salesOrderId = this.getNodeParameter('salesOrderId', i);
const endpoint = `/salesorders/${salesOrderId}`;
const endpoint = `/sales_orders/${salesOrderId}`;
responseData = await zohoApiRequest.call(this, 'GET', endpoint);
} else if (operation === 'getAll') {
@ -833,7 +858,7 @@ export class ZohoCrm implements INodeType {
// salesOrder: getAll
// ----------------------------------------
responseData = await handleListing.call(this, 'GET', '/salesorders');
responseData = await handleListing.call(this, 'GET', '/sales_orders');
} else if (operation === 'update') {
@ -850,7 +875,7 @@ export class ZohoCrm implements INodeType {
const salesOrderId = this.getNodeParameter('salesOrderId', i);
const endpoint = `/salesorders/${salesOrderId}`;
const endpoint = `/sales_orders/${salesOrderId}`;
responseData = await zohoApiRequest.call(this, 'PUT', endpoint, body);
}

View file

@ -5,7 +5,7 @@ import {
import {
billingAddress,
makeGetAllFields,
productDetails,
makeProductDetails,
shippingAddress,
} from './SharedFields';
@ -70,7 +70,7 @@ export const invoiceFields = [
},
},
},
productDetails('invoice', 'create'),
makeProductDetails('invoice', 'create'),
{
displayName: 'Additional Fields',
name: 'additionalFields',
@ -89,32 +89,14 @@ export const invoiceFields = [
},
options: [
{
displayName: 'Account',
name: 'Account',
type: 'fixedCollection',
description: 'Account who the invoice is issued for.',
default: {},
placeholder: 'Add Account Field',
options: [
{
displayName: 'Account Fields',
name: 'subfields',
values: [
{
displayName: 'ID',
name: 'id',
type: 'string',
default: '',
},
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
},
],
},
],
displayName: 'Account ID',
name: 'accountId',
type: 'options',
default: [],
typeOptions: {
loadOptionsMethod: 'getAccounts',
},
description: 'ID of the account associated with this invoice.',
},
{
displayName: 'Adjustment',
@ -295,31 +277,14 @@ export const invoiceFields = [
},
options: [
{
displayName: 'Account',
name: 'Account',
type: 'fixedCollection',
default: {},
placeholder: 'Add Account Field',
options: [
{
displayName: 'Account Fields',
name: 'subfields',
values: [
{
displayName: 'ID',
name: 'id',
type: 'string',
default: '',
},
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
},
],
},
],
displayName: 'Account ID',
name: 'accountId',
type: 'options',
default: [],
typeOptions: {
loadOptionsMethod: 'getAccounts',
},
description: 'ID of the account associated with this invoice.',
},
{
displayName: 'Adjustment',

View file

@ -136,6 +136,12 @@ export const leadFields = [
type: 'string',
default: '',
},
{
displayName: 'Email Opt Ou',
name: 'Email_Opt_Out',
type: 'boolean',
default: false,
},
{
displayName: 'Fax',
name: 'Fax',
@ -361,6 +367,12 @@ export const leadFields = [
type: 'string',
default: '',
},
{
displayName: 'Email Opt Ou',
name: 'Email_Opt_Out',
type: 'boolean',
default: false,
},
{
displayName: 'Fax',
name: 'Fax',

View file

@ -5,7 +5,7 @@ import {
import {
billingAddress,
makeGetAllFields,
productDetails,
makeProductDetails,
shippingAddress,
} from './SharedFields';
@ -90,7 +90,7 @@ export const purchaseOrderFields = [
},
},
},
productDetails('purchaseOrder', 'create'),
makeProductDetails('purchaseOrder', 'create'),
{
displayName: 'Additional Fields',
name: 'additionalFields',

View file

@ -5,7 +5,7 @@ import {
import {
billingAddress,
makeGetAllFields,
productDetails,
makeProductDetails,
shippingAddress,
} from './SharedFields';
@ -70,7 +70,7 @@ export const quoteFields = [
},
},
},
productDetails('quote', 'create'),
makeProductDetails('quote', 'create'),
{
displayName: 'Additional Fields',
name: 'additionalFields',

View file

@ -5,7 +5,7 @@ import {
import {
billingAddress,
makeGetAllFields,
productDetails,
makeProductDetails,
shippingAddress,
} from './SharedFields';
@ -53,11 +53,14 @@ export const salesOrderFields = [
// salesOrder: create
// ----------------------------------------
{
displayName: 'Account Name',
name: 'accountName',
type: '',
displayName: 'Account ID',
name: 'accountId',
required: true,
default: '',
type: 'options',
default: [],
typeOptions: {
loadOptionsMethod: 'getAccounts',
},
displayOptions: {
show: {
resource: [
@ -87,6 +90,7 @@ export const salesOrderFields = [
},
},
},
makeProductDetails('salesOrder', 'create'),
{
displayName: 'Additional Fields',
name: 'additionalFields',
@ -108,7 +112,10 @@ export const salesOrderFields = [
displayName: 'Adjustment',
name: 'Adjustment',
type: 'number',
default: '',
default: 0,
typeOptions: {
minValue: 0,
},
description: 'Adjustment in the grand total, if any.',
},
billingAddress,
@ -120,31 +127,13 @@ export const salesOrderFields = [
description: 'Name of the carrier.',
},
{
displayName: 'Contact Name',
name: 'Contact_Name',
type: 'fixedCollection',
default: {},
placeholder: 'Add Contact Name Field',
options: [
{
displayName: 'Contact Name Fields',
name: 'contact_name_fields',
values: [
{
displayName: 'ID',
name: 'id',
type: 'string',
default: '',
},
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
},
],
},
],
displayName: 'Contact ID',
name: 'contactId',
type: 'options',
default: [],
typeOptions: {
loadOptionsMethod: 'getContacts',
},
},
{
displayName: 'Currency',
@ -154,31 +143,13 @@ export const salesOrderFields = [
description: 'Symbol of the currency in which revenue is generated.',
},
{
displayName: 'Deal Name',
name: 'Deal_Name',
type: 'fixedCollection',
default: {},
placeholder: 'Add Deal Name Field',
options: [
{
displayName: 'Deal Name Fields',
name: 'deal_name_fields',
values: [
{
displayName: 'ID',
name: 'id',
type: 'string',
default: '',
},
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
},
],
},
],
displayName: 'Deal ID',
name: 'dealId',
type: 'options',
default: [],
typeOptions: {
loadOptionsMethod: 'getDeals',
},
},
{
displayName: 'Description',
@ -190,37 +161,39 @@ export const salesOrderFields = [
displayName: 'Discount',
name: 'Discount',
type: 'number',
default: '',
default: 0,
typeOptions: {
minValue: 0,
},
},
{
displayName: 'Due Date',
name: 'Due_Date',
type: 'string',
type: 'dateTime',
default: '',
},
{
displayName: 'Exchange Rate',
name: 'Exchange_Rate',
type: 'number',
default: '',
default: 0,
typeOptions: {
minValue: 0,
},
description: 'Exchange rate of the default currency to the home currency.',
},
{
displayName: 'Grand Total',
name: 'Grand_Total',
type: 'number',
default: '',
default: 0,
typeOptions: {
minValue: 0,
},
description: 'Total amount for the product after deducting tax and discounts.',
},
// productDetails,
{
displayName: 'Purchase Order',
name: 'Purchase_Order',
type: 'string',
default: '',
},
{
displayName: 'SO Number',
displayName: 'Sales Order Number',
name: 'SO_Number',
type: 'string',
default: '',
@ -229,8 +202,11 @@ export const salesOrderFields = [
{
displayName: 'Sales Commission',
name: 'Sales_Commission',
type: 'string',
default: '',
type: 'number',
default: 0,
typeOptions: {
minValue: 0,
},
description: 'Commission of sales person on deal closure.',
},
shippingAddress,
@ -245,14 +221,20 @@ export const salesOrderFields = [
displayName: 'Sub Total',
name: 'Sub_Total',
type: 'number',
default: '',
default: 0,
typeOptions: {
minValue: 0,
},
description: 'Total amount for the product excluding tax.',
},
{
displayName: 'Tax',
name: 'Tax',
type: 'number',
default: '',
default: 0,
typeOptions: {
minValue: 0,
},
description: 'Tax amount as the sum of sales tax and value-added tax.',
},
{
@ -291,7 +273,7 @@ export const salesOrderFields = [
// salesOrder: get
// ----------------------------------------
{
displayName: 'salesOrder ID',
displayName: 'Sales Order ID',
name: 'salesOrderId',
description: 'ID of the sales order to retrieve.',
type: 'string',
@ -353,37 +335,23 @@ export const salesOrderFields = [
},
options: [
{
displayName: 'Account Name',
name: 'Account_Name',
type: 'fixedCollection',
default: {},
placeholder: 'Add Account Name Field',
options: [
{
displayName: 'Account Name Fields',
name: 'account_name_fields',
values: [
{
displayName: 'ID',
name: 'id',
type: 'string',
default: '',
},
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
},
],
},
],
displayName: 'Account ID',
name: 'accountId',
type: 'options',
default: [],
typeOptions: {
loadOptionsMethod: 'getAccounts',
},
description: 'ID of the account associated with this invoice.',
},
{
displayName: 'Adjustment',
name: 'Adjustment',
type: 'number',
default: '',
default: 0,
typeOptions: {
minValue: 0,
},
description: 'Adjustment in the grand total, if any.',
},
billingAddress,
@ -395,31 +363,13 @@ export const salesOrderFields = [
description: 'Name of the carrier.',
},
{
displayName: 'Contact Name',
name: 'Contact_Name',
type: 'fixedCollection',
default: {},
placeholder: 'Add Contact Name Field',
options: [
{
displayName: 'Contact Name Fields',
name: 'contact_name_fields',
values: [
{
displayName: 'ID',
name: 'id',
type: 'string',
default: '',
},
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
},
],
},
],
displayName: 'Contact ID',
name: 'contactId',
type: 'options',
default: [],
typeOptions: {
loadOptionsMethod: 'getContacts',
},
},
{
displayName: 'Currency',
@ -429,31 +379,13 @@ export const salesOrderFields = [
description: 'Symbol of the currency in which revenue is generated.',
},
{
displayName: 'Deal Name',
name: 'Deal_Name',
type: 'fixedCollection',
default: {},
placeholder: 'Add Deal Name Field',
options: [
{
displayName: 'Deal Name Fields',
name: 'deal_name_fields',
values: [
{
displayName: 'ID',
name: 'id',
type: 'string',
default: '',
},
{
displayName: 'Name',
name: 'name',
type: 'string',
default: '',
},
],
},
],
displayName: 'Deal ID',
name: 'dealId',
type: 'options',
default: [],
typeOptions: {
loadOptionsMethod: 'getDeals',
},
},
{
displayName: 'Description',
@ -465,37 +397,39 @@ export const salesOrderFields = [
displayName: 'Discount',
name: 'Discount',
type: 'number',
default: '',
default: 0,
typeOptions: {
minValue: 0,
},
},
{
displayName: 'Due Date',
name: 'Due_Date',
type: 'string',
type: 'dateTime',
default: '',
},
{
displayName: 'Exchange Rate',
name: 'Exchange_Rate',
type: 'number',
default: '',
default: 0,
typeOptions: {
minValue: 0,
},
description: 'Exchange rate of the default currency to the home currency.',
},
{
displayName: 'Grand Total',
name: 'Grand_Total',
type: 'number',
default: '',
default: 0,
typeOptions: {
minValue: 0,
},
description: 'Total amount for the product after deducting tax and discounts.',
},
// productDetails,
{
displayName: 'Purchase Order',
name: 'Purchase_Order',
type: 'string',
default: '',
},
{
displayName: 'SO Number',
displayName: 'Sales Order Number',
name: 'SO_Number',
type: 'string',
default: '',
@ -504,8 +438,11 @@ export const salesOrderFields = [
{
displayName: 'Sales Commission',
name: 'Sales_Commission',
type: 'string',
default: '',
type: 'number',
default: 0,
typeOptions: {
minValue: 0,
},
description: 'Commission of sales person on deal closure.',
},
shippingAddress,
@ -520,7 +457,10 @@ export const salesOrderFields = [
displayName: 'Sub Total',
name: 'Sub_Total',
type: 'number',
default: '',
default: 0,
typeOptions: {
minValue: 0,
},
description: 'Total amount for the product excluding tax.',
},
{
@ -534,7 +474,10 @@ export const salesOrderFields = [
displayName: 'Tax',
name: 'Tax',
type: 'number',
default: '',
default: 0,
typeOptions: {
minValue: 0,
},
description: 'Tax amount as the sum of sales tax and value-added tax.',
},
{

View file

@ -222,7 +222,7 @@ export const address = {
],
};
export const productDetails = (resource: string, operation: string) => ({
export const makeProductDetails = (resource: string, operation: string) => ({
displayName: 'Products',
name: 'Product_Details',
type: 'collection',

View file

@ -0,0 +1,61 @@
import { IDataObject } from "n8n-workflow";
// ----------------------------------------
// for auth
// ----------------------------------------
export type ZohoOAuth2ApiCredentials = {
oauthTokenData: {
api_domain: string;
};
};
// ----------------------------------------
// for field adjusters
// ----------------------------------------
export type IdType = 'accountId' | 'contactId' | 'dealId' | 'purchaseOrderId';
export type NameType = 'Account_Name' | 'Full_Name' | 'Deal_Name' | 'Product_Name' | 'Vendor_Name';
type LocationType = 'Address' | 'Billing_Address' | 'Mailing_Address' | 'Shipping_Address' | 'Other_Address';
type DateType = 'Date_of_Birth' | 'Closing_Date' | 'Due_Date' | 'Invoice_Date' | 'PO_Date' | 'Valid_Till';
export type AllFields =
{ [Date in DateType]?: string } &
{ [Location in LocationType]?: { address_fields: { [key: string]: string } } } &
{ Account?: { subfields: { id: string; name: string; } } } &
{ [key in 'accountId' | 'contactId' | 'dealId']?: string } &
IDataObject;
export type ProductDetails = Array<{ id: string, quantity: number }>;
// ----------------------------------------
// for resource loaders
// ----------------------------------------
export type LoadedAccounts = Array<{
Account_Name: string;
id: string;
}>;
export type LoadedContacts = Array<{
Full_Name: string;
id: string;
}>;
export type LoadedDeals = Array<{
Deal_Name: string;
id: string;
}>;
export type LoadedVendors = Array<{
Vendor_Name: string;
id: string;
}>;
export type LoadedProducts = Array<{
Product_Name: string;
id: string;
}>;