fix(Xero Node): Fix some operations and add support for setting address and phone number (#3048)

* 🐛 Fix issue when sending Organization ID - Xero node

* 👕 Fix linting issue
This commit is contained in:
Ricardo Espinoza 2022-03-27 04:38:49 -04:00 committed by GitHub
parent bd9064cd0e
commit ab08c0df15
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 374 additions and 370 deletions

View file

@ -1,6 +1,6 @@
import { import {
INodeProperties, INodeProperties,
} from 'n8n-workflow'; } from 'n8n-workflow';
export const contactOperations: INodeProperties[] = [ export const contactOperations: INodeProperties[] = [
{ {
@ -43,9 +43,9 @@ export const contactOperations: INodeProperties[] = [
export const contactFields: INodeProperties[] = [ export const contactFields: INodeProperties[] = [
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* contact:create */ /* contact:create */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
{ {
displayName: 'Organization ID', displayName: 'Organization ID',
name: 'organizationId', name: 'organizationId',
@ -108,82 +108,82 @@ export const contactFields: INodeProperties[] = [
default: '', default: '',
description: 'A user defined account number', description: 'A user defined account number',
}, },
// { {
// displayName: 'Addresses', displayName: 'Addresses',
// name: 'addressesUi', name: 'addressesUi',
// type: 'fixedCollection', type: 'fixedCollection',
// typeOptions: { typeOptions: {
// multipleValues: true, multipleValues: true,
// }, },
// default: '', default: '',
// placeholder: 'Add Address', placeholder: 'Add Address',
// options: [ options: [
// { {
// name: 'addressesValues', name: 'addressesValues',
// displayName: 'Address', displayName: 'Address',
// values: [ values: [
// { {
// displayName: 'Type', displayName: 'Type',
// name: 'type', name: 'type',
// type: 'options', type: 'options',
// options: [ options: [
// { {
// name: 'PO Box', name: 'PO Box',
// value: 'POBOX', value: 'POBOX',
// }, },
// { {
// name: 'Street', name: 'Street',
// value: 'STREET', value: 'STREET',
// }, },
// ], ],
// default: '', default: '',
// }, },
// { {
// displayName: 'Line 1', displayName: 'Line 1',
// name: 'line1', name: 'line1',
// type: 'string', type: 'string',
// default: '', default: '',
// }, },
// { {
// displayName: 'Line 2', displayName: 'Line 2',
// name: 'line2', name: 'line2',
// type: 'string', type: 'string',
// default: '', default: '',
// }, },
// { {
// displayName: 'City', displayName: 'City',
// name: 'city', name: 'city',
// type: 'string', type: 'string',
// default: '', default: '',
// }, },
// { {
// displayName: 'Region', displayName: 'Region',
// name: 'region', name: 'region',
// type: 'string', type: 'string',
// default: '', default: '',
// }, },
// { {
// displayName: 'Postal Code', displayName: 'Postal Code',
// name: 'postalCode', name: 'postalCode',
// type: 'string', type: 'string',
// default: '', default: '',
// }, },
// { {
// displayName: 'Country', displayName: 'Country',
// name: 'country', name: 'country',
// type: 'string', type: 'string',
// default: '', default: '',
// }, },
// { {
// displayName: 'Attention To', displayName: 'Attention To',
// name: 'attentionTo', name: 'attentionTo',
// type: 'string', type: 'string',
// default: '', default: '',
// }, },
// ], ],
// }, },
// ], ],
// }, },
{ {
displayName: 'Bank Account Details', displayName: 'Bank Account Details',
name: 'bankAccountDetails', name: 'bankAccountDetails',
@ -250,66 +250,66 @@ export const contactFields: INodeProperties[] = [
default: '', default: '',
description: 'Last name of contact person (max length = 255)', description: 'Last name of contact person (max length = 255)',
}, },
// { {
// displayName: 'Phones', displayName: 'Phones',
// name: 'phonesUi', name: 'phonesUi',
// type: 'fixedCollection', type: 'fixedCollection',
// typeOptions: { typeOptions: {
// multipleValues: true, multipleValues: true,
// }, },
// default: '', default: '',
// placeholder: 'Add Phone', placeholder: 'Add Phone',
// options: [ options: [
// { {
// name: 'phonesValues', name: 'phonesValues',
// displayName: 'Phones', displayName: 'Phones',
// values: [ values: [
// { {
// displayName: 'Type', displayName: 'Type',
// name: 'type', name: 'phoneType',
// type: 'options', type: 'options',
// options: [ options: [
// { {
// name: 'Default', name: 'Default',
// value: 'DEFAULT', value: 'DEFAULT',
// }, },
// { {
// name: 'DDI', name: 'DDI',
// value: 'DDI', value: 'DDI',
// }, },
// { {
// name: 'Mobile', name: 'Mobile',
// value: 'MOBILE', value: 'MOBILE',
// }, },
// { {
// name: 'Fax', name: 'Fax',
// value: 'FAX', value: 'FAX',
// }, },
// ], ],
// default: '', default: '',
// }, },
// { {
// displayName: 'Number', displayName: 'Number',
// name: 'phoneNumber', name: 'phoneNumber',
// type: 'string', type: 'string',
// default: '', default: '',
// }, },
// { {
// displayName: 'Area Code', displayName: 'Area Code',
// name: 'phoneAreaCode', name: 'phoneAreaCode',
// type: 'string', type: 'string',
// default: '', default: '',
// }, },
// { {
// displayName: 'Country Code', displayName: 'Country Code',
// name: 'phoneCountryCode', name: 'phoneCountryCode',
// type: 'string', type: 'string',
// default: '', default: '',
// }, },
// ], ],
// }, },
// ], ],
// }, },
{ {
displayName: 'Purchase Default Account Code', displayName: 'Purchase Default Account Code',
name: 'purchasesDefaultAccountCode', name: 'purchasesDefaultAccountCode',
@ -353,9 +353,9 @@ export const contactFields: INodeProperties[] = [
}, },
], ],
}, },
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* contact:get */ /* contact:get */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
{ {
displayName: 'Organization ID', displayName: 'Organization ID',
name: 'organizationId', name: 'organizationId',
@ -393,9 +393,9 @@ export const contactFields: INodeProperties[] = [
}, },
required: true, required: true,
}, },
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* contact:getAll */ /* contact:getAll */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
{ {
displayName: 'Organization ID', displayName: 'Organization ID',
name: 'organizationId', name: 'organizationId',
@ -519,9 +519,9 @@ export const contactFields: INodeProperties[] = [
}, },
], ],
}, },
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
/* contact:update */ /* contact:update */
/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */
{ {
displayName: 'Organization ID', displayName: 'Organization ID',
name: 'organizationId', name: 'organizationId',
@ -583,82 +583,82 @@ export const contactFields: INodeProperties[] = [
default: '', default: '',
description: 'A user defined account number', description: 'A user defined account number',
}, },
// { {
// displayName: 'Addresses', displayName: 'Addresses',
// name: 'addressesUi', name: 'addressesUi',
// type: 'fixedCollection', type: 'fixedCollection',
// typeOptions: { typeOptions: {
// multipleValues: true, multipleValues: true,
// }, },
// default: '', default: '',
// placeholder: 'Add Address', placeholder: 'Add Address',
// options: [ options: [
// { {
// name: 'addressesValues', name: 'addressesValues',
// displayName: 'Address', displayName: 'Address',
// values: [ values: [
// { {
// displayName: 'Type', displayName: 'Type',
// name: 'type', name: 'type',
// type: 'options', type: 'options',
// options: [ options: [
// { {
// name: 'PO Box', name: 'PO Box',
// value: 'POBOX', value: 'POBOX',
// }, },
// { {
// name: 'Street', name: 'Street',
// value: 'STREET', value: 'STREET',
// }, },
// ], ],
// default: '', default: '',
// }, },
// { {
// displayName: 'Line 1', displayName: 'Line 1',
// name: 'line1', name: 'line1',
// type: 'string', type: 'string',
// default: '', default: '',
// }, },
// { {
// displayName: 'Line 2', displayName: 'Line 2',
// name: 'line2', name: 'line2',
// type: 'string', type: 'string',
// default: '', default: '',
// }, },
// { {
// displayName: 'City', displayName: 'City',
// name: 'city', name: 'city',
// type: 'string', type: 'string',
// default: '', default: '',
// }, },
// { {
// displayName: 'Region', displayName: 'Region',
// name: 'region', name: 'region',
// type: 'string', type: 'string',
// default: '', default: '',
// }, },
// { {
// displayName: 'Postal Code', displayName: 'Postal Code',
// name: 'postalCode', name: 'postalCode',
// type: 'string', type: 'string',
// default: '', default: '',
// }, },
// { {
// displayName: 'Country', displayName: 'Country',
// name: 'country', name: 'country',
// type: 'string', type: 'string',
// default: '', default: '',
// }, },
// { {
// displayName: 'Attention To', displayName: 'Attention To',
// name: 'attentionTo', name: 'attentionTo',
// type: 'string', type: 'string',
// default: '', default: '',
// }, },
// ], ],
// }, },
// ], ],
// }, },
{ {
displayName: 'Bank Account Details', displayName: 'Bank Account Details',
name: 'bankAccountDetails', name: 'bankAccountDetails',
@ -732,66 +732,66 @@ export const contactFields: INodeProperties[] = [
default: '', default: '',
description: 'Full name of contact/organisation', description: 'Full name of contact/organisation',
}, },
// { {
// displayName: 'Phones', displayName: 'Phones',
// name: 'phonesUi', name: 'phonesUi',
// type: 'fixedCollection', type: 'fixedCollection',
// typeOptions: { typeOptions: {
// multipleValues: true, multipleValues: true,
// }, },
// default: '', default: '',
// placeholder: 'Add Phone', placeholder: 'Add Phone',
// options: [ options: [
// { {
// name: 'phonesValues', name: 'phonesValues',
// displayName: 'Phones', displayName: 'Phones',
// values: [ values: [
// { {
// displayName: 'Type', displayName: 'Type',
// name: 'type', name: 'phoneType',
// type: 'options', type: 'options',
// options: [ options: [
// { {
// name: 'Default', name: 'Default',
// value: 'DEFAULT', value: 'DEFAULT',
// }, },
// { {
// name: 'DDI', name: 'DDI',
// value: 'DDI', value: 'DDI',
// }, },
// { {
// name: 'Mobile', name: 'Mobile',
// value: 'MOBILE', value: 'MOBILE',
// }, },
// { {
// name: 'Fax', name: 'Fax',
// value: 'FAX', value: 'FAX',
// }, },
// ], ],
// default: '', default: '',
// }, },
// { {
// displayName: 'Number', displayName: 'Number',
// name: 'phoneNumber', name: 'phoneNumber',
// type: 'string', type: 'string',
// default: '', default: '',
// }, },
// { {
// displayName: 'Area Code', displayName: 'Area Code',
// name: 'phoneAreaCode', name: 'phoneAreaCode',
// type: 'string', type: 'string',
// default: '', default: '',
// }, },
// { {
// displayName: 'Country Code', displayName: 'Country Code',
// name: 'phoneCountryCode', name: 'phoneCountryCode',
// type: 'string', type: 'string',
// default: '', default: '',
// }, },
// ], ],
// }, },
// ], ],
// }, },
{ {
displayName: 'Purchase Default Account Code', displayName: 'Purchase Default Account Code',
name: 'purchasesDefaultAccountCode', name: 'purchasesDefaultAccountCode',

View file

@ -9,7 +9,9 @@ import {
} from 'n8n-core'; } from 'n8n-core';
import { import {
IDataObject, NodeApiError, IDataObject,
JsonObject,
NodeApiError,
} from 'n8n-workflow'; } from 'n8n-workflow';
export async function xeroApiRequest(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, resource: string, body: any = {}, qs: IDataObject = {}, uri?: string, headers: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any export async function xeroApiRequest(this: IExecuteFunctions | IExecuteSingleFunctions | ILoadOptionsFunctions, method: string, resource: string, body: any = {}, qs: IDataObject = {}, uri?: string, headers: IDataObject = {}): Promise<any> { // tslint:disable-line:no-any
@ -26,6 +28,7 @@ export async function xeroApiRequest(this: IExecuteFunctions | IExecuteSingleFun
try { try {
if (body.organizationId) { if (body.organizationId) {
options.headers = { ...options.headers, 'Xero-tenant-id': body.organizationId }; options.headers = { ...options.headers, 'Xero-tenant-id': body.organizationId };
delete body.organizationId;
} }
if (Object.keys(headers).length !== 0) { if (Object.keys(headers).length !== 0) {
options.headers = Object.assign({}, options.headers, headers); options.headers = Object.assign({}, options.headers, headers);
@ -36,7 +39,7 @@ export async function xeroApiRequest(this: IExecuteFunctions | IExecuteSingleFun
//@ts-ignore //@ts-ignore
return await this.helpers.requestOAuth2.call(this, 'xeroOAuth2Api', options); return await this.helpers.requestOAuth2.call(this, 'xeroOAuth2Api', options);
} catch (error) { } catch (error) {
throw new NodeApiError(this.getNode(), error); throw new NodeApiError(this.getNode(), error as JsonObject);
} }
} }

View file

@ -1,6 +1,6 @@
export interface IAddress { export interface IAddress {
Type?: string; AddressType?: string;
AddressLine1?: string; AddressLine1?: string;
AddressLine2?: string; AddressLine2?: string;
City?: string; City?: string;
@ -11,7 +11,7 @@ export interface IAddress {
} }
export interface IPhone { export interface IPhone {
Type?: string; PhoneType?: string;
PhoneNumber?: string; PhoneNumber?: string;
PhoneAreaCode?: string; PhoneAreaCode?: string;
PhoneCountryCode?: string; PhoneCountryCode?: string;

View file

@ -9,6 +9,7 @@ import {
INodePropertyOptions, INodePropertyOptions,
INodeType, INodeType,
INodeTypeDescription, INodeTypeDescription,
JsonObject,
} from 'n8n-workflow'; } from 'n8n-workflow';
import { import {
@ -32,9 +33,9 @@ import {
} from './InvoiceInterface'; } from './InvoiceInterface';
import { import {
IAddress,
IContact, IContact,
// IPhone, IPhone,
// IAddress,
} from './IContactInterface'; } from './IContactInterface';
export class Xero implements INodeType { export class Xero implements INodeType {
@ -222,9 +223,9 @@ export class Xero implements INodeType {
const lineItemsValues = ((this.getNodeParameter('lineItemsUi', i) as IDataObject).lineItemsValues as IDataObject[]); const lineItemsValues = ((this.getNodeParameter('lineItemsUi', i) as IDataObject).lineItemsValues as IDataObject[]);
const body: IInvoice = { const body: IInvoice = {
organizationId, organizationId,
Type: type, Type: type,
Contact: { ContactID: contactId }, Contact: { ContactID: contactId },
}; };
if (lineItemsValues) { if (lineItemsValues) {
@ -311,7 +312,7 @@ export class Xero implements INodeType {
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
const body: IInvoice = { const body: IInvoice = {
organizationId, organizationId,
}; };
if (updateFields.lineItemsUi) { if (updateFields.lineItemsUi) {
@ -353,7 +354,7 @@ export class Xero implements INodeType {
body.Type = updateFields.type as string; body.Type = updateFields.type as string;
} }
if (updateFields.Contact) { if (updateFields.Contact) {
body.Contact = { ContactID: updateFields.contactId as string }; body.Contact = { ContactID: updateFields.contactId as string };
} }
if (updateFields.brandingThemeId) { if (updateFields.brandingThemeId) {
body.BrandingThemeID = updateFields.brandingThemeId as string; body.BrandingThemeID = updateFields.brandingThemeId as string;
@ -438,11 +439,11 @@ export class Xero implements INodeType {
const organizationId = this.getNodeParameter('organizationId', i) as string; const organizationId = this.getNodeParameter('organizationId', i) as string;
const name = this.getNodeParameter('name', i) as string; const name = this.getNodeParameter('name', i) as string;
const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject; const additionalFields = this.getNodeParameter('additionalFields', i) as IDataObject;
// const addressesUi = additionalFields.addressesUi as IDataObject; const addressesUi = additionalFields.addressesUi as IDataObject;
// const phonesUi = additionalFields.phonesUi as IDataObject; const phonesUi = additionalFields.phonesUi as IDataObject;
const body: IContact = { const body: IContact = {
Name: name, Name: name,
}; };
if (additionalFields.accountNumber) { if (additionalFields.accountNumber) {
@ -497,41 +498,41 @@ export class Xero implements INodeType {
body.xeroNetworkKey = additionalFields.xeroNetworkKey as string; body.xeroNetworkKey = additionalFields.xeroNetworkKey as string;
} }
// if (phonesUi) { if (phonesUi) {
// const phoneValues = phonesUi?.phonesValues as IDataObject[]; const phoneValues = phonesUi?.phonesValues as IDataObject[];
// if (phoneValues) { if (phoneValues) {
// const phones: IPhone[] = []; const phones: IPhone[] = [];
// for (const phoneValue of phoneValues) { for (const phoneValue of phoneValues) {
// const phone: IPhone = {}; const phone: IPhone = {};
// phone.Type = phoneValue.type as string; phone.PhoneType = phoneValue.phoneType as string;
// phone.PhoneNumber = phoneValue.PhoneNumber as string; phone.PhoneNumber = phoneValue.phoneNumber as string;
// phone.PhoneAreaCode = phoneValue.phoneAreaCode as string; phone.PhoneAreaCode = phoneValue.phoneAreaCode as string;
// phone.PhoneCountryCode = phoneValue.phoneCountryCode as string; phone.PhoneCountryCode = phoneValue.phoneCountryCode as string;
// phones.push(phone); phones.push(phone);
// } }
// body.Phones = phones; body.Phones = phones;
// } }
// } }
// if (addressesUi) { if (addressesUi) {
// const addressValues = addressesUi?.addressesValues as IDataObject[]; const addressValues = addressesUi?.addressesValues as IDataObject[];
// if (addressValues) { if (addressValues) {
// const addresses: IAddress[] = []; const addresses: IAddress[] = [];
// for (const addressValue of addressValues) { for (const addressValue of addressValues) {
// const address: IAddress = {}; const address: IAddress = {};
// address.Type = addressValue.type as string; address.AddressType = addressValue.type as string;
// address.AddressLine1 = addressValue.line1 as string; address.AddressLine1 = addressValue.line1 as string;
// address.AddressLine2 = addressValue.line2 as string; address.AddressLine2 = addressValue.line2 as string;
// address.City = addressValue.city as string; address.City = addressValue.city as string;
// address.Region = addressValue.region as string; address.Region = addressValue.region as string;
// address.PostalCode = addressValue.postalCode as string; address.PostalCode = addressValue.postalCode as string;
// address.Country = addressValue.country as string; address.Country = addressValue.country as string;
// address.AttentionTo = addressValue.attentionTo as string; address.AttentionTo = addressValue.attentionTo as string;
// addresses.push(address); addresses.push(address);
// } }
// body.Addresses = addresses; body.Addresses = addresses;
// } }
// } }
responseData = await xeroApiRequest.call(this, 'POST', '/Contacts', { organizationId, Contacts: [body] }); responseData = await xeroApiRequest.call(this, 'POST', '/Contacts', { organizationId, Contacts: [body] });
responseData = responseData.Contacts; responseData = responseData.Contacts;
@ -569,8 +570,8 @@ export class Xero implements INodeType {
const organizationId = this.getNodeParameter('organizationId', i) as string; const organizationId = this.getNodeParameter('organizationId', i) as string;
const contactId = this.getNodeParameter('contactId', i) as string; const contactId = this.getNodeParameter('contactId', i) as string;
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject; const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
// const addressesUi = updateFields.addressesUi as IDataObject; const addressesUi = updateFields.addressesUi as IDataObject;
// const phonesUi = updateFields.phonesUi as IDataObject; const phonesUi = updateFields.phonesUi as IDataObject;
const body: IContact = {}; const body: IContact = {};
@ -630,41 +631,41 @@ export class Xero implements INodeType {
body.xeroNetworkKey = updateFields.xeroNetworkKey as string; body.xeroNetworkKey = updateFields.xeroNetworkKey as string;
} }
// if (phonesUi) { if (phonesUi) {
// const phoneValues = phonesUi?.phonesValues as IDataObject[]; const phoneValues = phonesUi?.phonesValues as IDataObject[];
// if (phoneValues) { if (phoneValues) {
// const phones: IPhone[] = []; const phones: IPhone[] = [];
// for (const phoneValue of phoneValues) { for (const phoneValue of phoneValues) {
// const phone: IPhone = {}; const phone: IPhone = {};
// phone.Type = phoneValue.type as string; phone.PhoneType = phoneValue.phoneType as string;
// phone.PhoneNumber = phoneValue.PhoneNumber as string; phone.PhoneNumber = phoneValue.phoneNumber as string;
// phone.PhoneAreaCode = phoneValue.phoneAreaCode as string; phone.PhoneAreaCode = phoneValue.phoneAreaCode as string;
// phone.PhoneCountryCode = phoneValue.phoneCountryCode as string; phone.PhoneCountryCode = phoneValue.phoneCountryCode as string;
// phones.push(phone); phones.push(phone);
// } }
// body.Phones = phones; body.Phones = phones;
// } }
// } }
// if (addressesUi) { if (addressesUi) {
// const addressValues = addressesUi?.addressesValues as IDataObject[]; const addressValues = addressesUi?.addressesValues as IDataObject[];
// if (addressValues) { if (addressValues) {
// const addresses: IAddress[] = []; const addresses: IAddress[] = [];
// for (const addressValue of addressValues) { for (const addressValue of addressValues) {
// const address: IAddress = {}; const address: IAddress = {};
// address.Type = addressValue.type as string; address.AddressType = addressValue.type as string;
// address.AddressLine1 = addressValue.line1 as string; address.AddressLine1 = addressValue.line1 as string;
// address.AddressLine2 = addressValue.line2 as string; address.AddressLine2 = addressValue.line2 as string;
// address.City = addressValue.city as string; address.City = addressValue.city as string;
// address.Region = addressValue.region as string; address.Region = addressValue.region as string;
// address.PostalCode = addressValue.postalCode as string; address.PostalCode = addressValue.postalCode as string;
// address.Country = addressValue.country as string; address.Country = addressValue.country as string;
// address.AttentionTo = addressValue.attentionTo as string; address.AttentionTo = addressValue.attentionTo as string;
// addresses.push(address); addresses.push(address);
// } }
// body.Addresses = addresses; body.Addresses = addresses;
// } }
// } }
responseData = await xeroApiRequest.call(this, 'POST', `/Contacts/${contactId}`, { organizationId, Contacts: [body] }); responseData = await xeroApiRequest.call(this, 'POST', `/Contacts/${contactId}`, { organizationId, Contacts: [body] });
responseData = responseData.Contacts; responseData = responseData.Contacts;
@ -677,7 +678,7 @@ export class Xero implements INodeType {
} }
} catch (error) { } catch (error) {
if (this.continueOnFail()) { if (this.continueOnFail()) {
returnData.push({ error: error.message }); returnData.push({ error: (error as JsonObject).message });
continue; continue;
} }
throw error; throw error;