From 71b01bf20efc61b46bda7da05a51123c69ed8854 Mon Sep 17 00:00:00 2001 From: Sacha Al Himdani Date: Mon, 23 Feb 2026 14:06:18 +0100 Subject: [PATCH] Add vendor contacts to n8n Signed-off-by: Sacha Al Himdani --- package-lock.json | 1 + .../actions/vendor/createContact.operation.ts | 114 +++++++++++++++ .../actions/vendor/deleteContact.operation.ts | 41 ++++++ .../vendor/getAllContacts.operation.ts | 135 ++++++++++++++++++ .../actions/vendor/getContact.operation.ts | 82 +++++++++++ .../nodes/Probo/actions/vendor/index.ts | 45 ++++++ .../actions/vendor/updateContact.operation.ts | 105 ++++++++++++++ 7 files changed, 523 insertions(+) create mode 100644 packages/n8n-node/nodes/Probo/actions/vendor/createContact.operation.ts create mode 100644 packages/n8n-node/nodes/Probo/actions/vendor/deleteContact.operation.ts create mode 100644 packages/n8n-node/nodes/Probo/actions/vendor/getAllContacts.operation.ts create mode 100644 packages/n8n-node/nodes/Probo/actions/vendor/getContact.operation.ts create mode 100644 packages/n8n-node/nodes/Probo/actions/vendor/updateContact.operation.ts diff --git a/package-lock.json b/package-lock.json index b19ac8d78..2a3794774 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14347,6 +14347,7 @@ "os": [ "darwin" ], + "peer": true, "engines": { "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } diff --git a/packages/n8n-node/nodes/Probo/actions/vendor/createContact.operation.ts b/packages/n8n-node/nodes/Probo/actions/vendor/createContact.operation.ts new file mode 100644 index 000000000..28ce3cfec --- /dev/null +++ b/packages/n8n-node/nodes/Probo/actions/vendor/createContact.operation.ts @@ -0,0 +1,114 @@ +import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow'; +import { proboApiRequest } from '../../GenericFunctions'; + +export const description: INodeProperties[] = [ + { + displayName: 'Vendor ID', + name: 'vendorId', + type: 'string', + displayOptions: { + show: { + resource: ['vendor'], + operation: ['createContact'], + }, + }, + default: '', + description: 'The ID of the vendor', + required: true, + }, + { + displayName: 'Full Name', + name: 'fullName', + type: 'string', + displayOptions: { + show: { + resource: ['vendor'], + operation: ['createContact'], + }, + }, + default: '', + description: 'The full name of the contact', + }, + { + displayName: 'Email', + name: 'email', + type: 'string', + placeholder: 'name@email.com', + displayOptions: { + show: { + resource: ['vendor'], + operation: ['createContact'], + }, + }, + default: '', + description: 'The email address of the contact', + }, + { + displayName: 'Phone', + name: 'phone', + type: 'string', + displayOptions: { + show: { + resource: ['vendor'], + operation: ['createContact'], + }, + }, + default: '', + description: 'The phone number of the contact', + }, + { + displayName: 'Role', + name: 'role', + type: 'string', + displayOptions: { + show: { + resource: ['vendor'], + operation: ['createContact'], + }, + }, + default: '', + description: 'The role of the contact', + }, +]; + +export async function execute( + this: IExecuteFunctions, + itemIndex: number, +): Promise { + const vendorId = this.getNodeParameter('vendorId', itemIndex) as string; + const fullName = this.getNodeParameter('fullName', itemIndex, '') as string; + const email = this.getNodeParameter('email', itemIndex, '') as string; + const phone = this.getNodeParameter('phone', itemIndex, '') as string; + const role = this.getNodeParameter('role', itemIndex, '') as string; + + const query = ` + mutation CreateVendorContact($input: CreateVendorContactInput!) { + createVendorContact(input: $input) { + vendorContactEdge { + node { + id + fullName + email + phone + role + createdAt + updatedAt + } + } + } + } + `; + + const input: Record = { vendorId }; + if (fullName) input.fullName = fullName; + if (email) input.email = email; + if (phone) input.phone = phone; + if (role) input.role = role; + + const responseData = await proboApiRequest.call(this, query, { input }); + + return { + json: responseData, + pairedItem: { item: itemIndex }, + }; +} diff --git a/packages/n8n-node/nodes/Probo/actions/vendor/deleteContact.operation.ts b/packages/n8n-node/nodes/Probo/actions/vendor/deleteContact.operation.ts new file mode 100644 index 000000000..bb74d5f8b --- /dev/null +++ b/packages/n8n-node/nodes/Probo/actions/vendor/deleteContact.operation.ts @@ -0,0 +1,41 @@ +import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow'; +import { proboApiRequest } from '../../GenericFunctions'; + +export const description: INodeProperties[] = [ + { + displayName: 'Vendor Contact ID', + name: 'vendorContactId', + type: 'string', + displayOptions: { + show: { + resource: ['vendor'], + operation: ['deleteContact'], + }, + }, + default: '', + description: 'The ID of the vendor contact to delete', + required: true, + }, +]; + +export async function execute( + this: IExecuteFunctions, + itemIndex: number, +): Promise { + const vendorContactId = this.getNodeParameter('vendorContactId', itemIndex) as string; + + const query = ` + mutation DeleteVendorContact($input: DeleteVendorContactInput!) { + deleteVendorContact(input: $input) { + deletedVendorContactId + } + } + `; + + const responseData = await proboApiRequest.call(this, query, { input: { vendorContactId } }); + + return { + json: responseData, + pairedItem: { item: itemIndex }, + }; +} diff --git a/packages/n8n-node/nodes/Probo/actions/vendor/getAllContacts.operation.ts b/packages/n8n-node/nodes/Probo/actions/vendor/getAllContacts.operation.ts new file mode 100644 index 000000000..a518920ca --- /dev/null +++ b/packages/n8n-node/nodes/Probo/actions/vendor/getAllContacts.operation.ts @@ -0,0 +1,135 @@ +import type { INodeProperties, IExecuteFunctions, INodeExecutionData, IDataObject } from 'n8n-workflow'; +import { proboApiRequestAllItems } from '../../GenericFunctions'; + +export const description: INodeProperties[] = [ + { + displayName: 'Vendor ID', + name: 'vendorId', + type: 'string', + displayOptions: { + show: { + resource: ['vendor'], + operation: ['getAllContacts'], + }, + }, + default: '', + description: 'The ID of the vendor', + required: true, + }, + { + displayName: 'Return All', + name: 'returnAll', + type: 'boolean', + displayOptions: { + show: { + resource: ['vendor'], + operation: ['getAllContacts'], + }, + }, + default: false, + description: 'Whether to return all results or only up to a given limit', + }, + { + displayName: 'Limit', + name: 'limit', + type: 'number', + displayOptions: { + show: { + resource: ['vendor'], + operation: ['getAllContacts'], + returnAll: [false], + }, + }, + typeOptions: { + minValue: 1, + }, + default: 50, + description: 'Max number of results to return', + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Option', + default: {}, + displayOptions: { + show: { + resource: ['vendor'], + operation: ['getAllContacts'], + }, + }, + options: [ + { + displayName: 'Include Vendor', + name: 'includeVendor', + type: 'boolean', + default: false, + description: 'Whether to include vendor in the response', + }, + ], + }, +]; + +export async function execute( + this: IExecuteFunctions, + itemIndex: number, +): Promise { + const vendorId = this.getNodeParameter('vendorId', itemIndex) as string; + const returnAll = this.getNodeParameter('returnAll', itemIndex) as boolean; + const limit = this.getNodeParameter('limit', itemIndex, 50) as number; + const options = this.getNodeParameter('options', itemIndex, {}) as { + includeVendor?: boolean; + }; + + const vendorFragment = options.includeVendor + ? `vendor { + id + name + }` + : ''; + + const query = ` + query GetVendorContacts($vendorId: ID!, $first: Int, $after: CursorKey) { + node(id: $vendorId) { + ... on Vendor { + contacts(first: $first, after: $after) { + edges { + node { + id + fullName + email + phone + role + ${vendorFragment} + createdAt + updatedAt + } + } + pageInfo { + hasNextPage + endCursor + } + } + } + } + } + `; + + const vendorContacts = await proboApiRequestAllItems.call( + this, + query, + { vendorId }, + (response) => { + const data = response?.data as IDataObject | undefined; + const node = data?.node as IDataObject | undefined; + return node?.contacts as IDataObject | undefined; + }, + returnAll, + limit, + ); + + return { + json: { vendorContacts }, + pairedItem: { item: itemIndex }, + }; +} diff --git a/packages/n8n-node/nodes/Probo/actions/vendor/getContact.operation.ts b/packages/n8n-node/nodes/Probo/actions/vendor/getContact.operation.ts new file mode 100644 index 000000000..56eac701b --- /dev/null +++ b/packages/n8n-node/nodes/Probo/actions/vendor/getContact.operation.ts @@ -0,0 +1,82 @@ +import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow'; +import { proboApiRequest } from '../../GenericFunctions'; + +export const description: INodeProperties[] = [ + { + displayName: 'Vendor Contact ID', + name: 'vendorContactId', + type: 'string', + displayOptions: { + show: { + resource: ['vendor'], + operation: ['getContact'], + }, + }, + default: '', + description: 'The ID of the vendor contact', + required: true, + }, + { + displayName: 'Options', + name: 'options', + type: 'collection', + placeholder: 'Add Option', + default: {}, + displayOptions: { + show: { + resource: ['vendor'], + operation: ['getContact'], + }, + }, + options: [ + { + displayName: 'Include Vendor', + name: 'includeVendor', + type: 'boolean', + default: false, + description: 'Whether to include vendor in the response', + }, + ], + }, +]; + +export async function execute( + this: IExecuteFunctions, + itemIndex: number, +): Promise { + const vendorContactId = this.getNodeParameter('vendorContactId', itemIndex) as string; + const options = this.getNodeParameter('options', itemIndex, {}) as { + includeVendor?: boolean; + }; + + const vendorFragment = options.includeVendor + ? `vendor { + id + name + }` + : ''; + + const query = ` + query GetVendorContact($vendorContactId: ID!) { + node(id: $vendorContactId) { + ... on VendorContact { + id + fullName + email + phone + role + ${vendorFragment} + createdAt + updatedAt + } + } + } + `; + + const responseData = await proboApiRequest.call(this, query, { vendorContactId }); + + return { + json: responseData, + pairedItem: { item: itemIndex }, + }; +} diff --git a/packages/n8n-node/nodes/Probo/actions/vendor/index.ts b/packages/n8n-node/nodes/Probo/actions/vendor/index.ts index ea9080fba..1812b9253 100644 --- a/packages/n8n-node/nodes/Probo/actions/vendor/index.ts +++ b/packages/n8n-node/nodes/Probo/actions/vendor/index.ts @@ -4,6 +4,11 @@ import * as updateOp from './update.operation'; import * as deleteOp from './delete.operation'; import * as getOp from './get.operation'; import * as getAllOp from './getAll.operation'; +import * as createContactOp from './createContact.operation'; +import * as updateContactOp from './updateContact.operation'; +import * as deleteContactOp from './deleteContact.operation'; +import * as getContactOp from './getContact.operation'; +import * as getAllContactsOp from './getAllContacts.operation'; import * as createServiceOp from './createService.operation'; import * as updateServiceOp from './updateService.operation'; import * as deleteServiceOp from './deleteService.operation'; @@ -31,6 +36,12 @@ export const description: INodeProperties[] = [ description: 'Create a new vendor', action: 'Create a vendor', }, + { + name: 'Create Contact', + value: 'createContact', + description: 'Create a new vendor contact', + action: 'Create a vendor contact', + }, { name: 'Create Risk Assessment', value: 'createRiskAssessment', @@ -49,6 +60,12 @@ export const description: INodeProperties[] = [ description: 'Delete a vendor', action: 'Delete a vendor', }, + { + name: 'Delete Contact', + value: 'deleteContact', + description: 'Delete a vendor contact', + action: 'Delete a vendor contact', + }, { name: 'Delete Service', value: 'deleteService', @@ -61,12 +78,24 @@ export const description: INodeProperties[] = [ description: 'Get a vendor', action: 'Get a vendor', }, + { + name: 'Get Contact', + value: 'getContact', + description: 'Get a vendor contact', + action: 'Get a vendor contact', + }, { name: 'Get Many', value: 'getAll', description: 'Get many vendors', action: 'Get many vendors', }, + { + name: 'Get Many Contacts', + value: 'getAllContacts', + description: 'Get many vendor contacts', + action: 'Get many vendor contacts', + }, { name: 'Get Many Risk Assessments', value: 'getAllRiskAssessments', @@ -97,6 +126,12 @@ export const description: INodeProperties[] = [ description: 'Update an existing vendor', action: 'Update a vendor', }, + { + name: 'Update Contact', + value: 'updateContact', + description: 'Update an existing vendor contact', + action: 'Update a vendor contact', + }, { name: 'Update Service', value: 'updateService', @@ -111,6 +146,11 @@ export const description: INodeProperties[] = [ ...deleteOp.description, ...getOp.description, ...getAllOp.description, + ...createContactOp.description, + ...updateContactOp.description, + ...deleteContactOp.description, + ...getContactOp.description, + ...getAllContactsOp.description, ...createServiceOp.description, ...updateServiceOp.description, ...deleteServiceOp.description, @@ -127,6 +167,11 @@ export { deleteOp as delete, getOp as get, getAllOp as getAll, + createContactOp as createContact, + updateContactOp as updateContact, + deleteContactOp as deleteContact, + getContactOp as getContact, + getAllContactsOp as getAllContacts, createServiceOp as createService, updateServiceOp as updateService, deleteServiceOp as deleteService, diff --git a/packages/n8n-node/nodes/Probo/actions/vendor/updateContact.operation.ts b/packages/n8n-node/nodes/Probo/actions/vendor/updateContact.operation.ts new file mode 100644 index 000000000..617c55496 --- /dev/null +++ b/packages/n8n-node/nodes/Probo/actions/vendor/updateContact.operation.ts @@ -0,0 +1,105 @@ +import type { INodeProperties, IExecuteFunctions, INodeExecutionData } from 'n8n-workflow'; +import { proboApiRequest } from '../../GenericFunctions'; + +export const description: INodeProperties[] = [ + { + displayName: 'Vendor Contact ID', + name: 'vendorContactId', + type: 'string', + displayOptions: { + show: { + resource: ['vendor'], + operation: ['updateContact'], + }, + }, + default: '', + description: 'The ID of the vendor contact to update', + required: true, + }, + { + displayName: 'Additional Fields', + name: 'additionalFields', + type: 'collection', + placeholder: 'Add Field', + default: {}, + displayOptions: { + show: { + resource: ['vendor'], + operation: ['updateContact'], + }, + }, + options: [ + { + displayName: 'Email', + name: 'email', + type: 'string', + placeholder: 'name@email.com', + default: '', + description: 'The email address of the contact', + }, + { + displayName: 'Full Name', + name: 'fullName', + type: 'string', + default: '', + description: 'The full name of the contact', + }, + { + displayName: 'Phone', + name: 'phone', + type: 'string', + default: '', + description: 'The phone number of the contact', + }, + { + displayName: 'Role', + name: 'role', + type: 'string', + default: '', + description: 'The role of the contact', + }, + ], + }, +]; + +export async function execute( + this: IExecuteFunctions, + itemIndex: number, +): Promise { + const vendorContactId = this.getNodeParameter('vendorContactId', itemIndex) as string; + const additionalFields = this.getNodeParameter('additionalFields', itemIndex, {}) as { + fullName?: string; + email?: string; + phone?: string; + role?: string; + }; + + const query = ` + mutation UpdateVendorContact($input: UpdateVendorContactInput!) { + updateVendorContact(input: $input) { + vendorContact { + id + fullName + email + phone + role + createdAt + updatedAt + } + } + } + `; + + const input: Record = { id: vendorContactId }; + if (additionalFields.fullName !== undefined) input.fullName = additionalFields.fullName === '' ? null : additionalFields.fullName; + if (additionalFields.email !== undefined) input.email = additionalFields.email === '' ? null : additionalFields.email; + if (additionalFields.phone !== undefined) input.phone = additionalFields.phone === '' ? null : additionalFields.phone; + if (additionalFields.role !== undefined) input.role = additionalFields.role === '' ? null : additionalFields.role; + + const responseData = await proboApiRequest.call(this, query, { input }); + + return { + json: responseData, + pairedItem: { item: itemIndex }, + }; +}