mirror of
https://github.com/n8n-io/n8n.git
synced 2025-02-21 02:56:40 -08:00
🔨 Refactor product details
This commit is contained in:
parent
120a8eec09
commit
0735316973
|
@ -66,6 +66,7 @@ export async function zohoApiRequest(
|
|||
}
|
||||
|
||||
try {
|
||||
console.log(JSON.stringify(options, null, 2));
|
||||
const responseData = await this.helpers.requestOAuth2?.call(this, 'zohoOAuth2Api', options);
|
||||
|
||||
if (responseData === undefined) return [];
|
||||
|
@ -138,6 +139,19 @@ export function throwOnEmptyUpdate(this: IExecuteFunctions, resource: CamelCaseR
|
|||
);
|
||||
}
|
||||
|
||||
export function throwOnMissingProducts(
|
||||
this: IExecuteFunctions,
|
||||
resource: CamelCaseResource,
|
||||
productDetails: ProductDetails,
|
||||
) {
|
||||
if (!productDetails.length) {
|
||||
throw new NodeOperationError(
|
||||
this.getNode(),
|
||||
`Please enter at least one product for the ${resource}.`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export function throwOnErrorStatus(
|
||||
this: IExecuteFunctions | IHookFunctions | ILoadOptionsFunctions,
|
||||
responseData: { data?: Array<{ status: string, message: string }> },
|
||||
|
@ -168,6 +182,23 @@ export const adjustProductDetails = (productDetails: ProductDetails) => {
|
|||
// additional field adjusters
|
||||
// ----------------------------------------
|
||||
|
||||
/**
|
||||
* Place a product ID at a nested position in a product details field.
|
||||
*
|
||||
* Only for updating products from Invoice, Purchase Order, Quote, and Sales Order.
|
||||
*/
|
||||
export const adjustProductDetailsOnUpdate = (allFields: AllFields) => {
|
||||
if (!allFields.Product_Details) return allFields;
|
||||
|
||||
return allFields.Product_Details.map(p => {
|
||||
return {
|
||||
...omit('product', p),
|
||||
product: { id: p.id },
|
||||
quantity: p.quantity || 1,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Place a location field's contents at the top level of the payload.
|
||||
*/
|
||||
|
@ -268,6 +299,11 @@ export const adjustInvoicePayload = flow(
|
|||
adjustCustomFields,
|
||||
);
|
||||
|
||||
export const adjustInvoicePayloadOnUpdate = flow(
|
||||
adjustInvoicePayload,
|
||||
adjustProductDetailsOnUpdate,
|
||||
);
|
||||
|
||||
export const adjustLeadPayload = flow(
|
||||
adjustAddressFields,
|
||||
adjustCustomFields,
|
||||
|
|
|
@ -16,6 +16,7 @@ import {
|
|||
adjustContactPayload,
|
||||
adjustDealPayload,
|
||||
adjustInvoicePayload,
|
||||
adjustInvoicePayloadOnUpdate,
|
||||
adjustLeadPayload,
|
||||
adjustProductDetails,
|
||||
adjustProductPayload,
|
||||
|
@ -27,6 +28,7 @@ import {
|
|||
getPicklistOptions,
|
||||
handleListing,
|
||||
throwOnEmptyUpdate,
|
||||
throwOnMissingProducts,
|
||||
toLoadOptions,
|
||||
zohoApiRequest,
|
||||
zohoApiRequestAllItems,
|
||||
|
@ -669,6 +671,8 @@ export class ZohoCrm implements INodeType {
|
|||
|
||||
const productDetails = this.getNodeParameter('Product_Details', i) as ProductDetails;
|
||||
|
||||
throwOnMissingProducts.call(this, resource, productDetails);
|
||||
|
||||
const body: IDataObject = {
|
||||
Subject: this.getNodeParameter('subject', i),
|
||||
Product_Details: adjustProductDetails(productDetails),
|
||||
|
@ -730,7 +734,7 @@ export class ZohoCrm implements INodeType {
|
|||
const updateFields = this.getNodeParameter('updateFields', i) as IDataObject;
|
||||
|
||||
if (Object.keys(updateFields).length) {
|
||||
Object.assign(body, adjustInvoicePayload(updateFields));
|
||||
Object.assign(body, adjustInvoicePayloadOnUpdate(updateFields));
|
||||
} else {
|
||||
throwOnEmptyUpdate.call(this, resource);
|
||||
}
|
||||
|
@ -738,6 +742,7 @@ export class ZohoCrm implements INodeType {
|
|||
const invoiceId = this.getNodeParameter('invoiceId', i);
|
||||
|
||||
const endpoint = `/invoices/${invoiceId}`;
|
||||
|
||||
responseData = await zohoApiRequest.call(this, 'PUT', endpoint, body);
|
||||
responseData = responseData.data;
|
||||
|
||||
|
@ -760,7 +765,7 @@ export class ZohoCrm implements INodeType {
|
|||
Object.assign(body, adjustInvoicePayload(additionalFields));
|
||||
}
|
||||
|
||||
responseData = await zohoApiRequest.call(this, 'POST', `/invoices/upsert`, body);
|
||||
responseData = await zohoApiRequest.call(this, 'POST', '/invoices/upsert', body);
|
||||
responseData = responseData.data;
|
||||
|
||||
}
|
||||
|
@ -994,6 +999,8 @@ export class ZohoCrm implements INodeType {
|
|||
|
||||
const productDetails = this.getNodeParameter('Product_Details', i) as ProductDetails;
|
||||
|
||||
throwOnMissingProducts.call(this, resource, productDetails);
|
||||
|
||||
const body: IDataObject = {
|
||||
Subject: this.getNodeParameter('subject', i),
|
||||
Vendor_Name: { id: this.getNodeParameter('vendorId', i) },
|
||||
|
@ -1109,6 +1116,8 @@ export class ZohoCrm implements INodeType {
|
|||
|
||||
const productDetails = this.getNodeParameter('Product_Details', i) as ProductDetails;
|
||||
|
||||
throwOnMissingProducts.call(this, resource, productDetails);
|
||||
|
||||
const body: IDataObject = {
|
||||
Subject: this.getNodeParameter('subject', i),
|
||||
Product_Details: adjustProductDetails(productDetails),
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
currencies,
|
||||
makeCustomFieldsFixedCollection,
|
||||
makeGetAllFields,
|
||||
makeProductDetails,
|
||||
productDetailsOptions,
|
||||
shippingAddress,
|
||||
} from './SharedFields';
|
||||
|
||||
|
@ -103,7 +103,29 @@ export const invoiceFields = [
|
|||
// ----------------------------------------
|
||||
// invoice: create + upsert
|
||||
// ----------------------------------------
|
||||
makeProductDetails('invoice'),
|
||||
{
|
||||
displayName: 'Products',
|
||||
name: 'Product_Details',
|
||||
type: 'collection',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
multipleValueButtonText: 'Add Product',
|
||||
},
|
||||
default: {},
|
||||
placeholder: 'Add Field',
|
||||
options: productDetailsOptions,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'invoice',
|
||||
],
|
||||
operation: [
|
||||
'create',
|
||||
'upsert',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
|
@ -377,6 +399,18 @@ export const invoiceFields = [
|
|||
type: 'string',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Products',
|
||||
name: 'Product_Details',
|
||||
type: 'collection',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
multipleValueButtonText: 'Add Product',
|
||||
},
|
||||
default: {},
|
||||
placeholder: 'Add Field',
|
||||
options: productDetailsOptions,
|
||||
},
|
||||
{
|
||||
displayName: 'Sales Commission',
|
||||
name: 'Sales_Commission',
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
currencies,
|
||||
makeCustomFieldsFixedCollection,
|
||||
makeGetAllFields,
|
||||
makeProductDetails,
|
||||
productDetailsOptions,
|
||||
shippingAddress,
|
||||
} from './SharedFields';
|
||||
|
||||
|
@ -124,7 +124,29 @@ export const purchaseOrderFields = [
|
|||
},
|
||||
},
|
||||
},
|
||||
makeProductDetails('purchaseOrder'),
|
||||
{
|
||||
displayName: 'Products',
|
||||
name: 'Product_Details',
|
||||
type: 'collection',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
multipleValueButtonText: 'Add Product',
|
||||
},
|
||||
default: {},
|
||||
placeholder: 'Add Field',
|
||||
options: productDetailsOptions,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'purchaseOrder',
|
||||
],
|
||||
operation: [
|
||||
'create',
|
||||
'upsert',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
currencies,
|
||||
makeCustomFieldsFixedCollection,
|
||||
makeGetAllFields,
|
||||
makeProductDetails,
|
||||
productDetailsOptions,
|
||||
shippingAddress,
|
||||
} from './SharedFields';
|
||||
|
||||
|
@ -103,7 +103,29 @@ export const quoteFields = [
|
|||
// ----------------------------------------
|
||||
// quote: create + upsert
|
||||
// ----------------------------------------
|
||||
makeProductDetails('quote'),
|
||||
{
|
||||
displayName: 'Products',
|
||||
name: 'Product_Details',
|
||||
type: 'collection',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
multipleValueButtonText: 'Add Product',
|
||||
},
|
||||
default: {},
|
||||
placeholder: 'Add Field',
|
||||
options: productDetailsOptions,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'quote',
|
||||
],
|
||||
operation: [
|
||||
'create',
|
||||
'upsert',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
|
|
|
@ -7,7 +7,7 @@ import {
|
|||
currencies,
|
||||
makeCustomFieldsFixedCollection,
|
||||
makeGetAllFields,
|
||||
makeProductDetails,
|
||||
productDetailsOptions,
|
||||
shippingAddress,
|
||||
} from './SharedFields';
|
||||
|
||||
|
@ -128,7 +128,29 @@ export const salesOrderFields = [
|
|||
// ----------------------------------------
|
||||
// salesOrder: create + upsert
|
||||
// ----------------------------------------
|
||||
makeProductDetails('salesOrder'),
|
||||
{
|
||||
displayName: 'Products',
|
||||
name: 'Product_Details',
|
||||
type: 'collection',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
multipleValueButtonText: 'Add Product',
|
||||
},
|
||||
default: {},
|
||||
placeholder: 'Add Field',
|
||||
options: productDetailsOptions,
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
'salesOrder',
|
||||
],
|
||||
operation: [
|
||||
'create',
|
||||
'upsert',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Additional Fields',
|
||||
name: 'additionalFields',
|
||||
|
|
|
@ -225,93 +225,91 @@ export const address = {
|
|||
],
|
||||
};
|
||||
|
||||
export const makeProductDetails = (resource: CamelCaseResource) => ({
|
||||
displayName: 'Products',
|
||||
name: 'Product_Details',
|
||||
type: 'collection',
|
||||
typeOptions: {
|
||||
multipleValues: true,
|
||||
multipleValueButtonText: 'Add Product',
|
||||
// displayName: 'Products',
|
||||
// name: 'Product_Details',
|
||||
// type: 'collection',
|
||||
// typeOptions: {
|
||||
// multipleValues: true,
|
||||
// multipleValueButtonText: 'Add Product',
|
||||
// },
|
||||
// default: {},
|
||||
// placeholder: 'Add Field',
|
||||
// displayOptions: {
|
||||
// show: {
|
||||
// resource: [
|
||||
// resource,
|
||||
// ],
|
||||
// operation: [
|
||||
// operation,
|
||||
// ],
|
||||
// },
|
||||
// },
|
||||
|
||||
export const productDetailsOptions = [
|
||||
{
|
||||
displayName: 'List Price',
|
||||
name: 'list_price',
|
||||
type: 'number',
|
||||
default: '',
|
||||
},
|
||||
default: {},
|
||||
placeholder: 'Add Field',
|
||||
displayOptions: {
|
||||
show: {
|
||||
resource: [
|
||||
resource,
|
||||
],
|
||||
operation: [
|
||||
'create',
|
||||
'upsert',
|
||||
],
|
||||
{
|
||||
displayName: 'Product ID',
|
||||
name: 'id',
|
||||
type: 'options',
|
||||
default: [],
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getProducts',
|
||||
},
|
||||
},
|
||||
options: [
|
||||
{
|
||||
displayName: 'List Price',
|
||||
name: 'list_price',
|
||||
type: 'number',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Product ID',
|
||||
name: 'id',
|
||||
type: 'options',
|
||||
default: [],
|
||||
typeOptions: {
|
||||
loadOptionsMethod: 'getProducts',
|
||||
},
|
||||
},
|
||||
{
|
||||
displayName: 'Product Description',
|
||||
name: 'product_description',
|
||||
type: 'string',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Quantity',
|
||||
name: 'quantity',
|
||||
type: 'number',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Quantity in Stock',
|
||||
name: 'quantity_in_stock',
|
||||
type: 'number',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Tax',
|
||||
name: 'Tax',
|
||||
type: 'number',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Total',
|
||||
name: 'total',
|
||||
type: 'number',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Total After Discount',
|
||||
name: 'total_after_discount',
|
||||
type: 'number',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Total (Net)',
|
||||
name: 'net_total',
|
||||
type: 'number',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Unit Price',
|
||||
name: 'unit_price',
|
||||
type: 'number',
|
||||
default: '',
|
||||
},
|
||||
],
|
||||
});
|
||||
{
|
||||
displayName: 'Product Description',
|
||||
name: 'product_description',
|
||||
type: 'string',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Quantity',
|
||||
name: 'quantity',
|
||||
type: 'number',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Quantity in Stock',
|
||||
name: 'quantity_in_stock',
|
||||
type: 'number',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Tax',
|
||||
name: 'Tax',
|
||||
type: 'number',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Total',
|
||||
name: 'total',
|
||||
type: 'number',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Total After Discount',
|
||||
name: 'total_after_discount',
|
||||
type: 'number',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Total (Net)',
|
||||
name: 'net_total',
|
||||
type: 'number',
|
||||
default: '',
|
||||
},
|
||||
{
|
||||
displayName: 'Unit Price',
|
||||
name: 'unit_price',
|
||||
type: 'number',
|
||||
default: '',
|
||||
},
|
||||
];
|
||||
|
||||
export const makeGetAllFields = (resource: CamelCaseResource) => {
|
||||
const loadOptionsMethod = `get${capitalizeInitial(resource)}Fields`;
|
||||
|
|
1
packages/nodes-base/nodes/Zoho/types.d.ts
vendored
1
packages/nodes-base/nodes/Zoho/types.d.ts
vendored
|
@ -43,6 +43,7 @@ export type AllFields =
|
|||
{ Account?: { subfields: { id: string; name: string; } } } &
|
||||
{ [key in 'accountId' | 'contactId' | 'dealId']?: string } &
|
||||
{ customFields?: { customFields: Array<{ fieldId: string; value: string; }> } } &
|
||||
{ Product_Details?: ProductDetails } &
|
||||
IDataObject;
|
||||
|
||||
export type ProductDetails = Array<{ id: string, quantity: number }>;
|
||||
|
|
Loading…
Reference in a new issue