n8n-nodes-perfexcrm 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +119 -0
- package/dist/credentials/PerfexCrmApi.credentials.d.ts +9 -0
- package/dist/credentials/PerfexCrmApi.credentials.js +71 -0
- package/dist/nodes/PerfexCrm/PerfexCrm.node.d.ts +5 -0
- package/dist/nodes/PerfexCrm/PerfexCrm.node.js +409 -0
- package/dist/nodes/PerfexCrm/PerfexCrmTrigger.node.d.ts +12 -0
- package/dist/nodes/PerfexCrm/PerfexCrmTrigger.node.js +415 -0
- package/dist/nodes/PerfexCrm/descriptions/ContractDescription.d.ts +3 -0
- package/dist/nodes/PerfexCrm/descriptions/ContractDescription.js +5 -0
- package/dist/nodes/PerfexCrm/descriptions/CustomerDescription.d.ts +3 -0
- package/dist/nodes/PerfexCrm/descriptions/CustomerDescription.js +421 -0
- package/dist/nodes/PerfexCrm/descriptions/InvoiceDescription.d.ts +3 -0
- package/dist/nodes/PerfexCrm/descriptions/InvoiceDescription.js +5 -0
- package/dist/nodes/PerfexCrm/descriptions/LeadDescription.d.ts +3 -0
- package/dist/nodes/PerfexCrm/descriptions/LeadDescription.js +5 -0
- package/dist/nodes/PerfexCrm/descriptions/ProjectDescription.d.ts +3 -0
- package/dist/nodes/PerfexCrm/descriptions/ProjectDescription.js +5 -0
- package/dist/nodes/PerfexCrm/descriptions/TicketDescription.d.ts +3 -0
- package/dist/nodes/PerfexCrm/descriptions/TicketDescription.js +569 -0
- package/package.json +63 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 OBS Technologies
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# n8n-nodes-perfexcrm
|
|
2
|
+
|
|
3
|
+
This is an n8n community node. It lets you use PerfexCRM in your n8n workflows.
|
|
4
|
+
|
|
5
|
+
PerfexCRM is a powerful customer relationship management system. This node allows you to interact with the PerfexCRM API and receive webhooks for real-time events.
|
|
6
|
+
|
|
7
|
+
[n8n](https://n8n.io/) is a [fair-code licensed](https://docs.n8n.io/reference/license/) workflow automation platform.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
Follow the [installation guide](https://docs.n8n.io/integrations/community-nodes/installation/) in the n8n community nodes documentation.
|
|
12
|
+
|
|
13
|
+
### Manual Installation
|
|
14
|
+
|
|
15
|
+
1. Clone or download this repository
|
|
16
|
+
2. In your n8n installation folder, navigate to `~/.n8n/nodes/`
|
|
17
|
+
3. Create a folder called `n8n-nodes-perfexcrm`
|
|
18
|
+
4. Copy all files from this repository into that folder
|
|
19
|
+
5. Build the node:
|
|
20
|
+
```bash
|
|
21
|
+
cd ~/.n8n/nodes/n8n-nodes-perfexcrm
|
|
22
|
+
npm install
|
|
23
|
+
npm run build
|
|
24
|
+
```
|
|
25
|
+
6. Restart n8n
|
|
26
|
+
|
|
27
|
+
## Operations
|
|
28
|
+
|
|
29
|
+
### PerfexCRM Node
|
|
30
|
+
|
|
31
|
+
This node allows you to perform CRUD operations on various PerfexCRM resources:
|
|
32
|
+
|
|
33
|
+
#### Customers
|
|
34
|
+
- Create a new customer
|
|
35
|
+
- Get a customer by ID
|
|
36
|
+
- Get all customers with filters
|
|
37
|
+
- Update a customer
|
|
38
|
+
- Delete a customer
|
|
39
|
+
|
|
40
|
+
#### Tickets
|
|
41
|
+
- Create a new ticket
|
|
42
|
+
- Get a ticket by ID
|
|
43
|
+
- Get all tickets with filters
|
|
44
|
+
- Update a ticket
|
|
45
|
+
- Delete a ticket
|
|
46
|
+
- Add a reply to a ticket
|
|
47
|
+
|
|
48
|
+
#### Invoices
|
|
49
|
+
- Create a new invoice
|
|
50
|
+
- Get an invoice by ID
|
|
51
|
+
- Get all invoices with filters
|
|
52
|
+
|
|
53
|
+
#### Leads
|
|
54
|
+
- Create a new lead
|
|
55
|
+
- Get a lead by ID
|
|
56
|
+
- Convert a lead to customer
|
|
57
|
+
|
|
58
|
+
#### Projects
|
|
59
|
+
- Create a new project
|
|
60
|
+
- Get a project by ID
|
|
61
|
+
|
|
62
|
+
#### Contracts
|
|
63
|
+
- Create a new contract
|
|
64
|
+
- Get a contract by ID
|
|
65
|
+
|
|
66
|
+
### PerfexCRM Trigger Node
|
|
67
|
+
|
|
68
|
+
This trigger node listens for webhooks from PerfexCRM and starts workflows when events occur:
|
|
69
|
+
|
|
70
|
+
#### Supported Events
|
|
71
|
+
- Customer events (created, updated, deleted)
|
|
72
|
+
- Contact events (created, updated, deleted)
|
|
73
|
+
- Lead events (created, updated, converted, deleted)
|
|
74
|
+
- Invoice events (created, updated, paid, overdue, deleted)
|
|
75
|
+
- Payment events (recorded, failed)
|
|
76
|
+
- Proposal events (created, sent, accepted, declined)
|
|
77
|
+
- Estimate events (created, sent, accepted, declined, converted)
|
|
78
|
+
- Contract events (created, signed, expiring, expired)
|
|
79
|
+
- Project events (created, updated, completed)
|
|
80
|
+
- Task events (created, updated, completed, comment added)
|
|
81
|
+
- Ticket events (created, updated, status changed, reply added, assigned, closed)
|
|
82
|
+
- Staff events (created, login)
|
|
83
|
+
- Expense events (created, updated)
|
|
84
|
+
|
|
85
|
+
## Credentials
|
|
86
|
+
|
|
87
|
+
You'll need to enter the following credentials to use this node:
|
|
88
|
+
|
|
89
|
+
1. **Base URL**: The URL of your PerfexCRM installation (e.g., `https://your-perfex.com`)
|
|
90
|
+
2. **API Key**: Your PerfexCRM API key (starts with `pk_`)
|
|
91
|
+
3. **API Version**: The API version to use (currently only `v1` is supported)
|
|
92
|
+
|
|
93
|
+
### Getting your API Key
|
|
94
|
+
|
|
95
|
+
1. Log in to your PerfexCRM admin panel
|
|
96
|
+
2. Navigate to **Setup** → **API & Webhooks**
|
|
97
|
+
3. Click on **API Keys**
|
|
98
|
+
4. Create a new API key with the appropriate permissions
|
|
99
|
+
5. Copy the API key (you'll only see it once!)
|
|
100
|
+
|
|
101
|
+
## Compatibility
|
|
102
|
+
|
|
103
|
+
- Requires n8n version 0.180.0 or later
|
|
104
|
+
- Tested with PerfexCRM 2.3.x and later
|
|
105
|
+
|
|
106
|
+
## Resources
|
|
107
|
+
|
|
108
|
+
* [n8n community nodes documentation](https://docs.n8n.io/integrations/community-nodes/)
|
|
109
|
+
* [PerfexCRM API Documentation](https://your-perfex.com/admin/api_webhooks/documentation)
|
|
110
|
+
|
|
111
|
+
## Support
|
|
112
|
+
|
|
113
|
+
For issues specific to this node, please create an issue in this repository.
|
|
114
|
+
|
|
115
|
+
For general n8n support, visit the [n8n community forum](https://community.n8n.io/).
|
|
116
|
+
|
|
117
|
+
## License
|
|
118
|
+
|
|
119
|
+
[MIT](https://github.com/your-org/n8n-nodes-perfexcrm/blob/master/LICENSE.md)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { IAuthenticateGeneric, ICredentialTestRequest, ICredentialType, INodeProperties } from 'n8n-workflow';
|
|
2
|
+
export declare class PerfexCrmApi implements ICredentialType {
|
|
3
|
+
name: string;
|
|
4
|
+
displayName: string;
|
|
5
|
+
documentationUrl: string;
|
|
6
|
+
properties: INodeProperties[];
|
|
7
|
+
authenticate: IAuthenticateGeneric;
|
|
8
|
+
test: ICredentialTestRequest;
|
|
9
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PerfexCrmApi = void 0;
|
|
4
|
+
class PerfexCrmApi {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.name = 'perfexCrmApi';
|
|
7
|
+
this.displayName = 'PerfexCRM API';
|
|
8
|
+
this.documentationUrl = 'https://github.com/your-org/n8n-nodes-perfexcrm';
|
|
9
|
+
this.properties = [
|
|
10
|
+
{
|
|
11
|
+
displayName: 'Base URL',
|
|
12
|
+
name: 'baseUrl',
|
|
13
|
+
type: 'string',
|
|
14
|
+
default: '',
|
|
15
|
+
placeholder: 'https://your-perfex-instance.com',
|
|
16
|
+
required: true,
|
|
17
|
+
description: 'The base URL of your PerfexCRM instance',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
displayName: 'API Key',
|
|
21
|
+
name: 'apiKey',
|
|
22
|
+
type: 'string',
|
|
23
|
+
typeOptions: {
|
|
24
|
+
password: true,
|
|
25
|
+
},
|
|
26
|
+
default: '',
|
|
27
|
+
required: true,
|
|
28
|
+
description: 'Your PerfexCRM API key (starts with pk_)',
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
displayName: 'API Version',
|
|
32
|
+
name: 'apiVersion',
|
|
33
|
+
type: 'options',
|
|
34
|
+
options: [
|
|
35
|
+
{
|
|
36
|
+
name: 'V1',
|
|
37
|
+
value: 'v1',
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
default: 'v1',
|
|
41
|
+
description: 'The API version to use',
|
|
42
|
+
},
|
|
43
|
+
];
|
|
44
|
+
this.authenticate = {
|
|
45
|
+
type: 'generic',
|
|
46
|
+
properties: {
|
|
47
|
+
headers: {
|
|
48
|
+
'X-API-KEY': '={{$credentials.apiKey}}',
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
this.test = {
|
|
53
|
+
request: {
|
|
54
|
+
baseURL: '={{$credentials.baseUrl}}',
|
|
55
|
+
url: '/api/{{$credentials.apiVersion}}/customers?limit=1',
|
|
56
|
+
method: 'GET',
|
|
57
|
+
},
|
|
58
|
+
rules: [
|
|
59
|
+
{
|
|
60
|
+
type: 'responseSuccessBody',
|
|
61
|
+
properties: {
|
|
62
|
+
key: 'success',
|
|
63
|
+
value: true,
|
|
64
|
+
message: 'Authentication successful!',
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.PerfexCrmApi = PerfexCrmApi;
|
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PerfexCrm = void 0;
|
|
4
|
+
const CustomerDescription_1 = require("./descriptions/CustomerDescription");
|
|
5
|
+
const TicketDescription_1 = require("./descriptions/TicketDescription");
|
|
6
|
+
const InvoiceDescription_1 = require("./descriptions/InvoiceDescription");
|
|
7
|
+
const LeadDescription_1 = require("./descriptions/LeadDescription");
|
|
8
|
+
const ProjectDescription_1 = require("./descriptions/ProjectDescription");
|
|
9
|
+
const ContractDescription_1 = require("./descriptions/ContractDescription");
|
|
10
|
+
class PerfexCrm {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.description = {
|
|
13
|
+
displayName: 'PerfexCRM',
|
|
14
|
+
name: 'perfexCrm',
|
|
15
|
+
icon: 'file:perfexcrm.svg',
|
|
16
|
+
group: ['transform'],
|
|
17
|
+
version: 1,
|
|
18
|
+
subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
|
|
19
|
+
description: 'Interact with PerfexCRM API',
|
|
20
|
+
defaults: {
|
|
21
|
+
name: 'PerfexCRM',
|
|
22
|
+
},
|
|
23
|
+
inputs: ["main" /* NodeConnectionType.Main */],
|
|
24
|
+
outputs: ["main" /* NodeConnectionType.Main */],
|
|
25
|
+
credentials: [
|
|
26
|
+
{
|
|
27
|
+
name: 'perfexCrmApi',
|
|
28
|
+
required: true,
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
properties: [
|
|
32
|
+
{
|
|
33
|
+
displayName: 'Resource',
|
|
34
|
+
name: 'resource',
|
|
35
|
+
type: 'options',
|
|
36
|
+
noDataExpression: true,
|
|
37
|
+
options: [
|
|
38
|
+
{
|
|
39
|
+
name: 'Customer',
|
|
40
|
+
value: 'customer',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
name: 'Ticket',
|
|
44
|
+
value: 'ticket',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: 'Invoice',
|
|
48
|
+
value: 'invoice',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
name: 'Lead',
|
|
52
|
+
value: 'lead',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
name: 'Project',
|
|
56
|
+
value: 'project',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
name: 'Contract',
|
|
60
|
+
value: 'contract',
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
default: 'customer',
|
|
64
|
+
},
|
|
65
|
+
...CustomerDescription_1.customerOperations,
|
|
66
|
+
...CustomerDescription_1.customerFields,
|
|
67
|
+
...TicketDescription_1.ticketOperations,
|
|
68
|
+
...TicketDescription_1.ticketFields,
|
|
69
|
+
...InvoiceDescription_1.invoiceOperations,
|
|
70
|
+
...InvoiceDescription_1.invoiceFields,
|
|
71
|
+
...LeadDescription_1.leadOperations,
|
|
72
|
+
...LeadDescription_1.leadFields,
|
|
73
|
+
...ProjectDescription_1.projectOperations,
|
|
74
|
+
...ProjectDescription_1.projectFields,
|
|
75
|
+
...ContractDescription_1.contractOperations,
|
|
76
|
+
...ContractDescription_1.contractFields,
|
|
77
|
+
],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
async execute() {
|
|
81
|
+
const items = this.getInputData();
|
|
82
|
+
const returnData = [];
|
|
83
|
+
const credentials = await this.getCredentials('perfexCrmApi');
|
|
84
|
+
const resource = this.getNodeParameter('resource', 0);
|
|
85
|
+
const operation = this.getNodeParameter('operation', 0);
|
|
86
|
+
let responseData;
|
|
87
|
+
const baseUrl = credentials.baseUrl;
|
|
88
|
+
const apiVersion = credentials.apiVersion;
|
|
89
|
+
for (let i = 0; i < items.length; i++) {
|
|
90
|
+
try {
|
|
91
|
+
if (resource === 'customer') {
|
|
92
|
+
if (operation === 'create') {
|
|
93
|
+
const company = this.getNodeParameter('company', i);
|
|
94
|
+
const additionalFields = this.getNodeParameter('additionalFields', i);
|
|
95
|
+
const body = {
|
|
96
|
+
company,
|
|
97
|
+
...additionalFields,
|
|
98
|
+
};
|
|
99
|
+
responseData = await this.helpers.request({
|
|
100
|
+
method: 'POST',
|
|
101
|
+
url: `${baseUrl}/api/${apiVersion}/customers`,
|
|
102
|
+
body,
|
|
103
|
+
json: true,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
else if (operation === 'get') {
|
|
107
|
+
const customerId = this.getNodeParameter('customerId', i);
|
|
108
|
+
responseData = await this.helpers.request({
|
|
109
|
+
method: 'GET',
|
|
110
|
+
url: `${baseUrl}/api/${apiVersion}/customers/${customerId}`,
|
|
111
|
+
json: true,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
else if (operation === 'getAll') {
|
|
115
|
+
const returnAll = this.getNodeParameter('returnAll', i);
|
|
116
|
+
const filters = this.getNodeParameter('filters', i);
|
|
117
|
+
const qs = {};
|
|
118
|
+
if (!returnAll) {
|
|
119
|
+
qs.limit = this.getNodeParameter('limit', i);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
qs.limit = 1000;
|
|
123
|
+
}
|
|
124
|
+
Object.assign(qs, filters);
|
|
125
|
+
responseData = await this.helpers.request({
|
|
126
|
+
method: 'GET',
|
|
127
|
+
url: `${baseUrl}/api/${apiVersion}/customers`,
|
|
128
|
+
qs,
|
|
129
|
+
json: true,
|
|
130
|
+
});
|
|
131
|
+
if (responseData.data) {
|
|
132
|
+
responseData = responseData.data;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else if (operation === 'update') {
|
|
136
|
+
const customerId = this.getNodeParameter('customerId', i);
|
|
137
|
+
const updateFields = this.getNodeParameter('updateFields', i);
|
|
138
|
+
const body = updateFields;
|
|
139
|
+
responseData = await this.helpers.request({
|
|
140
|
+
method: 'PUT',
|
|
141
|
+
url: `${baseUrl}/api/${apiVersion}/customers/${customerId}`,
|
|
142
|
+
body,
|
|
143
|
+
json: true,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
else if (operation === 'delete') {
|
|
147
|
+
const customerId = this.getNodeParameter('customerId', i);
|
|
148
|
+
responseData = await this.helpers.request({
|
|
149
|
+
method: 'DELETE',
|
|
150
|
+
url: `${baseUrl}/api/${apiVersion}/customers/${customerId}`,
|
|
151
|
+
json: true,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
else if (resource === 'ticket') {
|
|
156
|
+
if (operation === 'create') {
|
|
157
|
+
const subject = this.getNodeParameter('subject', i);
|
|
158
|
+
const department = this.getNodeParameter('department', i);
|
|
159
|
+
const additionalFields = this.getNodeParameter('additionalFields', i);
|
|
160
|
+
const body = {
|
|
161
|
+
subject,
|
|
162
|
+
department,
|
|
163
|
+
...additionalFields,
|
|
164
|
+
};
|
|
165
|
+
responseData = await this.helpers.request({
|
|
166
|
+
method: 'POST',
|
|
167
|
+
url: `${baseUrl}/api/${apiVersion}/tickets`,
|
|
168
|
+
body,
|
|
169
|
+
json: true,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
else if (operation === 'get') {
|
|
173
|
+
const ticketId = this.getNodeParameter('ticketId', i);
|
|
174
|
+
const options = this.getNodeParameter('options', i);
|
|
175
|
+
const qs = {};
|
|
176
|
+
if (options.includeReplies) {
|
|
177
|
+
qs.include = 'replies';
|
|
178
|
+
}
|
|
179
|
+
responseData = await this.helpers.request({
|
|
180
|
+
method: 'GET',
|
|
181
|
+
url: `${baseUrl}/api/${apiVersion}/tickets/${ticketId}`,
|
|
182
|
+
qs,
|
|
183
|
+
json: true,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
else if (operation === 'getAll') {
|
|
187
|
+
const returnAll = this.getNodeParameter('returnAll', i);
|
|
188
|
+
const filters = this.getNodeParameter('filters', i);
|
|
189
|
+
const qs = {};
|
|
190
|
+
if (!returnAll) {
|
|
191
|
+
qs.limit = this.getNodeParameter('limit', i);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
qs.limit = 1000;
|
|
195
|
+
}
|
|
196
|
+
// Handle status filter
|
|
197
|
+
if (filters.status) {
|
|
198
|
+
qs.status = filters.status;
|
|
199
|
+
}
|
|
200
|
+
if (filters.department) {
|
|
201
|
+
qs.department = filters.department;
|
|
202
|
+
}
|
|
203
|
+
if (filters.priority) {
|
|
204
|
+
qs.priority = filters.priority;
|
|
205
|
+
}
|
|
206
|
+
responseData = await this.helpers.request({
|
|
207
|
+
method: 'GET',
|
|
208
|
+
url: `${baseUrl}/api/${apiVersion}/tickets`,
|
|
209
|
+
qs,
|
|
210
|
+
json: true,
|
|
211
|
+
});
|
|
212
|
+
if (responseData.data) {
|
|
213
|
+
responseData = responseData.data;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
else if (operation === 'update') {
|
|
217
|
+
const ticketId = this.getNodeParameter('ticketId', i);
|
|
218
|
+
const updateFields = this.getNodeParameter('updateFields', i);
|
|
219
|
+
const body = updateFields;
|
|
220
|
+
responseData = await this.helpers.request({
|
|
221
|
+
method: 'PUT',
|
|
222
|
+
url: `${baseUrl}/api/${apiVersion}/tickets/${ticketId}`,
|
|
223
|
+
body,
|
|
224
|
+
json: true,
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
else if (operation === 'delete') {
|
|
228
|
+
const ticketId = this.getNodeParameter('ticketId', i);
|
|
229
|
+
responseData = await this.helpers.request({
|
|
230
|
+
method: 'DELETE',
|
|
231
|
+
url: `${baseUrl}/api/${apiVersion}/tickets/${ticketId}`,
|
|
232
|
+
json: true,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
else if (operation === 'addReply') {
|
|
236
|
+
const ticketId = this.getNodeParameter('ticketId', i);
|
|
237
|
+
const message = this.getNodeParameter('message', i);
|
|
238
|
+
const additionalFields = this.getNodeParameter('additionalFields', i);
|
|
239
|
+
const body = {
|
|
240
|
+
message,
|
|
241
|
+
...additionalFields,
|
|
242
|
+
};
|
|
243
|
+
responseData = await this.helpers.request({
|
|
244
|
+
method: 'POST',
|
|
245
|
+
url: `${baseUrl}/api/${apiVersion}/tickets/${ticketId}/replies`,
|
|
246
|
+
body,
|
|
247
|
+
json: true,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
else if (resource === 'invoice') {
|
|
252
|
+
if (operation === 'create') {
|
|
253
|
+
const clientId = this.getNodeParameter('clientId', i);
|
|
254
|
+
const number = this.getNodeParameter('number', i);
|
|
255
|
+
const date = this.getNodeParameter('date', i);
|
|
256
|
+
const duedate = this.getNodeParameter('duedate', i);
|
|
257
|
+
const additionalFields = this.getNodeParameter('additionalFields', i);
|
|
258
|
+
const body = {
|
|
259
|
+
clientid: clientId,
|
|
260
|
+
number,
|
|
261
|
+
date,
|
|
262
|
+
duedate,
|
|
263
|
+
...additionalFields,
|
|
264
|
+
};
|
|
265
|
+
responseData = await this.helpers.request({
|
|
266
|
+
method: 'POST',
|
|
267
|
+
url: `${baseUrl}/api/${apiVersion}/invoices`,
|
|
268
|
+
body,
|
|
269
|
+
json: true,
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
else if (operation === 'get') {
|
|
273
|
+
const invoiceId = this.getNodeParameter('invoiceId', i);
|
|
274
|
+
responseData = await this.helpers.request({
|
|
275
|
+
method: 'GET',
|
|
276
|
+
url: `${baseUrl}/api/${apiVersion}/invoices/${invoiceId}`,
|
|
277
|
+
json: true,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
else if (operation === 'getAll') {
|
|
281
|
+
const returnAll = this.getNodeParameter('returnAll', i);
|
|
282
|
+
const filters = this.getNodeParameter('filters', i);
|
|
283
|
+
const qs = {};
|
|
284
|
+
if (!returnAll) {
|
|
285
|
+
qs.limit = this.getNodeParameter('limit', i);
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
qs.limit = 1000;
|
|
289
|
+
}
|
|
290
|
+
Object.assign(qs, filters);
|
|
291
|
+
responseData = await this.helpers.request({
|
|
292
|
+
method: 'GET',
|
|
293
|
+
url: `${baseUrl}/api/${apiVersion}/invoices`,
|
|
294
|
+
qs,
|
|
295
|
+
json: true,
|
|
296
|
+
});
|
|
297
|
+
if (responseData.data) {
|
|
298
|
+
responseData = responseData.data;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
else if (resource === 'lead') {
|
|
303
|
+
if (operation === 'create') {
|
|
304
|
+
const name = this.getNodeParameter('name', i);
|
|
305
|
+
const additionalFields = this.getNodeParameter('additionalFields', i);
|
|
306
|
+
const body = {
|
|
307
|
+
name,
|
|
308
|
+
...additionalFields,
|
|
309
|
+
};
|
|
310
|
+
responseData = await this.helpers.request({
|
|
311
|
+
method: 'POST',
|
|
312
|
+
url: `${baseUrl}/api/${apiVersion}/leads`,
|
|
313
|
+
body,
|
|
314
|
+
json: true,
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
else if (operation === 'get') {
|
|
318
|
+
const leadId = this.getNodeParameter('leadId', i);
|
|
319
|
+
responseData = await this.helpers.request({
|
|
320
|
+
method: 'GET',
|
|
321
|
+
url: `${baseUrl}/api/${apiVersion}/leads/${leadId}`,
|
|
322
|
+
json: true,
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
else if (operation === 'convert') {
|
|
326
|
+
const leadId = this.getNodeParameter('leadId', i);
|
|
327
|
+
responseData = await this.helpers.request({
|
|
328
|
+
method: 'POST',
|
|
329
|
+
url: `${baseUrl}/api/${apiVersion}/leads/${leadId}/convert`,
|
|
330
|
+
json: true,
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
else if (resource === 'project') {
|
|
335
|
+
if (operation === 'create') {
|
|
336
|
+
const name = this.getNodeParameter('name', i);
|
|
337
|
+
const clientId = this.getNodeParameter('clientId', i);
|
|
338
|
+
const additionalFields = this.getNodeParameter('additionalFields', i);
|
|
339
|
+
const body = {
|
|
340
|
+
name,
|
|
341
|
+
clientid: clientId,
|
|
342
|
+
...additionalFields,
|
|
343
|
+
};
|
|
344
|
+
responseData = await this.helpers.request({
|
|
345
|
+
method: 'POST',
|
|
346
|
+
url: `${baseUrl}/api/${apiVersion}/projects`,
|
|
347
|
+
body,
|
|
348
|
+
json: true,
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
else if (operation === 'get') {
|
|
352
|
+
const projectId = this.getNodeParameter('projectId', i);
|
|
353
|
+
responseData = await this.helpers.request({
|
|
354
|
+
method: 'GET',
|
|
355
|
+
url: `${baseUrl}/api/${apiVersion}/projects/${projectId}`,
|
|
356
|
+
json: true,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
else if (resource === 'contract') {
|
|
361
|
+
if (operation === 'create') {
|
|
362
|
+
const subject = this.getNodeParameter('subject', i);
|
|
363
|
+
const client = this.getNodeParameter('client', i);
|
|
364
|
+
const datestart = this.getNodeParameter('datestart', i);
|
|
365
|
+
const dateend = this.getNodeParameter('dateend', i);
|
|
366
|
+
const additionalFields = this.getNodeParameter('additionalFields', i);
|
|
367
|
+
const body = {
|
|
368
|
+
subject,
|
|
369
|
+
client,
|
|
370
|
+
datestart,
|
|
371
|
+
dateend,
|
|
372
|
+
...additionalFields,
|
|
373
|
+
};
|
|
374
|
+
responseData = await this.helpers.request({
|
|
375
|
+
method: 'POST',
|
|
376
|
+
url: `${baseUrl}/api/${apiVersion}/contracts`,
|
|
377
|
+
body,
|
|
378
|
+
json: true,
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
else if (operation === 'get') {
|
|
382
|
+
const contractId = this.getNodeParameter('contractId', i);
|
|
383
|
+
responseData = await this.helpers.request({
|
|
384
|
+
method: 'GET',
|
|
385
|
+
url: `${baseUrl}/api/${apiVersion}/contracts/${contractId}`,
|
|
386
|
+
json: true,
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
if (Array.isArray(responseData)) {
|
|
391
|
+
returnData.push(...responseData.map((item) => ({ json: item })));
|
|
392
|
+
}
|
|
393
|
+
else {
|
|
394
|
+
returnData.push({ json: responseData });
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
catch (error) {
|
|
398
|
+
if (this.continueOnFail()) {
|
|
399
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
400
|
+
returnData.push({ json: { error: errorMessage } });
|
|
401
|
+
continue;
|
|
402
|
+
}
|
|
403
|
+
throw error;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return [returnData];
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
exports.PerfexCrm = PerfexCrm;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { IHookFunctions, IWebhookFunctions, INodeType, INodeTypeDescription, IWebhookResponseData } from 'n8n-workflow';
|
|
2
|
+
export declare class PerfexCrmTrigger implements INodeType {
|
|
3
|
+
description: INodeTypeDescription;
|
|
4
|
+
webhookMethods: {
|
|
5
|
+
default: {
|
|
6
|
+
checkExists(this: IHookFunctions): Promise<boolean>;
|
|
7
|
+
create(this: IHookFunctions): Promise<boolean>;
|
|
8
|
+
delete(this: IHookFunctions): Promise<boolean>;
|
|
9
|
+
};
|
|
10
|
+
};
|
|
11
|
+
webhook(this: IWebhookFunctions): Promise<IWebhookResponseData>;
|
|
12
|
+
}
|