n8n-nodes-aivencerealtycrm 1.0.6 → 1.0.8

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.
@@ -102,10 +102,16 @@ class AivenceRealty {
102
102
  description: 'Obtener lead por ID',
103
103
  action: 'Obtener lead',
104
104
  },
105
+ {
106
+ name: 'Add Activity',
107
+ value: 'addActivity',
108
+ description: 'Agregar actividad a un lead',
109
+ action: 'Agregar actividad',
110
+ },
105
111
  ],
106
112
  default: 'list',
107
113
  },
108
- // Lead ID (para Update y Get)
114
+ // Lead ID (para Update, Get y AddActivity)
109
115
  {
110
116
  displayName: 'Lead ID',
111
117
  name: 'leadId',
@@ -114,7 +120,7 @@ class AivenceRealty {
114
120
  displayOptions: {
115
121
  show: {
116
122
  resource: ['lead'],
117
- operation: ['update', 'get'],
123
+ operation: ['update', 'get', 'addActivity'],
118
124
  },
119
125
  },
120
126
  default: '',
@@ -131,10 +137,378 @@ class AivenceRealty {
131
137
  operation: ['create', 'update'],
132
138
  },
133
139
  },
134
- default: true,
140
+ default: false,
135
141
  description: 'Si está activado, usará el JSON completo del nodo anterior',
136
142
  },
137
143
  // ============================================
144
+ // LEAD CREATE/UPDATE FIELDS (Structured)
145
+ // ============================================
146
+ {
147
+ displayName: 'Nombre',
148
+ name: 'name',
149
+ type: 'string',
150
+ required: true,
151
+ displayOptions: {
152
+ show: {
153
+ resource: ['lead'],
154
+ operation: ['create', 'update'],
155
+ useJsonInput: [false],
156
+ },
157
+ },
158
+ default: '',
159
+ description: 'Nombre completo del lead',
160
+ },
161
+ {
162
+ displayName: 'Email',
163
+ name: 'email',
164
+ type: 'string',
165
+ required: true,
166
+ displayOptions: {
167
+ show: {
168
+ resource: ['lead'],
169
+ operation: ['create', 'update'],
170
+ useJsonInput: [false],
171
+ },
172
+ },
173
+ default: '',
174
+ description: 'Email del lead',
175
+ },
176
+ {
177
+ displayName: 'Teléfono',
178
+ name: 'phone',
179
+ type: 'string',
180
+ required: true,
181
+ displayOptions: {
182
+ show: {
183
+ resource: ['lead'],
184
+ operation: ['create', 'update'],
185
+ useJsonInput: [false],
186
+ },
187
+ },
188
+ default: '',
189
+ description: 'Teléfono del lead',
190
+ },
191
+ {
192
+ displayName: 'Mensaje',
193
+ name: 'message',
194
+ type: 'string',
195
+ typeOptions: {
196
+ rows: 4,
197
+ },
198
+ displayOptions: {
199
+ show: {
200
+ resource: ['lead'],
201
+ operation: ['create', 'update'],
202
+ useJsonInput: [false],
203
+ },
204
+ },
205
+ default: '',
206
+ description: 'Mensaje o consulta del lead',
207
+ },
208
+ {
209
+ displayName: 'Interés',
210
+ name: 'interest',
211
+ type: 'options',
212
+ options: [
213
+ {
214
+ name: 'Compra',
215
+ value: 'compra',
216
+ },
217
+ {
218
+ name: 'Alquiler',
219
+ value: 'alquiler',
220
+ },
221
+ ],
222
+ displayOptions: {
223
+ show: {
224
+ resource: ['lead'],
225
+ operation: ['create', 'update'],
226
+ useJsonInput: [false],
227
+ },
228
+ },
229
+ default: 'compra',
230
+ description: 'Tipo de interés del lead',
231
+ },
232
+ {
233
+ displayName: 'Presupuesto Mínimo',
234
+ name: 'budget_min',
235
+ type: 'number',
236
+ displayOptions: {
237
+ show: {
238
+ resource: ['lead'],
239
+ operation: ['create', 'update'],
240
+ useJsonInput: [false],
241
+ },
242
+ },
243
+ default: 0,
244
+ description: 'Presupuesto mínimo',
245
+ },
246
+ {
247
+ displayName: 'Presupuesto Máximo',
248
+ name: 'budget_max',
249
+ type: 'number',
250
+ displayOptions: {
251
+ show: {
252
+ resource: ['lead'],
253
+ operation: ['create', 'update'],
254
+ useJsonInput: [false],
255
+ },
256
+ },
257
+ default: 0,
258
+ description: 'Presupuesto máximo',
259
+ },
260
+ {
261
+ displayName: 'Áreas Preferidas',
262
+ name: 'preferred_areas',
263
+ type: 'string',
264
+ displayOptions: {
265
+ show: {
266
+ resource: ['lead'],
267
+ operation: ['create', 'update'],
268
+ useJsonInput: [false],
269
+ },
270
+ },
271
+ default: '',
272
+ description: 'Áreas preferidas separadas por comas',
273
+ },
274
+ {
275
+ displayName: 'Tipo de Propiedad',
276
+ name: 'property_type',
277
+ type: 'options',
278
+ options: [
279
+ {
280
+ name: 'Apartamento',
281
+ value: 'apartamento',
282
+ },
283
+ {
284
+ name: 'Casa',
285
+ value: 'casa',
286
+ },
287
+ {
288
+ name: 'Loft',
289
+ value: 'loft',
290
+ },
291
+ {
292
+ name: 'Estudio',
293
+ value: 'estudio',
294
+ },
295
+ ],
296
+ displayOptions: {
297
+ show: {
298
+ resource: ['lead'],
299
+ operation: ['create', 'update'],
300
+ useJsonInput: [false],
301
+ },
302
+ },
303
+ default: 'apartamento',
304
+ description: 'Tipo de propiedad de interés',
305
+ },
306
+ {
307
+ displayName: 'Conversation ID',
308
+ name: 'conversation_id',
309
+ type: 'string',
310
+ displayOptions: {
311
+ show: {
312
+ resource: ['lead'],
313
+ operation: ['create', 'update'],
314
+ useJsonInput: [false],
315
+ },
316
+ },
317
+ default: '',
318
+ description: 'ID de conversación de Chatwoot/AivenceGraph para vincular el lead con su historial',
319
+ },
320
+ {
321
+ displayName: 'Status',
322
+ name: 'status',
323
+ type: 'options',
324
+ options: [
325
+ {
326
+ name: 'New',
327
+ value: 'new',
328
+ },
329
+ {
330
+ name: 'Contacted',
331
+ value: 'contacted',
332
+ },
333
+ {
334
+ name: 'Qualified',
335
+ value: 'qualified',
336
+ },
337
+ {
338
+ name: 'Converted',
339
+ value: 'converted',
340
+ },
341
+ {
342
+ name: 'Lost',
343
+ value: 'lost',
344
+ },
345
+ ],
346
+ displayOptions: {
347
+ show: {
348
+ resource: ['lead'],
349
+ operation: ['create', 'update'],
350
+ useJsonInput: [false],
351
+ },
352
+ },
353
+ default: 'new',
354
+ description: 'Estado del lead',
355
+ },
356
+ {
357
+ displayName: 'Score',
358
+ name: 'score',
359
+ type: 'number',
360
+ typeOptions: {
361
+ minValue: 0,
362
+ maxValue: 100,
363
+ },
364
+ displayOptions: {
365
+ show: {
366
+ resource: ['lead'],
367
+ operation: ['create', 'update'],
368
+ useJsonInput: [false],
369
+ },
370
+ },
371
+ default: 0,
372
+ description: 'Puntuación del lead (0-100)',
373
+ },
374
+ {
375
+ displayName: 'Category',
376
+ name: 'category',
377
+ type: 'options',
378
+ options: [
379
+ {
380
+ name: 'Hot',
381
+ value: 'hot',
382
+ },
383
+ {
384
+ name: 'Warm',
385
+ value: 'warm',
386
+ },
387
+ {
388
+ name: 'Cold',
389
+ value: 'cold',
390
+ },
391
+ ],
392
+ displayOptions: {
393
+ show: {
394
+ resource: ['lead'],
395
+ operation: ['create', 'update'],
396
+ useJsonInput: [false],
397
+ },
398
+ },
399
+ default: 'warm',
400
+ description: 'Categoría del lead',
401
+ },
402
+ {
403
+ displayName: 'Tags',
404
+ name: 'tags',
405
+ type: 'string',
406
+ displayOptions: {
407
+ show: {
408
+ resource: ['lead'],
409
+ operation: ['create', 'update'],
410
+ useJsonInput: [false],
411
+ },
412
+ },
413
+ default: '',
414
+ description: 'Tags separados por comas (ej: "VIP,Urgente,Referido")',
415
+ },
416
+ {
417
+ displayName: 'Notes',
418
+ name: 'notes',
419
+ type: 'string',
420
+ typeOptions: {
421
+ rows: 4,
422
+ },
423
+ displayOptions: {
424
+ show: {
425
+ resource: ['lead'],
426
+ operation: ['create', 'update'],
427
+ useJsonInput: [false],
428
+ },
429
+ },
430
+ default: '',
431
+ description: 'Notas adicionales sobre el lead',
432
+ },
433
+ {
434
+ displayName: 'CRM ID',
435
+ name: 'crm_id',
436
+ type: 'string',
437
+ displayOptions: {
438
+ show: {
439
+ resource: ['lead'],
440
+ operation: ['create', 'update'],
441
+ useJsonInput: [false],
442
+ },
443
+ },
444
+ default: '',
445
+ description: 'ID del lead en sistema CRM externo',
446
+ },
447
+ // ============================================
448
+ // LEAD ADD ACTIVITY FIELDS
449
+ // ============================================
450
+ {
451
+ displayName: 'Activity Type',
452
+ name: 'activity_type',
453
+ type: 'options',
454
+ required: true,
455
+ options: [
456
+ {
457
+ name: 'Llamada',
458
+ value: 'llamada',
459
+ },
460
+ {
461
+ name: 'Email',
462
+ value: 'email',
463
+ },
464
+ {
465
+ name: 'WhatsApp',
466
+ value: 'whatsapp',
467
+ },
468
+ {
469
+ name: 'Reunión',
470
+ value: 'reunion',
471
+ },
472
+ {
473
+ name: 'Visita Propiedad',
474
+ value: 'visita_propiedad',
475
+ },
476
+ {
477
+ name: 'Seguimiento',
478
+ value: 'seguimiento',
479
+ },
480
+ {
481
+ name: 'Otro',
482
+ value: 'otro',
483
+ },
484
+ ],
485
+ displayOptions: {
486
+ show: {
487
+ resource: ['lead'],
488
+ operation: ['addActivity'],
489
+ },
490
+ },
491
+ default: 'llamada',
492
+ description: 'Tipo de actividad',
493
+ },
494
+ {
495
+ displayName: 'Description',
496
+ name: 'activity_description',
497
+ type: 'string',
498
+ required: true,
499
+ typeOptions: {
500
+ rows: 4,
501
+ },
502
+ displayOptions: {
503
+ show: {
504
+ resource: ['lead'],
505
+ operation: ['addActivity'],
506
+ },
507
+ },
508
+ default: '',
509
+ description: 'Descripción de la actividad',
510
+ },
511
+ // ============================================
138
512
  // PROPERTY OPERATIONS
139
513
  // ============================================
140
514
  {
@@ -374,14 +748,38 @@ class AivenceRealty {
374
748
  },
375
749
  },
376
750
  options: [
751
+ {
752
+ name: 'List',
753
+ value: 'list',
754
+ description: 'Listar citas',
755
+ action: 'Listar citas',
756
+ },
377
757
  {
378
758
  name: 'Create',
379
759
  value: 'create',
380
760
  description: 'Crear cita',
381
761
  action: 'Crear cita',
382
762
  },
763
+ {
764
+ name: 'Get',
765
+ value: 'get',
766
+ description: 'Obtener cita por ID',
767
+ action: 'Obtener cita',
768
+ },
769
+ {
770
+ name: 'Update Status',
771
+ value: 'updateStatus',
772
+ description: 'Actualizar estado de cita',
773
+ action: 'Actualizar estado',
774
+ },
775
+ {
776
+ name: 'Delete',
777
+ value: 'delete',
778
+ description: 'Eliminar cita',
779
+ action: 'Eliminar cita',
780
+ },
383
781
  ],
384
- default: 'create',
782
+ default: 'list',
385
783
  },
386
784
  {
387
785
  displayName: 'Usar datos del nodo anterior',
@@ -396,6 +794,54 @@ class AivenceRealty {
396
794
  default: true,
397
795
  description: 'Si está activado, usará el JSON completo del nodo anterior',
398
796
  },
797
+ // Appointment ID para get, updateStatus y delete
798
+ {
799
+ displayName: 'Appointment ID',
800
+ name: 'appointmentId',
801
+ type: 'string',
802
+ required: true,
803
+ displayOptions: {
804
+ show: {
805
+ resource: ['appointment'],
806
+ operation: ['get', 'updateStatus', 'delete'],
807
+ },
808
+ },
809
+ default: '',
810
+ description: 'ID de la cita',
811
+ },
812
+ // Estado para updateStatus
813
+ {
814
+ displayName: 'Estado',
815
+ name: 'appointment_status',
816
+ type: 'options',
817
+ required: true,
818
+ options: [
819
+ {
820
+ name: 'Pending',
821
+ value: 'pending',
822
+ },
823
+ {
824
+ name: 'Confirmed',
825
+ value: 'confirmed',
826
+ },
827
+ {
828
+ name: 'Completed',
829
+ value: 'completed',
830
+ },
831
+ {
832
+ name: 'Cancelled',
833
+ value: 'cancelled',
834
+ },
835
+ ],
836
+ displayOptions: {
837
+ show: {
838
+ resource: ['appointment'],
839
+ operation: ['updateStatus'],
840
+ },
841
+ },
842
+ default: 'pending',
843
+ description: 'Nuevo estado de la cita',
844
+ },
399
845
  ],
400
846
  };
401
847
  }
@@ -421,8 +867,60 @@ class AivenceRealty {
421
867
  });
422
868
  }
423
869
  else if (operation === 'create') {
424
- const useJsonInput = this.getNodeParameter('useJsonInput', i, true);
425
- const body = useJsonInput ? items[i].json : {};
870
+ const useJsonInput = this.getNodeParameter('useJsonInput', i, false);
871
+ let body = {};
872
+ if (useJsonInput) {
873
+ // Usar JSON del nodo anterior
874
+ body = items[i].json;
875
+ }
876
+ else {
877
+ // Construir body con campos estructurados
878
+ body = {
879
+ name: this.getNodeParameter('name', i),
880
+ email: this.getNodeParameter('email', i),
881
+ phone: this.getNodeParameter('phone', i),
882
+ message: this.getNodeParameter('message', i, ''),
883
+ interest: this.getNodeParameter('interest', i, 'compra'),
884
+ budget_min: this.getNodeParameter('budget_min', i, 0),
885
+ budget_max: this.getNodeParameter('budget_max', i, 0),
886
+ property_type: this.getNodeParameter('property_type', i, 'apartamento'),
887
+ conversation_id: this.getNodeParameter('conversation_id', i, ''),
888
+ status: this.getNodeParameter('status', i, 'new'),
889
+ score: this.getNodeParameter('score', i, 0),
890
+ category: this.getNodeParameter('category', i, 'warm'),
891
+ notes: this.getNodeParameter('notes', i, ''),
892
+ crm_id: this.getNodeParameter('crm_id', i, ''),
893
+ };
894
+ // Procesar preferred_areas (convertir string separado por comas a array)
895
+ const areasString = this.getNodeParameter('preferred_areas', i, '');
896
+ if (areasString) {
897
+ body.preferred_areas = areasString.split(',').map((area) => area.trim());
898
+ }
899
+ // Procesar tags (convertir string separado por comas a array)
900
+ const tagsString = this.getNodeParameter('tags', i, '');
901
+ if (tagsString) {
902
+ body.tags = tagsString.split(',').map((tag) => tag.trim());
903
+ }
904
+ // Remover campos vacíos opcionales
905
+ if (!body.message)
906
+ delete body.message;
907
+ if (body.budget_min === 0)
908
+ delete body.budget_min;
909
+ if (body.budget_max === 0)
910
+ delete body.budget_max;
911
+ if (!body.preferred_areas || body.preferred_areas.length === 0)
912
+ delete body.preferred_areas;
913
+ if (!body.conversation_id)
914
+ delete body.conversation_id;
915
+ if (!body.notes)
916
+ delete body.notes;
917
+ if (!body.crm_id)
918
+ delete body.crm_id;
919
+ if (!body.tags || body.tags.length === 0)
920
+ delete body.tags;
921
+ if (body.score === 0)
922
+ delete body.score;
923
+ }
426
924
  responseData = await this.helpers.httpRequest({
427
925
  method: 'POST',
428
926
  url: `${baseUrl}/api/v1/leads`,
@@ -432,8 +930,65 @@ class AivenceRealty {
432
930
  }
433
931
  else if (operation === 'update') {
434
932
  const leadId = this.getNodeParameter('leadId', i);
435
- const useJsonInput = this.getNodeParameter('useJsonInput', i, true);
436
- const body = useJsonInput ? items[i].json : {};
933
+ const useJsonInput = this.getNodeParameter('useJsonInput', i, false);
934
+ let body = {};
935
+ if (useJsonInput) {
936
+ // Usar JSON del nodo anterior
937
+ body = items[i].json;
938
+ }
939
+ else {
940
+ // Construir body con campos estructurados (solo enviar campos proporcionados)
941
+ const name = this.getNodeParameter('name', i, '');
942
+ const email = this.getNodeParameter('email', i, '');
943
+ const phone = this.getNodeParameter('phone', i, '');
944
+ const message = this.getNodeParameter('message', i, '');
945
+ const interest = this.getNodeParameter('interest', i, '');
946
+ const budget_min = this.getNodeParameter('budget_min', i, 0);
947
+ const budget_max = this.getNodeParameter('budget_max', i, 0);
948
+ const property_type = this.getNodeParameter('property_type', i, '');
949
+ const areasString = this.getNodeParameter('preferred_areas', i, '');
950
+ const conversation_id = this.getNodeParameter('conversation_id', i, '');
951
+ const status = this.getNodeParameter('status', i, '');
952
+ const score = this.getNodeParameter('score', i, 0);
953
+ const category = this.getNodeParameter('category', i, '');
954
+ const notes = this.getNodeParameter('notes', i, '');
955
+ const crm_id = this.getNodeParameter('crm_id', i, '');
956
+ const tagsString = this.getNodeParameter('tags', i, '');
957
+ if (name)
958
+ body.name = name;
959
+ if (email)
960
+ body.email = email;
961
+ if (phone)
962
+ body.phone = phone;
963
+ if (message)
964
+ body.message = message;
965
+ if (interest)
966
+ body.interest = interest;
967
+ if (budget_min > 0)
968
+ body.budget_min = budget_min;
969
+ if (budget_max > 0)
970
+ body.budget_max = budget_max;
971
+ if (property_type)
972
+ body.property_type = property_type;
973
+ if (conversation_id)
974
+ body.conversation_id = conversation_id;
975
+ if (status)
976
+ body.status = status;
977
+ if (score > 0)
978
+ body.score = score;
979
+ if (category)
980
+ body.category = category;
981
+ if (notes)
982
+ body.notes = notes;
983
+ if (crm_id)
984
+ body.crm_id = crm_id;
985
+ if (areasString) {
986
+ body.preferred_areas = areasString.split(',').map((area) => area.trim());
987
+ }
988
+ if (tagsString) {
989
+ body.tags = tagsString.split(',').map((tag) => tag.trim());
990
+ }
991
+ }
437
992
  responseData = await this.helpers.httpRequest({
438
993
  method: 'PATCH',
439
994
  url: `${baseUrl}/api/v1/leads/${leadId}`,
@@ -449,6 +1004,21 @@ class AivenceRealty {
449
1004
  json: true,
450
1005
  });
451
1006
  }
1007
+ else if (operation === 'addActivity') {
1008
+ const leadId = this.getNodeParameter('leadId', i);
1009
+ const activityType = this.getNodeParameter('activity_type', i);
1010
+ const description = this.getNodeParameter('activity_description', i);
1011
+ const body = {
1012
+ activity_type: activityType,
1013
+ description: description,
1014
+ };
1015
+ responseData = await this.helpers.httpRequest({
1016
+ method: 'POST',
1017
+ url: `${baseUrl}/api/v1/mariana/leads/${leadId}/activity`,
1018
+ body,
1019
+ json: true,
1020
+ });
1021
+ }
452
1022
  }
453
1023
  // ============================================
454
1024
  // PROPERTY RESOURCE
@@ -583,16 +1153,49 @@ class AivenceRealty {
583
1153
  // APPOINTMENT RESOURCE
584
1154
  // ============================================
585
1155
  else if (resource === 'appointment') {
586
- if (operation === 'create') {
1156
+ if (operation === 'list') {
1157
+ responseData = await this.helpers.httpRequest({
1158
+ method: 'GET',
1159
+ url: `${baseUrl}/api/v1/reservas`,
1160
+ json: true,
1161
+ });
1162
+ }
1163
+ else if (operation === 'create') {
587
1164
  const useJsonInput = this.getNodeParameter('useJsonInput', i, true);
588
1165
  const body = useJsonInput ? items[i].json : {};
589
1166
  responseData = await this.helpers.httpRequest({
590
1167
  method: 'POST',
591
- url: `${baseUrl}/api/v1/appointments`,
1168
+ url: `${baseUrl}/api/v1/reservas`,
592
1169
  body,
593
1170
  json: true,
594
1171
  });
595
1172
  }
1173
+ else if (operation === 'get') {
1174
+ const appointmentId = this.getNodeParameter('appointmentId', i);
1175
+ responseData = await this.helpers.httpRequest({
1176
+ method: 'GET',
1177
+ url: `${baseUrl}/api/v1/reservas/${appointmentId}`,
1178
+ json: true,
1179
+ });
1180
+ }
1181
+ else if (operation === 'updateStatus') {
1182
+ const appointmentId = this.getNodeParameter('appointmentId', i);
1183
+ const status = this.getNodeParameter('appointment_status', i);
1184
+ responseData = await this.helpers.httpRequest({
1185
+ method: 'PUT',
1186
+ url: `${baseUrl}/api/v1/reservas/${appointmentId}/estado`,
1187
+ body: { estado: status },
1188
+ json: true,
1189
+ });
1190
+ }
1191
+ else if (operation === 'delete') {
1192
+ const appointmentId = this.getNodeParameter('appointmentId', i);
1193
+ responseData = await this.helpers.httpRequest({
1194
+ method: 'DELETE',
1195
+ url: `${baseUrl}/api/v1/reservas/${appointmentId}`,
1196
+ json: true,
1197
+ });
1198
+ }
596
1199
  }
597
1200
  // Formatear respuesta
598
1201
  const executionData = this.helpers.constructExecutionMetaData(this.helpers.returnJsonArray(responseData), { itemData: { item: i } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n8n-nodes-aivencerealtycrm",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "Nodo n8n para integrar el CRM inmobiliario AivenceRealty",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",