UNPKG

n8n-nodes-sap-service-layer

Version:

n8n custom node for SAP Service Layer integration

471 lines (470 loc) 20.1 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SapServiceLayer = void 0; const n8n_workflow_1 = require("n8n-workflow"); const axios_1 = __importStar(require("axios")); const https_1 = __importDefault(require("https")); class SapServiceLayer { constructor() { this.description = { displayName: "PlantScanner - SAP Service Layer", name: "sapServiceLayer", icon: "file:sap_1.svg", group: ["transform"], version: 1, subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}', description: "Interact with SAP Service Layer API", defaults: { name: "SAP Service Layer", }, inputs: ["main"], outputs: ["main"], credentials: [ { name: "sapServiceLayerApi", required: true, }, ], properties: [ { displayName: "Resource", name: "resource", type: "options", noDataExpression: true, options: [ { name: "Item", value: "item", description: "Get materials and items", }, { name: "Production Order", value: "productionOrder", description: "Manage production orders", }, { name: "Warehouse", value: "warehouse", description: "Get warehouse information", }, { name: "Product Tree", value: "productTree", description: "Get production trees", }, { name: "Inventory Gen Entry", value: "inventoryGenEntry", description: "Create and manage inventory entries", }, { name: "Inventory Gen Exit", value: "inventoryGenExit", description: "Create and manage inventory exits", }, { name: "SQL Query", value: "sqlQuery", description: "Execute custom SQL queries", }, ], default: "item", }, { displayName: "Operation", name: "operation", type: "options", noDataExpression: true, displayOptions: { show: { resource: [ "item", "productionOrder", "warehouse", "productTree", "inventoryGenEntry", "inventoryGenExit", "sqlQuery", ], }, }, options: [ { name: "Get", value: "get", description: "Get a single record", action: "Get a record", }, { name: "Get All", value: "getAll", description: "Get all records with filters", action: "Get all records", }, { name: "Update", value: "update", description: "Update a record", action: "Update a record", }, { name: "Create", value: "create", description: "Create a new record", action: "Create a new record", }, { name: "Execute Query", value: "executeQuery", description: "Execute a SQL query", action: "Execute a SQL query", }, { name: "Verify Exists", value: "verifyExists", description: "Check if a record exists", action: "Verify if a record exists", }, ], default: "getAll", }, { displayName: "ID", name: "id", type: "string", displayOptions: { show: { operation: ["get", "update"], resource: ["productionOrder", "warehouse", "productTree"], }, }, default: "", required: true, description: "The ID of the record", }, { displayName: "Journal Memo", name: "journalMemo", type: "string", displayOptions: { show: { operation: ["verifyExists"], resource: ["inventoryGenEntry", "inventoryGenExit"], }, }, default: "", required: true, description: "The journal memo to check", }, { displayName: "Query Name", name: "queryName", type: "string", displayOptions: { show: { operation: ["executeQuery"], resource: ["sqlQuery"], }, }, default: "", required: true, description: "Name of the SQL query to execute (e.g., PlantScannerGetFirstBatch, PlantScannerStockUpdateOnly)", placeholder: "PlantScannerStockUpdateOnly", }, { displayName: "Query Parameters", name: "queryParams", type: "string", displayOptions: { show: { operation: ["executeQuery"], resource: ["sqlQuery"], }, }, default: "", required: false, description: "Parameters for the SQL query body (e.g., updateDate='20240616'). Leave empty if no body parameters needed.", placeholder: "updateDate='20240616'", }, { displayName: "URL Parameters", name: "urlParams", type: "string", displayOptions: { show: { operation: ["executeQuery"], resource: ["sqlQuery"], }, }, default: "", required: false, description: "URL parameters to append to the query (e.g., updateDate=20240614&$skip=400). Leave empty if no URL parameters needed.", placeholder: "updateDate=20240614&$skip=400", }, { displayName: "Filters", name: "filters", type: "string", displayOptions: { show: { operation: ["getAll"], resource: [ "item", "productionOrder", "warehouse", "productTree", "inventoryGenEntry", "inventoryGenExit", ], }, }, default: "", required: false, description: "OData filter string (e.g., WarehouseCode eq 'WH001' or CreationDate ge '2024-03-20')", }, { displayName: "Skip", name: "skip", type: "number", displayOptions: { show: { operation: ["getAll"], resource: [ "item", "productionOrder", "warehouse", "productTree", "inventoryGenEntry", "inventoryGenExit", ], }, }, default: 0, required: false, description: "Number of records to skip", }, { displayName: "Select", name: "select", type: "string", displayOptions: { show: { operation: ["get", "getAll"], resource: [ "item", "productionOrder", "warehouse", "productTree", "inventoryGenEntry", "inventoryGenExit", "sqlQuery", ], }, }, default: "", required: false, description: "Fields to select in the response (comma-separated). Leave empty to get all fields.", hint: "Example: ItemCode, ItemName, PurchaseItem, SalesItem", }, { displayName: "Data", name: "data", type: "json", displayOptions: { show: { operation: ["create", "update"], resource: [ "productionOrder", "inventoryGenEntry", "inventoryGenExit", ], }, }, default: "{}", required: true, description: "The data to send", }, ], }; } async execute() { var _a, _b, _c; const items = this.getInputData(); const returnData = []; const resource = this.getNodeParameter("resource", 0); const operation = this.getNodeParameter("operation", 0); // Get credentials const credentials = await this.getCredentials("sapServiceLayerApi"); const baseUrl = credentials.url; // Create axios instance with SSL verification disabled const axiosInstance = axios_1.default.create({ httpsAgent: new https_1.default.Agent({ rejectUnauthorized: false, }), }); // Login to get session cookie const loginResponse = await axiosInstance.post(`${baseUrl}/Login`, { CompanyDB: credentials.companyDB, UserName: credentials.username, Password: credentials.password, Language: credentials.language || 1, }); const cookies = loginResponse.headers["set-cookie"]; if (!cookies) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), "Failed to get session cookie"); } const sessionCookie = cookies[0].split(";")[0]; const headers = { Cookie: sessionCookie, }; // Process each item for (let i = 0; i < items.length; i++) { try { let response; const endpoint = SapServiceLayer.getEndpoint(resource); switch (operation) { case "create": const createData = this.getNodeParameter("data", i); response = await axiosInstance.post(`${baseUrl}/${endpoint}`, createData, { headers, }); break; case "get": const id = this.getNodeParameter("id", i); const selectGet = this.getNodeParameter("select", i, ""); const paramsGet = {}; if (selectGet) paramsGet.$select = selectGet; response = await axiosInstance.get(`${baseUrl}/${endpoint}(${id})`, { headers, params: paramsGet, }); break; case "getAll": const skip = this.getNodeParameter("skip", i, 0); const filters = this.getNodeParameter("filters", i, ""); const select = this.getNodeParameter("select", i, ""); const params = { $skip: skip, }; if (filters) { params.$filter = filters; } if (select) { params.$select = select; } response = await axiosInstance.get(`${baseUrl}/${endpoint}`, { headers, params, }); break; case "update": const updateId = this.getNodeParameter("id", i); const updateData = this.getNodeParameter("data", i); response = await axiosInstance.patch(`${baseUrl}/${endpoint}(${updateId})`, updateData, { headers }); break; case "executeQuery": const queryName = this.getNodeParameter("queryName", i); const queryParams = this.getNodeParameter("queryParams", i, ""); const urlParams = this.getNodeParameter("urlParams", i, ""); // Build the URL with query parameters let queryUrl = `${baseUrl}/SQLQueries('${queryName}')/List`; if (urlParams) { queryUrl += `?${urlParams}`; } // Build the request body - only include ParamList if queryParams is provided const requestBody = {}; if (queryParams && queryParams.trim() !== '') { requestBody.ParamList = queryParams; } response = await axiosInstance.post(queryUrl, requestBody, { headers }); break; case "verifyExists": const journalMemo = this.getNodeParameter("journalMemo", i); response = await axiosInstance.get(`${baseUrl}/${endpoint}`, { headers, params: { $filter: `JournalMemo eq '${journalMemo}'`, }, }); returnData.push({ json: { exists: response.data.value.length > 0, count: response.data.value.length, }, }); continue; default: throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Operation ${operation} not supported`); } returnData.push({ json: response.data, }); } catch (error) { if (this.continueOnFail()) { const errorMessage = error instanceof axios_1.AxiosError ? ((_c = (_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.error) === null || _c === void 0 ? void 0 : _c.message) || error.message : error instanceof Error ? error.message : "Unknown error occurred"; returnData.push({ json: { error: errorMessage, }, }); continue; } throw error; } } return [returnData]; } static getEndpoint(resource) { switch (resource) { case "item": return "Items"; case "productionOrder": return "ProductionOrders"; case "warehouse": return "Warehouses"; case "productTree": return "ProductTrees"; case "inventoryGenEntry": return "InventoryGenEntries"; case "inventoryGenExit": return "InventoryGenExits"; case "sqlQuery": return "SQLQueries"; default: throw new Error(`Resource ${resource} not supported`); } } } exports.SapServiceLayer = SapServiceLayer;