@upazambuja/n8n-nodes-agendamento-saas 1.0.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/README.md ADDED
@@ -0,0 +1,301 @@
1
+ # n8n-nodes-agendamento-saas
2
+
3
+ ![n8n.io - Workflow Automation](https://raw.githubusercontent.com/n8n-io/n8n/master/assets/n8n-logo.png)
4
+
5
+ Nó personalizado para n8n que integra com o sistema **Agendamento SaaS** - uma plataforma completa de agendamento com WhatsApp e IA.
6
+
7
+ ## 🚀 Funcionalidades
8
+
9
+ ### 📅 Agendamentos
10
+ - ✅ **Criar** novos agendamentos
11
+ - ✅ **Buscar** agendamentos por ID
12
+ - ✅ **Listar** todos os agendamentos
13
+ - ✅ **Atualizar** status de agendamentos
14
+ - ✅ **Reagendar** agendamentos existentes
15
+ - ✅ **Cancelar** agendamentos (soft delete)
16
+ - ✅ **Excluir** agendamentos permanentemente
17
+ - ✅ **Buscar horários disponíveis** por período
18
+
19
+ ### 💼 Serviços
20
+ - ✅ **Listar** todos os serviços
21
+ - ✅ **Buscar** serviço por ID
22
+ - ✅ **Criar** novos serviços
23
+ - ✅ **Atualizar** serviços existentes
24
+ - ✅ **Excluir** serviços (soft delete)
25
+
26
+ ### ⏰ Horários
27
+ - ✅ **Buscar horários disponíveis** por data
28
+ - ✅ **Verificar disponibilidade específica** (data + hora)
29
+ - ✅ **Listar configuração** de horários de funcionamento
30
+ - ✅ **Validação automática** de conflitos
31
+
32
+ ### 📱 WhatsApp
33
+ - ✅ Enviar mensagens de texto
34
+ - ✅ Enviar áudios (text-to-speech)
35
+ - ✅ Verificar status da instância
36
+ - ✅ Integração nativa com Baileys
37
+
38
+ ### 🤖 Inteligência Artificial
39
+ - ✅ Processar mensagens com IA
40
+ - ✅ Gerar respostas personalizadas
41
+ - ✅ Suporte a Groq, Mistral e OpenAI
42
+ - ✅ Análise de linguagem natural
43
+
44
+ ## 📦 Instalação
45
+
46
+ ### Via npm (Recomendado)
47
+ ```bash
48
+ npm install n8n-nodes-agendamento-saas
49
+ ```
50
+
51
+ ### Via n8n Community Nodes
52
+ 1. Abra seu n8n
53
+ 2. Vá em **Settings** → **Community Nodes**
54
+ 3. Clique em **Install**
55
+ 4. Digite: `n8n-nodes-agendamento-saas`
56
+ 5. Clique em **Install**
57
+
58
+ ## ⚙️ Configuração
59
+
60
+ ### 1. Credenciais
61
+ Antes de usar o nó, configure suas credenciais:
62
+
63
+ 1. **API URL**: URL base do seu sistema (ex: `https://seu-dominio.com`)
64
+ 2. **API Key**: Chave de API para autenticação
65
+ 3. **Empresa ID**: ID da sua empresa no sistema
66
+
67
+ ### 2. Endpoints da API
68
+ Certifique-se de que sua API tenha os seguintes endpoints:
69
+
70
+ ```
71
+ # Teste de conexão
72
+ GET /api/test-connection
73
+
74
+ # Agendamentos
75
+ POST /api/agendamentos # Criar agendamento
76
+ GET /api/agendamentos # Listar agendamentos
77
+ GET /api/agendamentos/{id} # Buscar agendamento
78
+ PUT /api/agendamentos/{id} # Atualizar agendamento
79
+ PUT /api/agendamentos/{id}/reschedule # Reagendar agendamento
80
+ PUT /api/agendamentos/{id}/cancel # Cancelar agendamento
81
+ DELETE /api/agendamentos/{id} # Excluir agendamento
82
+
83
+ # Serviços
84
+ GET /api/servicos # Listar serviços
85
+ GET /api/servicos/{id} # Buscar serviço
86
+ POST /api/servicos # Criar serviço
87
+ PUT /api/servicos/{id} # Atualizar serviço
88
+ DELETE /api/servicos/{id} # Excluir serviço
89
+
90
+ # Horários
91
+ GET /api/horarios-disponiveis # Buscar horários disponíveis
92
+ GET /api/horarios-configuracao # Configuração de horários
93
+ GET /api/verificar-disponibilidade # Verificar disponibilidade específica
94
+
95
+ # WhatsApp
96
+ POST /api/whatsapp/send-message # Enviar mensagem
97
+ POST /api/whatsapp/send-audio # Enviar áudio
98
+ GET /api/whatsapp/status # Status da instância
99
+
100
+ # IA
101
+ POST /api/ia/process-message # Processar com IA
102
+ POST /api/ia/generate-response # Gerar resposta
103
+ ```
104
+
105
+ ## 🎯 Casos de Uso
106
+
107
+ ### 1. Automação de Agendamentos
108
+ ```
109
+ Trigger: Webhook (formulário web)
110
+
111
+ Agendamento SaaS: Criar agendamento
112
+
113
+ Agendamento SaaS: Enviar confirmação via WhatsApp
114
+ ```
115
+
116
+ ### 2. Lembretes Automáticos
117
+ ```
118
+ Trigger: Cron (diário às 9h)
119
+
120
+ Agendamento SaaS: Listar agendamentos do dia
121
+
122
+ Agendamento SaaS: Enviar lembrete via WhatsApp
123
+ ```
124
+
125
+ ### 3. Chatbot Inteligente
126
+ ```
127
+ Trigger: Webhook (WhatsApp)
128
+
129
+ Agendamento SaaS: Processar mensagem com IA
130
+
131
+ Agendamento SaaS: Criar agendamento (se necessário)
132
+
133
+ Agendamento SaaS: Enviar resposta personalizada
134
+ ```
135
+
136
+ ### 4. Integração com CRM
137
+ ```
138
+ Trigger: Novo lead no CRM
139
+
140
+ Agendamento SaaS: Criar agendamento
141
+
142
+ Agendamento SaaS: Enviar mensagem de boas-vindas
143
+
144
+ CRM: Atualizar status do lead
145
+ ```
146
+
147
+ ## 📋 Exemplos de Workflow
148
+
149
+ ### Exemplo 1: Agendamento Simples
150
+ ```json
151
+ {
152
+ "nodes": [
153
+ {
154
+ "name": "Webhook",
155
+ "type": "n8n-nodes-base.webhook"
156
+ },
157
+ {
158
+ "name": "Criar Agendamento",
159
+ "type": "n8n-nodes-agendamento-saas.agendamentoSaas",
160
+ "parameters": {
161
+ "resource": "agendamento",
162
+ "operation": "create",
163
+ "clienteNome": "={{$node['Webhook'].json['nome']}}",
164
+ "clienteTelefone": "={{$node['Webhook'].json['telefone']}}",
165
+ "servicoId": 1,
166
+ "dataAgendamento": "={{$node['Webhook'].json['data']}}"
167
+ }
168
+ },
169
+ {
170
+ "name": "Enviar Confirmação",
171
+ "type": "n8n-nodes-agendamento-saas.agendamentoSaas",
172
+ "parameters": {
173
+ "resource": "whatsapp",
174
+ "operation": "sendMessage",
175
+ "telefone": "={{$node['Webhook'].json['telefone']}}",
176
+ "mensagem": "Olá {{$node['Webhook'].json['nome']}}! Seu agendamento foi confirmado para {{$node['Webhook'].json['data']}}. Obrigado!"
177
+ }
178
+ }
179
+ ]
180
+ }
181
+ ```
182
+
183
+ ### Exemplo 2: Processamento com IA
184
+ ```json
185
+ {
186
+ "nodes": [
187
+ {
188
+ "name": "Webhook WhatsApp",
189
+ "type": "n8n-nodes-base.webhook"
190
+ },
191
+ {
192
+ "name": "Processar com IA",
193
+ "type": "n8n-nodes-agendamento-saas.agendamentoSaas",
194
+ "parameters": {
195
+ "resource": "ia",
196
+ "operation": "processMessage",
197
+ "mensagemCliente": "={{$node['Webhook WhatsApp'].json['message']}}",
198
+ "nomeCliente": "={{$node['Webhook WhatsApp'].json['pushName']}}"
199
+ }
200
+ },
201
+ {
202
+ "name": "Enviar Resposta",
203
+ "type": "n8n-nodes-agendamento-saas.agendamentoSaas",
204
+ "parameters": {
205
+ "resource": "whatsapp",
206
+ "operation": "sendMessage",
207
+ "telefone": "={{$node['Webhook WhatsApp'].json['from']}}",
208
+ "mensagem": "={{$node['Processar com IA'].json['resposta_cliente']}}"
209
+ }
210
+ }
211
+ ]
212
+ }
213
+ ```
214
+
215
+ ## 🔧 Desenvolvimento
216
+
217
+ ### Pré-requisitos
218
+ - Node.js 16+
219
+ - TypeScript
220
+ - n8n instalado
221
+
222
+ ### Setup Local
223
+ ```bash
224
+ # Clone o repositório
225
+ git clone https://github.com/seu-usuario/n8n-nodes-agendamento-saas.git
226
+ cd n8n-nodes-agendamento-saas
227
+
228
+ # Instale dependências
229
+ npm install
230
+
231
+ # Build
232
+ npm run build
233
+
234
+ # Link para desenvolvimento local
235
+ npm link
236
+ cd ~/.n8n/nodes
237
+ npm link n8n-nodes-agendamento-saas
238
+ ```
239
+
240
+ ### Scripts Disponíveis
241
+ ```bash
242
+ npm run build # Compilar TypeScript
243
+ npm run dev # Modo desenvolvimento
244
+ npm run lint # Verificar código
245
+ npm run format # Formatar código
246
+ ```
247
+
248
+ ## 📚 Documentação da API
249
+
250
+ ### Estrutura de Resposta
251
+ ```json
252
+ {
253
+ "success": true,
254
+ "data": {
255
+ "id": 123,
256
+ "cliente_nome": "João Silva",
257
+ "cliente_telefone": "5521999999999",
258
+ "data_agendamento": "2024-02-05",
259
+ "hora_agendamento": "14:30:00",
260
+ "status": "agendado"
261
+ },
262
+ "message": "Agendamento criado com sucesso"
263
+ }
264
+ ```
265
+
266
+ ### Códigos de Status
267
+ - `200` - Sucesso
268
+ - `201` - Criado com sucesso
269
+ - `400` - Erro de validação
270
+ - `401` - Não autorizado
271
+ - `404` - Não encontrado
272
+ - `500` - Erro interno
273
+
274
+ ## 🤝 Contribuição
275
+
276
+ 1. Fork o projeto
277
+ 2. Crie uma branch para sua feature (`git checkout -b feature/AmazingFeature`)
278
+ 3. Commit suas mudanças (`git commit -m 'Add some AmazingFeature'`)
279
+ 4. Push para a branch (`git push origin feature/AmazingFeature`)
280
+ 5. Abra um Pull Request
281
+
282
+ ## 📄 Licença
283
+
284
+ Este projeto está sob a licença MIT. Veja o arquivo [LICENSE](LICENSE) para detalhes.
285
+
286
+ ## 🆘 Suporte
287
+
288
+ - 📧 Email: seu-email@exemplo.com
289
+ - 💬 Discord: [Link do Discord]
290
+ - 📖 Documentação: [Link da Documentação]
291
+ - 🐛 Issues: [GitHub Issues](https://github.com/seu-usuario/n8n-nodes-agendamento-saas/issues)
292
+
293
+ ## 🎉 Agradecimentos
294
+
295
+ - [n8n.io](https://n8n.io) pela plataforma incrível
296
+ - Comunidade n8n pelo suporte
297
+ - Contribuidores do projeto
298
+
299
+ ---
300
+
301
+ **Feito com ❤️ para a comunidade n8n**
@@ -0,0 +1,52 @@
1
+ export declare class AgendamentoSaasApi {
2
+ name: string;
3
+ displayName: string;
4
+ documentationUrl: string;
5
+ properties: ({
6
+ displayName: string;
7
+ name: string;
8
+ type: string;
9
+ default: string;
10
+ placeholder: string;
11
+ description: string;
12
+ required: boolean;
13
+ typeOptions?: undefined;
14
+ } | {
15
+ displayName: string;
16
+ name: string;
17
+ type: string;
18
+ typeOptions: {
19
+ password: boolean;
20
+ };
21
+ default: string;
22
+ placeholder: string;
23
+ description: string;
24
+ required: boolean;
25
+ } | {
26
+ displayName: string;
27
+ name: string;
28
+ type: string;
29
+ default: number;
30
+ description: string;
31
+ required: boolean;
32
+ placeholder?: undefined;
33
+ typeOptions?: undefined;
34
+ })[];
35
+ authenticate: {
36
+ type: string;
37
+ properties: {
38
+ headers: {
39
+ Authorization: string;
40
+ 'X-Empresa-ID': string;
41
+ 'Content-Type': string;
42
+ };
43
+ };
44
+ };
45
+ test: {
46
+ request: {
47
+ baseURL: string;
48
+ url: string;
49
+ method: string;
50
+ };
51
+ };
52
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AgendamentoSaasApi = void 0;
4
+ class AgendamentoSaasApi {
5
+ constructor() {
6
+ this.name = 'agendamentoSaasApi';
7
+ this.displayName = 'Agendamento SaaS API';
8
+ this.documentationUrl = 'https://github.com/seu-usuario/n8n-nodes-agendamento-saas';
9
+ this.properties = [
10
+ {
11
+ displayName: 'API URL',
12
+ name: 'apiUrl',
13
+ type: 'string',
14
+ default: 'https://seu-dominio.com',
15
+ placeholder: 'https://seu-dominio.com',
16
+ description: 'URL base da sua API do Agendamento SaaS',
17
+ required: true,
18
+ },
19
+ {
20
+ displayName: 'API Key',
21
+ name: 'apiKey',
22
+ type: 'string',
23
+ typeOptions: {
24
+ password: true,
25
+ },
26
+ default: '',
27
+ placeholder: 'sua-api-key-aqui',
28
+ description: 'Chave de API para autenticação',
29
+ required: true,
30
+ },
31
+ {
32
+ displayName: 'Empresa ID',
33
+ name: 'empresaId',
34
+ type: 'number',
35
+ default: 1,
36
+ description: 'ID da empresa no sistema',
37
+ required: true,
38
+ },
39
+ ];
40
+ this.authenticate = {
41
+ type: 'generic',
42
+ properties: {
43
+ headers: {
44
+ 'Authorization': '=Bearer {{$credentials.apiKey}}',
45
+ 'X-Empresa-ID': '={{$credentials.empresaId}}',
46
+ 'Content-Type': 'application/json',
47
+ },
48
+ },
49
+ };
50
+ this.test = {
51
+ request: {
52
+ baseURL: '={{$credentials.apiUrl}}',
53
+ url: '/api/test-connection',
54
+ method: 'GET',
55
+ },
56
+ };
57
+ }
58
+ }
59
+ exports.AgendamentoSaasApi = AgendamentoSaasApi;
@@ -0,0 +1,137 @@
1
+ export declare class AgendamentoSaas {
2
+ description: {
3
+ displayName: string;
4
+ name: string;
5
+ icon: string;
6
+ group: string[];
7
+ version: number;
8
+ subtitle: string;
9
+ description: string;
10
+ defaults: {
11
+ name: string;
12
+ };
13
+ inputs: string[];
14
+ outputs: string[];
15
+ credentials: {
16
+ name: string;
17
+ required: boolean;
18
+ }[];
19
+ properties: ({
20
+ displayName: string;
21
+ name: string;
22
+ type: string;
23
+ noDataExpression: boolean;
24
+ options: {
25
+ name: string;
26
+ value: string;
27
+ }[];
28
+ default: string;
29
+ displayOptions?: undefined;
30
+ required?: undefined;
31
+ description?: undefined;
32
+ placeholder?: undefined;
33
+ } | {
34
+ displayName: string;
35
+ name: string;
36
+ type: string;
37
+ noDataExpression: boolean;
38
+ displayOptions: {
39
+ show: {
40
+ resource: string[];
41
+ operation?: undefined;
42
+ };
43
+ };
44
+ options: {
45
+ name: string;
46
+ value: string;
47
+ description: string;
48
+ action: string;
49
+ }[];
50
+ default: string;
51
+ required?: undefined;
52
+ description?: undefined;
53
+ placeholder?: undefined;
54
+ } | {
55
+ displayName: string;
56
+ name: string;
57
+ type: string;
58
+ required: boolean;
59
+ displayOptions: {
60
+ show: {
61
+ resource: string[];
62
+ operation: string[];
63
+ };
64
+ };
65
+ default: string;
66
+ description: string;
67
+ noDataExpression?: undefined;
68
+ options?: undefined;
69
+ placeholder?: undefined;
70
+ } | {
71
+ displayName: string;
72
+ name: string;
73
+ type: string;
74
+ required: boolean;
75
+ displayOptions: {
76
+ show: {
77
+ resource: string[];
78
+ operation: string[];
79
+ };
80
+ };
81
+ default: number;
82
+ description: string;
83
+ noDataExpression?: undefined;
84
+ options?: undefined;
85
+ placeholder?: undefined;
86
+ } | {
87
+ displayName: string;
88
+ name: string;
89
+ type: string;
90
+ displayOptions: {
91
+ show: {
92
+ resource: string[];
93
+ operation: string[];
94
+ };
95
+ };
96
+ default: string;
97
+ description: string;
98
+ noDataExpression?: undefined;
99
+ options?: undefined;
100
+ required?: undefined;
101
+ placeholder?: undefined;
102
+ } | {
103
+ displayName: string;
104
+ name: string;
105
+ type: string;
106
+ displayOptions: {
107
+ show: {
108
+ resource: string[];
109
+ operation: string[];
110
+ };
111
+ };
112
+ default: number;
113
+ description: string;
114
+ noDataExpression?: undefined;
115
+ options?: undefined;
116
+ required?: undefined;
117
+ placeholder?: undefined;
118
+ } | {
119
+ displayName: string;
120
+ name: string;
121
+ type: string;
122
+ displayOptions: {
123
+ show: {
124
+ resource: string[];
125
+ operation: string[];
126
+ };
127
+ };
128
+ default: string;
129
+ placeholder: string;
130
+ description: string;
131
+ noDataExpression?: undefined;
132
+ options?: undefined;
133
+ required?: undefined;
134
+ })[];
135
+ };
136
+ execute(executeFunctions: any): Promise<any[][]>;
137
+ }
@@ -0,0 +1,626 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AgendamentoSaas = void 0;
4
+ const GenericFunctions_1 = require("./GenericFunctions");
5
+ class AgendamentoSaas {
6
+ constructor() {
7
+ this.description = {
8
+ displayName: 'Agendamento SaaS',
9
+ name: 'agendamentoSaas',
10
+ icon: 'file:agendamento.svg',
11
+ group: ['transform'],
12
+ version: 1,
13
+ subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
14
+ description: 'Integração com sistema de agendamento SaaS com WhatsApp e IA',
15
+ defaults: {
16
+ name: 'Agendamento SaaS',
17
+ },
18
+ inputs: ['main'],
19
+ outputs: ['main'],
20
+ credentials: [
21
+ {
22
+ name: 'agendamentoSaasApi',
23
+ required: true,
24
+ },
25
+ ],
26
+ properties: [
27
+ {
28
+ displayName: 'Resource',
29
+ name: 'resource',
30
+ type: 'options',
31
+ noDataExpression: true,
32
+ options: [
33
+ {
34
+ name: 'Agendamento',
35
+ value: 'agendamento',
36
+ },
37
+ {
38
+ name: 'Serviço',
39
+ value: 'servico',
40
+ },
41
+ {
42
+ name: 'Horário',
43
+ value: 'horario',
44
+ },
45
+ {
46
+ name: 'WhatsApp',
47
+ value: 'whatsapp',
48
+ },
49
+ {
50
+ name: 'IA',
51
+ value: 'ia',
52
+ },
53
+ ],
54
+ default: 'agendamento',
55
+ },
56
+ // AGENDAMENTO OPERATIONS
57
+ {
58
+ displayName: 'Operation',
59
+ name: 'operation',
60
+ type: 'options',
61
+ noDataExpression: true,
62
+ displayOptions: {
63
+ show: {
64
+ resource: ['agendamento'],
65
+ },
66
+ },
67
+ options: [
68
+ {
69
+ name: 'Create',
70
+ value: 'create',
71
+ description: 'Criar novo agendamento',
72
+ action: 'Create an agendamento',
73
+ },
74
+ {
75
+ name: 'Get',
76
+ value: 'get',
77
+ description: 'Buscar agendamento por ID',
78
+ action: 'Get an agendamento',
79
+ },
80
+ {
81
+ name: 'Get All',
82
+ value: 'getAll',
83
+ description: 'Listar todos os agendamentos',
84
+ action: 'Get all agendamentos',
85
+ },
86
+ {
87
+ name: 'Update',
88
+ value: 'update',
89
+ description: 'Atualizar agendamento',
90
+ action: 'Update an agendamento',
91
+ },
92
+ {
93
+ name: 'Reschedule',
94
+ value: 'reschedule',
95
+ description: 'Reagendar agendamento',
96
+ action: 'Reschedule an agendamento',
97
+ },
98
+ {
99
+ name: 'Cancel',
100
+ value: 'cancel',
101
+ description: 'Cancelar agendamento',
102
+ action: 'Cancel an agendamento',
103
+ },
104
+ {
105
+ name: 'Delete',
106
+ value: 'delete',
107
+ description: 'Excluir agendamento permanentemente',
108
+ action: 'Delete an agendamento',
109
+ },
110
+ ],
111
+ default: 'create',
112
+ },
113
+ // SERVICO OPERATIONS
114
+ {
115
+ displayName: 'Operation',
116
+ name: 'operation',
117
+ type: 'options',
118
+ noDataExpression: true,
119
+ displayOptions: {
120
+ show: {
121
+ resource: ['servico'],
122
+ },
123
+ },
124
+ options: [
125
+ {
126
+ name: 'Get All',
127
+ value: 'getAll',
128
+ description: 'Listar todos os serviços',
129
+ action: 'Get all servicos',
130
+ },
131
+ {
132
+ name: 'Get',
133
+ value: 'get',
134
+ description: 'Buscar serviço por ID',
135
+ action: 'Get a servico',
136
+ },
137
+ {
138
+ name: 'Create',
139
+ value: 'create',
140
+ description: 'Criar novo serviço',
141
+ action: 'Create a servico',
142
+ },
143
+ {
144
+ name: 'Update',
145
+ value: 'update',
146
+ description: 'Atualizar serviço',
147
+ action: 'Update a servico',
148
+ },
149
+ {
150
+ name: 'Delete',
151
+ value: 'delete',
152
+ description: 'Excluir serviço',
153
+ action: 'Delete a servico',
154
+ },
155
+ ],
156
+ default: 'getAll',
157
+ },
158
+ // HORARIO OPERATIONS
159
+ {
160
+ displayName: 'Operation',
161
+ name: 'operation',
162
+ type: 'options',
163
+ noDataExpression: true,
164
+ displayOptions: {
165
+ show: {
166
+ resource: ['horario'],
167
+ },
168
+ },
169
+ options: [
170
+ {
171
+ name: 'Get Available',
172
+ value: 'getAvailable',
173
+ description: 'Buscar horários disponíveis',
174
+ action: 'Get available horarios',
175
+ },
176
+ {
177
+ name: 'Check Availability',
178
+ value: 'checkAvailability',
179
+ description: 'Verificar disponibilidade específica',
180
+ action: 'Check horario availability',
181
+ },
182
+ ],
183
+ default: 'getAvailable',
184
+ },
185
+ // WHATSAPP OPERATIONS
186
+ {
187
+ displayName: 'Operation',
188
+ name: 'operation',
189
+ type: 'options',
190
+ noDataExpression: true,
191
+ displayOptions: {
192
+ show: {
193
+ resource: ['whatsapp'],
194
+ },
195
+ },
196
+ options: [
197
+ {
198
+ name: 'Send Message',
199
+ value: 'sendMessage',
200
+ description: 'Enviar mensagem via WhatsApp',
201
+ action: 'Send a WhatsApp message',
202
+ },
203
+ {
204
+ name: 'Send Audio',
205
+ value: 'sendAudio',
206
+ description: 'Enviar áudio via WhatsApp',
207
+ action: 'Send WhatsApp audio',
208
+ },
209
+ {
210
+ name: 'Get Status',
211
+ value: 'getStatus',
212
+ description: 'Verificar status da instância',
213
+ action: 'Get WhatsApp status',
214
+ },
215
+ ],
216
+ default: 'sendMessage',
217
+ },
218
+ // IA OPERATIONS
219
+ {
220
+ displayName: 'Operation',
221
+ name: 'operation',
222
+ type: 'options',
223
+ noDataExpression: true,
224
+ displayOptions: {
225
+ show: {
226
+ resource: ['ia'],
227
+ },
228
+ },
229
+ options: [
230
+ {
231
+ name: 'Process Message',
232
+ value: 'processMessage',
233
+ description: 'Processar mensagem com IA',
234
+ action: 'Process message with AI',
235
+ },
236
+ {
237
+ name: 'Generate Response',
238
+ value: 'generateResponse',
239
+ description: 'Gerar resposta personalizada',
240
+ action: 'Generate AI response',
241
+ },
242
+ ],
243
+ default: 'processMessage',
244
+ },
245
+ // AGENDAMENTO FIELDS
246
+ {
247
+ displayName: 'Cliente Nome',
248
+ name: 'clienteNome',
249
+ type: 'string',
250
+ required: true,
251
+ displayOptions: {
252
+ show: {
253
+ resource: ['agendamento'],
254
+ operation: ['create'],
255
+ },
256
+ },
257
+ default: '',
258
+ description: 'Nome do cliente',
259
+ },
260
+ {
261
+ displayName: 'Cliente Telefone',
262
+ name: 'clienteTelefone',
263
+ type: 'string',
264
+ required: true,
265
+ displayOptions: {
266
+ show: {
267
+ resource: ['agendamento'],
268
+ operation: ['create'],
269
+ },
270
+ },
271
+ default: '',
272
+ description: 'Telefone do cliente (formato: 5521999999999)',
273
+ },
274
+ {
275
+ displayName: 'Serviço ID',
276
+ name: 'servicoId',
277
+ type: 'number',
278
+ required: true,
279
+ displayOptions: {
280
+ show: {
281
+ resource: ['agendamento'],
282
+ operation: ['create'],
283
+ },
284
+ },
285
+ default: 1,
286
+ description: 'ID do serviço a ser agendado',
287
+ },
288
+ {
289
+ displayName: 'Data',
290
+ name: 'dataAgendamento',
291
+ type: 'dateTime',
292
+ required: true,
293
+ displayOptions: {
294
+ show: {
295
+ resource: ['agendamento'],
296
+ operation: ['create'],
297
+ },
298
+ },
299
+ default: '',
300
+ description: 'Data e hora do agendamento',
301
+ },
302
+ {
303
+ displayName: 'Observações',
304
+ name: 'observacoes',
305
+ type: 'string',
306
+ displayOptions: {
307
+ show: {
308
+ resource: ['agendamento'],
309
+ operation: ['create'],
310
+ },
311
+ },
312
+ default: '',
313
+ description: 'Observações adicionais',
314
+ },
315
+ // REAGENDAMENTO FIELDS
316
+ {
317
+ displayName: 'Nova Data',
318
+ name: 'novaDataAgendamento',
319
+ type: 'dateTime',
320
+ required: true,
321
+ displayOptions: {
322
+ show: {
323
+ resource: ['agendamento'],
324
+ operation: ['reschedule'],
325
+ },
326
+ },
327
+ default: '',
328
+ description: 'Nova data e hora do agendamento',
329
+ },
330
+ {
331
+ displayName: 'Motivo do Reagendamento',
332
+ name: 'motivoReagendamento',
333
+ type: 'string',
334
+ displayOptions: {
335
+ show: {
336
+ resource: ['agendamento'],
337
+ operation: ['reschedule'],
338
+ },
339
+ },
340
+ default: '',
341
+ description: 'Motivo do reagendamento (opcional)',
342
+ },
343
+ // HORARIO FIELDS
344
+ {
345
+ displayName: 'Data',
346
+ name: 'dataHorario',
347
+ type: 'dateTime',
348
+ required: true,
349
+ displayOptions: {
350
+ show: {
351
+ resource: ['horario'],
352
+ operation: ['getAvailable', 'checkAvailability'],
353
+ },
354
+ },
355
+ default: '',
356
+ description: 'Data para verificar disponibilidade',
357
+ },
358
+ {
359
+ displayName: 'Serviço ID',
360
+ name: 'servicoIdHorario',
361
+ type: 'number',
362
+ displayOptions: {
363
+ show: {
364
+ resource: ['horario'],
365
+ operation: ['getAvailable', 'checkAvailability'],
366
+ },
367
+ },
368
+ default: 0,
369
+ description: 'ID do serviço (opcional)',
370
+ },
371
+ {
372
+ displayName: 'Hora Específica',
373
+ name: 'horaEspecifica',
374
+ type: 'string',
375
+ displayOptions: {
376
+ show: {
377
+ resource: ['horario'],
378
+ operation: ['checkAvailability'],
379
+ },
380
+ },
381
+ default: '',
382
+ placeholder: '14:30',
383
+ description: 'Hora específica para verificar (formato HH:MM)',
384
+ },
385
+ // WHATSAPP FIELDS
386
+ {
387
+ displayName: 'Telefone',
388
+ name: 'telefone',
389
+ type: 'string',
390
+ required: true,
391
+ displayOptions: {
392
+ show: {
393
+ resource: ['whatsapp'],
394
+ operation: ['sendMessage', 'sendAudio'],
395
+ },
396
+ },
397
+ default: '',
398
+ description: 'Número do telefone (formato: 5521999999999)',
399
+ },
400
+ {
401
+ displayName: 'Mensagem',
402
+ name: 'mensagem',
403
+ type: 'string',
404
+ required: true,
405
+ displayOptions: {
406
+ show: {
407
+ resource: ['whatsapp'],
408
+ operation: ['sendMessage'],
409
+ },
410
+ },
411
+ default: '',
412
+ description: 'Texto da mensagem',
413
+ },
414
+ {
415
+ displayName: 'Texto para Áudio',
416
+ name: 'textoAudio',
417
+ type: 'string',
418
+ required: true,
419
+ displayOptions: {
420
+ show: {
421
+ resource: ['whatsapp'],
422
+ operation: ['sendAudio'],
423
+ },
424
+ },
425
+ default: '',
426
+ description: 'Texto que será convertido em áudio',
427
+ },
428
+ // IA FIELDS
429
+ {
430
+ displayName: 'Mensagem do Cliente',
431
+ name: 'mensagemCliente',
432
+ type: 'string',
433
+ required: true,
434
+ displayOptions: {
435
+ show: {
436
+ resource: ['ia'],
437
+ operation: ['processMessage', 'generateResponse'],
438
+ },
439
+ },
440
+ default: '',
441
+ description: 'Mensagem enviada pelo cliente',
442
+ },
443
+ {
444
+ displayName: 'Nome do Cliente',
445
+ name: 'nomeCliente',
446
+ type: 'string',
447
+ displayOptions: {
448
+ show: {
449
+ resource: ['ia'],
450
+ operation: ['processMessage', 'generateResponse'],
451
+ },
452
+ },
453
+ default: '',
454
+ description: 'Nome do cliente para personalização',
455
+ },
456
+ // COMMON FIELDS
457
+ {
458
+ displayName: 'ID',
459
+ name: 'id',
460
+ type: 'number',
461
+ required: true,
462
+ displayOptions: {
463
+ show: {
464
+ resource: ['agendamento', 'servico'],
465
+ operation: ['get', 'update', 'delete', 'reschedule', 'cancel'],
466
+ },
467
+ },
468
+ default: 1,
469
+ description: 'ID do registro',
470
+ },
471
+ ],
472
+ };
473
+ }
474
+ async execute(executeFunctions) {
475
+ const items = executeFunctions.getInputData();
476
+ const returnData = [];
477
+ const resource = executeFunctions.getNodeParameter('resource', 0);
478
+ const operation = executeFunctions.getNodeParameter('operation', 0);
479
+ for (let i = 0; i < items.length; i++) {
480
+ try {
481
+ let responseData;
482
+ if (resource === 'agendamento') {
483
+ if (operation === 'create') {
484
+ const clienteNome = executeFunctions.getNodeParameter('clienteNome', i);
485
+ const clienteTelefone = executeFunctions.getNodeParameter('clienteTelefone', i);
486
+ const servicoId = executeFunctions.getNodeParameter('servicoId', i);
487
+ const dataAgendamento = executeFunctions.getNodeParameter('dataAgendamento', i);
488
+ const observacoes = executeFunctions.getNodeParameter('observacoes', i);
489
+ const body = {
490
+ cliente_nome: clienteNome,
491
+ cliente_telefone: clienteTelefone,
492
+ servico_id: servicoId,
493
+ data_agendamento: new Date(dataAgendamento).toISOString().split('T')[0],
494
+ hora_agendamento: new Date(dataAgendamento).toTimeString().split(' ')[0],
495
+ observacoes,
496
+ };
497
+ responseData = await GenericFunctions_1.agendamentoSaasApiRequest.call(executeFunctions, 'POST', '/api/agendamentos', body);
498
+ }
499
+ if (operation === 'get') {
500
+ const id = executeFunctions.getNodeParameter('id', i);
501
+ responseData = await GenericFunctions_1.agendamentoSaasApiRequest.call(executeFunctions, 'GET', `/api/agendamentos/${id}`);
502
+ }
503
+ if (operation === 'getAll') {
504
+ responseData = await GenericFunctions_1.agendamentoSaasApiRequest.call(executeFunctions, 'GET', '/api/agendamentos');
505
+ }
506
+ if (operation === 'reschedule') {
507
+ const id = executeFunctions.getNodeParameter('id', i);
508
+ const novaDataAgendamento = executeFunctions.getNodeParameter('novaDataAgendamento', i);
509
+ const motivoReagendamento = executeFunctions.getNodeParameter('motivoReagendamento', i);
510
+ const body = {
511
+ data_agendamento: new Date(novaDataAgendamento).toISOString().split('T')[0],
512
+ hora_agendamento: new Date(novaDataAgendamento).toTimeString().split(' ')[0],
513
+ motivo_reagendamento: motivoReagendamento,
514
+ status: 'reagendado',
515
+ };
516
+ responseData = await GenericFunctions_1.agendamentoSaasApiRequest.call(executeFunctions, 'PUT', `/api/agendamentos/${id}/reschedule`, body);
517
+ }
518
+ if (operation === 'cancel') {
519
+ const id = executeFunctions.getNodeParameter('id', i);
520
+ const body = {
521
+ status: 'cancelado',
522
+ };
523
+ responseData = await GenericFunctions_1.agendamentoSaasApiRequest.call(executeFunctions, 'PUT', `/api/agendamentos/${id}/cancel`, body);
524
+ }
525
+ if (operation === 'delete') {
526
+ const id = executeFunctions.getNodeParameter('id', i);
527
+ responseData = await GenericFunctions_1.agendamentoSaasApiRequest.call(executeFunctions, 'DELETE', `/api/agendamentos/${id}`);
528
+ }
529
+ }
530
+ if (resource === 'servico') {
531
+ if (operation === 'getAll') {
532
+ responseData = await GenericFunctions_1.agendamentoSaasApiRequest.call(executeFunctions, 'GET', '/api/servicos');
533
+ }
534
+ if (operation === 'get') {
535
+ const id = executeFunctions.getNodeParameter('id', i);
536
+ responseData = await GenericFunctions_1.agendamentoSaasApiRequest.call(executeFunctions, 'GET', `/api/servicos/${id}`);
537
+ }
538
+ }
539
+ if (resource === 'horario') {
540
+ if (operation === 'getAvailable') {
541
+ const dataHorario = executeFunctions.getNodeParameter('dataHorario', i);
542
+ const servicoIdHorario = executeFunctions.getNodeParameter('servicoIdHorario', i);
543
+ const qs = {
544
+ data: new Date(dataHorario).toISOString().split('T')[0],
545
+ };
546
+ if (servicoIdHorario > 0) {
547
+ qs.servico_id = servicoIdHorario;
548
+ }
549
+ responseData = await GenericFunctions_1.agendamentoSaasApiRequest.call(executeFunctions, 'GET', '/api/horarios-disponiveis', {}, qs);
550
+ }
551
+ if (operation === 'checkAvailability') {
552
+ const dataHorario = executeFunctions.getNodeParameter('dataHorario', i);
553
+ const horaEspecifica = executeFunctions.getNodeParameter('horaEspecifica', i);
554
+ const servicoIdHorario = executeFunctions.getNodeParameter('servicoIdHorario', i);
555
+ const qs = {
556
+ data: new Date(dataHorario).toISOString().split('T')[0],
557
+ hora: horaEspecifica,
558
+ };
559
+ if (servicoIdHorario > 0) {
560
+ qs.servico_id = servicoIdHorario;
561
+ }
562
+ responseData = await GenericFunctions_1.agendamentoSaasApiRequest.call(executeFunctions, 'GET', '/api/verificar-disponibilidade', {}, qs);
563
+ }
564
+ }
565
+ if (resource === 'whatsapp') {
566
+ if (operation === 'sendMessage') {
567
+ const telefone = executeFunctions.getNodeParameter('telefone', i);
568
+ const mensagem = executeFunctions.getNodeParameter('mensagem', i);
569
+ const body = {
570
+ telefone,
571
+ mensagem,
572
+ };
573
+ responseData = await GenericFunctions_1.agendamentoSaasApiRequest.call(executeFunctions, 'POST', '/api/whatsapp/send-message', body);
574
+ }
575
+ if (operation === 'sendAudio') {
576
+ const telefone = executeFunctions.getNodeParameter('telefone', i);
577
+ const textoAudio = executeFunctions.getNodeParameter('textoAudio', i);
578
+ const body = {
579
+ telefone,
580
+ texto: textoAudio,
581
+ };
582
+ responseData = await GenericFunctions_1.agendamentoSaasApiRequest.call(executeFunctions, 'POST', '/api/whatsapp/send-audio', body);
583
+ }
584
+ if (operation === 'getStatus') {
585
+ responseData = await GenericFunctions_1.agendamentoSaasApiRequest.call(executeFunctions, 'GET', '/api/whatsapp/status');
586
+ }
587
+ }
588
+ if (resource === 'ia') {
589
+ if (operation === 'processMessage') {
590
+ const mensagemCliente = executeFunctions.getNodeParameter('mensagemCliente', i);
591
+ const nomeCliente = executeFunctions.getNodeParameter('nomeCliente', i);
592
+ const body = {
593
+ mensagem: mensagemCliente,
594
+ nome_cliente: nomeCliente,
595
+ };
596
+ responseData = await GenericFunctions_1.agendamentoSaasApiRequest.call(executeFunctions, 'POST', '/api/ia/process-message', body);
597
+ }
598
+ if (operation === 'generateResponse') {
599
+ const mensagemCliente = executeFunctions.getNodeParameter('mensagemCliente', i);
600
+ const nomeCliente = executeFunctions.getNodeParameter('nomeCliente', i);
601
+ const body = {
602
+ mensagem: mensagemCliente,
603
+ nome_cliente: nomeCliente,
604
+ apenas_resposta: true,
605
+ };
606
+ responseData = await GenericFunctions_1.agendamentoSaasApiRequest.call(executeFunctions, 'POST', '/api/ia/generate-response', body);
607
+ }
608
+ }
609
+ returnData.push({
610
+ json: responseData || {},
611
+ });
612
+ }
613
+ catch (error) {
614
+ if (executeFunctions.continueOnFail()) {
615
+ returnData.push({
616
+ json: { error: error.message },
617
+ });
618
+ continue;
619
+ }
620
+ throw error;
621
+ }
622
+ }
623
+ return [returnData];
624
+ }
625
+ }
626
+ exports.AgendamentoSaas = AgendamentoSaas;
@@ -0,0 +1 @@
1
+ export declare function agendamentoSaasApiRequest(executeFunctions: any, method: string, resource: string, body?: any, qs?: any, uri?: string, headers?: any): Promise<any>;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.agendamentoSaasApiRequest = void 0;
4
+ async function agendamentoSaasApiRequest(executeFunctions, method, resource, body = {}, qs = {}, uri, headers = {}) {
5
+ const credentials = await executeFunctions.getCredentials('agendamentoSaasApi');
6
+ const options = {
7
+ method,
8
+ headers: {
9
+ 'Authorization': `Bearer ${credentials.apiKey}`,
10
+ 'X-Empresa-ID': credentials.empresaId,
11
+ 'Content-Type': 'application/json',
12
+ ...headers,
13
+ },
14
+ body,
15
+ qs,
16
+ uri: uri || `${credentials.apiUrl}${resource}`,
17
+ json: true,
18
+ };
19
+ try {
20
+ if (Object.keys(body).length === 0) {
21
+ delete options.body;
22
+ }
23
+ return await executeFunctions.helpers.httpRequest(options);
24
+ }
25
+ catch (error) {
26
+ throw new Error(`API Request failed: ${error.message}`);
27
+ }
28
+ }
29
+ exports.agendamentoSaasApiRequest = agendamentoSaasApiRequest;
@@ -0,0 +1,12 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
2
+ <rect x="3" y="4" width="18" height="18" rx="2" ry="2"/>
3
+ <line x1="16" y1="2" x2="16" y2="6"/>
4
+ <line x1="8" y1="2" x2="8" y2="6"/>
5
+ <line x1="3" y1="10" x2="21" y2="10"/>
6
+ <path d="M8 14h.01"/>
7
+ <path d="M12 14h.01"/>
8
+ <path d="M16 14h.01"/>
9
+ <path d="M8 18h.01"/>
10
+ <path d="M12 18h.01"/>
11
+ <path d="M16 18h.01"/>
12
+ </svg>
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@upazambuja/n8n-nodes-agendamento-saas",
3
+ "version": "1.0.0",
4
+ "description": "n8n node for Agendamento SaaS - WhatsApp scheduling system with AI",
5
+ "keywords": [
6
+ "n8n-community-node-package",
7
+ "n8n",
8
+ "agendamento",
9
+ "whatsapp",
10
+ "scheduling",
11
+ "saas",
12
+ "ai",
13
+ "appointment"
14
+ ],
15
+ "license": "MIT",
16
+ "homepage": "https://github.com/seu-usuario/n8n-nodes-agendamento-saas",
17
+ "author": {
18
+ "name": "upazambuja",
19
+ "email": "andre808202@gmail.com"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/seu-usuario/n8n-nodes-agendamento-saas.git"
24
+ },
25
+ "main": "index.js",
26
+ "scripts": {
27
+ "build": "tsc && gulp build:icons",
28
+ "dev": "tsc --watch",
29
+ "format": "prettier nodes --write",
30
+ "prepublishOnly": "npm run build"
31
+ },
32
+ "files": [
33
+ "dist"
34
+ ],
35
+ "n8n": {
36
+ "n8nNodesApiVersion": 1,
37
+ "credentials": [
38
+ "dist/credentials/AgendamentoSaasApi.credentials.js"
39
+ ],
40
+ "nodes": [
41
+ "dist/nodes/AgendamentoSaas/AgendamentoSaas.node.js"
42
+ ]
43
+ },
44
+ "devDependencies": {
45
+ "@types/node": "^18.16.16",
46
+ "gulp": "^4.0.2",
47
+ "prettier": "^2.7.1",
48
+ "typescript": "^4.8.4"
49
+ },
50
+ "peerDependencies": {}
51
+ }