martes, 18 de octubre de 2022

BOT Telegram para toma de pedido

 Hola a continuación le dejo material para que puedan implementar un BOT en Telegram de Toma de Pedidp empleando hoja de calculo Google Sheet.

¿ Que necesitas para implementarlo ?

- Crear la hoja Google sheet como indica el video 

         - Crear BOT en telegram como indica el video

Video Implementación



Página Excel Plantilla


https://docs.google.com/spreadsheets/d/1bBL_hnLEY_7ZuvmaH-a66JOdA-vLrfWxy8J7NbxmfoE/edit?usp=sharing


Código AppScript 


En este link encontraran las fuentes mostradas en el Video del APP Script


https://anlusoftware.blogspot.com/?p=a913f147


ASESORIA o Consultas PERSONALIZADA :

En caso necesites alguna asesoría personalizada agéndame un espacio.

https://reservarasesoriaanlusoft.blogspot.com/

BOT Telegram para reenvio mensajes

 Hola a continuación le dejo material para que puedan implementar un BOT en Telegram empleando hoja de calculo Google Sheet.

¿ Que necesitas para implementarlo ?

- Crear la hoja Google sheet como indica el video 

         - Crear BOT en telegram como indica el video

Video Implementación




Página Excel Plantilla


https://docs.google.com/spreadsheets/d/1m9Kgdr6qHcoygzWKLxaXPm74wV43SyvAanbGzpmGJyg/edit?usp=sharing


Código AppScript 


function notificartelegran(mensaje, numero, api, token) {  

  try {

        var options =

             {

               'headers': {"Content-Type" : "application/json"},

               'method' : "POST",

               'payload' : JSON.stringify({

                 "method":"sendMessage",

                 "chat_id":numero,

                 "text":mensaje,

                 "parse_mode":"HTML",

               })

        };    

       var response = UrlFetchApp.fetch(api+token+"/", options);

        var json = JSON.parse(response.getContentText());

    } catch (e) {

    }

}

function enviar(messague) {


  var excel = SpreadsheetApp.getActiveSpreadsheet();

  var sheet_informacion = excel.getSheetByName("Informacion");

  sheet_informacion.appendRow([new Date(), messague]); 

  var mensaje_telegram = JSON.parse(messague);  

  var mensaje_buscar = "Te reenvio : "+ mensaje_telegram.message.text;

  var numero_enviar = mensaje_telegram.message.chat.id;

  var sheet_configuracion = excel.getSheetByName("Configuracion");

  var token = sheet_configuracion.getRange(1, 2).getValue();

  var api = sheet_configuracion.getRange(2, 2).getValue();

  notificartelegran(mensaje_buscar, numero_enviar,api,token);  

}


function doPost(e) {

    enviar(e.postData.contents);

}


ASESORIA o Consultas PERSONALIZADA :

En caso necesites alguna asesoría personalizada agéndame un espacio.

https://reservarasesoriaanlusoft.blogspot.com/

martes, 11 de octubre de 2022

API FTP con Google Drive

  A continuación se muestra una solución para crear una API Google Drive para almacenar y recuperar archivo desde tu carpetas de Google drive.

¿ Que necesitas para implementarlo ?

- Solo tener cuenta gmail

Video Solución:



Payload API FTP

trama envio documento:

{

    "op": "ftp_archivo",

    "archivo_name": "archivo1.pdf",

    "archivo_base64": ""

}

trama lectura documento:

{

    "op": "ftp_descargar",

    "archivo_name": "archivo1.pdf"

}

Código App Script

var folderurl = "ID_FOLDER";

function doPost(e){

  Logger.log("Funcion doPost Ingreso : la fecha y hora: " + new Date());

  var operacion = JSON.parse(e.postData.contents)

  var respuesta = "";

  if (operacion.op == "ftp_archivo"){

     var archivo_name = operacion.archivo_name;

     var archivo_type = "image/jpeg";

     if(archivo_name.includes(".pdf")){

       archivo_type="application/pdf";

     }else if(archivo_name.includes(".zip")){

       archivo_type="application/zip";

     }else if(archivo_name.includes(".xml")){

       archivo_type="application/xml";

     }    

     var archivo_base64 = operacion.archivo_base64;

     respuesta = almacenar(archivo_name,archivo_type,archivo_base64);

  }else if (operacion.op == "ftp_descargar"){

     var archivo_name = operacion.archivo_name;

     respuesta = descargar(archivo_name);

  } 

  return ContentService.createTextOutput(respuesta).setMimeType(ContentService.MimeType.JSON);

}

function descargar(archivo_name){

  

  var folder_ = DriveApp.getFolderById(folderurl); 

  var files_ = folder_.getFilesByName(archivo_name);

  var jo = {};

  jo.status = '1';

  jo.message = 'No existe el archivo'; 

  while (files_.hasNext()) {

    var archivo_=files_.next();          

    var encoded = Utilities.base64Encode(archivo_.getBlob().getBytes());

    jo.status = '0';

    jo.message = 'Existe el archivo'; 

    jo.archivo_base64 =encoded;

    existe = true;

  }     

  var result = JSON.stringify(jo); 

  return result;        

}

function almacenar(archivo_name,archivo_type,archivo_base64){

  

  var decoded = Utilities.base64Decode(archivo_base64);

  var image = Utilities.newBlob(decoded,archivo_type,archivo_name);

  var folder_ = DriveApp.getFolderById(folderurl); 

 // SE CREA EL ARCHIVO

  var file = folder_.createFile(image);

  var jo = {};

  jo.status = '0';

  jo.message = 'Exito';

  jo.urlpublica = "https://drive.google.com/uc?id="+file.getId();

  var result = JSON.stringify(jo); 

  return result;        

}





Tienda online confirmación pedido whatsapp

 A continuación se muestra una solución  de una tienda online con confirmacion del pedido como mensaje a whatsapp  se emplea google APP Script, google Sheet, blogger , esta realizada con HTML 5 Responsive - Jquery se alinea a diversos tipos de navegadores Web y Mobile.

¿ Que necesitas para implementarlo ?

- SOLO  una cuenta de GMAIL

- Abrir URL Blogger

LINK APLICACIÓN :

https://carritoventaswhatsapp.blogspot.com/

EXCEL APLICACIÓN :

https://docs.google.com/spreadsheets/d/19SO8cTBJlzrDHNiQ2CR9qEFtso8BqYXj8ZkEq6jff1I/edit?usp=sharing

VIDEO APLICACION :

FUENTES APLICACIÓN :

Para obtener las fuentes tiene un costo $ 4.00.

IR a PAGAR 4 DOLARES

NOTA : Luego del pago se redireccionara a una carpeta para descargar las fuentes

ASESORIA PERSONALIZADA :

En caso necesites alguna asesoría personalizada agéndame un espacio.

https://reservarasesoriaanlusoft.blogspot.com/

jueves, 6 de octubre de 2022

BOT Whatsapp de reserva de vehiculo con confirmación a grupos

 Hola a continuación le dejo material para que puedan implementar un BOT Whatsapp que le permite reserva vehiculos de tipo taxis , motos y otros y que permite reenviar la confirmación de la reserva a un Grupo de Whatsapp

1) Conversele al numero de celular .

2) El BOT trabaja con la siguiente hoja sheet se iran almacenado los registros ahi,

https://docs.google.com/spreadsheets/d/1YDrkpt7cuovZoMcyrZbcQjVafD6F2NZAOQe1TiMDVdY/edit?usp=sharing

¿ Necesitas implementarlo tu mismo para realizar cambios ?

- Crear la hoja Google sheet como indica el video 

         - Escanear la hoja para obtener token QR

Video Implementación


Pasos de ejecución

Luego de haber copiado el código appscript y desplegarlo , ejecutar la funcion onOpen y se mostrara un menu de opciones Whatsapp , iniciar con el paso 1 y se mostrara codigo QR que debe escanearlo con su Whatsapp y se obtendra token de session en la celda 3B

Luego ejecutar el paso 2 Menu Whatsapp se iniciara el BOT

Esperar 10 seg a que aparesca el menu Whatsapp

Código AppScript 


var excel_qr = SpreadsheetApp.getActiveSpreadsheet();

var sheet_qr = excel_qr.getSheetByName("Configuracion");

var sheet_informacion = excel_qr.getSheetByName("Informacion");

var sheet_solicitud = excel_qr.getSheetByName("Solicitud");

var rows_solicitud = [];

var gmt = "GMT-5";

try {

  rows_solicitud = sheet_solicitud.getRange(2, 1, sheet_solicitud.getLastRow() - 1, sheet_solicitud.getLastColumn()).getValues();

} catch (ee) {

}

var api_interna = "https://script.google.com/macros/s/AKfycbyoBhxuklU5D3LTguTcYAS85klwFINHxxd-FroauC4CmFVvS0ua/exec";

var token_session = "" + sheet_qr.getRange(3, 2).getValue()

function onOpen() {

  createMenus();

}

function createMenus() {

  var menu = SpreadsheetApp.getUi().createMenu("Whatsapp");

  menu.addItem('1) Obtener TOKEN Session - QR Whatsapp', 'qrwhatsapp');

  menu.addItem('2) Habilitar BOT - Whatsapp', 'enviarconversacion_v2');

  menu.addItem('3) Recuperar Grupo Whatsapp', 'recuperargrupos');

  menu.addToUi();

}


function recuperargrupos() {


  var response = "No"

  var token_session = "";

  try {

    token_session = sheet_qr.getRange(3, 2).getValue();

    var response = Browser.msgBox('Seguro que quiere recuperar grupos del token de session sera : ' + token_session + ' ?', Browser.Buttons.YES_NO);

  } catch (e) {

    Browser.msgBox('La acción no se ha realizado', Browser.Buttons.OK);

  }

  if (response == "yes") {

    var dataArray = [{ "mensaje": "grupo" }];

    var payload = { "op": "registermessage", "token_qr": token_session, "listener": "true", "grupos": dataArray };

    var options =

    {

      'headers': { "Content-Type": "application/json" },

      'method': "POST",

      'payload': JSON.stringify(payload)

    };

    try {

      var response = UrlFetchApp.fetch(api_interna, options);

      var json = JSON.parse(response.getContentText());

      if (json.status == "0") {

        Browser.msgBox('Se habilito el BOT para recuperar grupos ', Browser.Buttons.OK);

      } else {

        Browser.msgBox('Error al iniciar : ' + json.message, Browser.Buttons.OK);

      }

    } catch (e) {

      Browser.msgBox('Se habilito el BOT para recuperar grupos asincrono ', Browser.Buttons.OK);

    }

  }

}


function doPost(e) {


  var operacion = JSON.parse(e.postData.contents)

  var respuesta = "";

  console.log("INICIO", JSON.stringify(operacion));

  if (operacion.op == "qr") {

    respuesta = generar(JSON.stringify(operacion));

  } else if (operacion.op == "find_conversacion") {

    sheet_informacion.appendRow(["JSON ENTRADA", new Date(), operacion]);

    respuesta = enviar_bot(JSON.stringify(operacion), "Whatsapp");

    sheet_informacion.appendRow(["JSON SALIDA", new Date(), respuesta]);

  } else if (operacion.op == "grupos") {

    respuesta = grupos(JSON.stringify(operacion));

  }

  return ContentService.createTextOutput(respuesta).setMimeType(ContentService.MimeType.JSON);

}


function grupos(informacion) {

  try {

    var resultado = JSON.parse(informacion);

    sheet_qr.getRange(6, 2).setValue(JSON.stringify(resultado.mensajes));

    var result, jo = {};

    jo.status = '0';

    jo.message = ' Se grabo el registro';

  } catch (e) {

    jo.status = '-1';

    jo.message = e.toString();

  }

  var result = JSON.stringify(jo);

  return result;

}


function enviar_bot(messague) {

  var conversacion_ingresado = {};

  try {


    var mensaje_json = JSON.parse(messague);

    if (mensaje_json.mensaje == "documento_send") {

      base64 = mensaje_json.documento.data;

      mensaje_json.documento.data = "Se puso vacio";

    } else if (mensaje_json.mensaje == "ubicacion_send") {

      mensaje_buscar = "ubicacion_send";

    } else {

      mensaje_buscar = mensaje_json.mensaje;

    }

    numero_enviar = (mensaje_json.numero).substring(0, (mensaje_json.numero).lastIndexOf("@"));

    /* se recupera la session del cached en caso exista*/

    var cache = CacheService.getScriptCache();

    var conversaciones = [];

    if (cache.get("conversaciones") != null) {

      conversaciones = JSON.parse(cache.get("conversaciones"));

    }

    // RECORREMOS LAS CONVERCACION PARA CONOCER EL EVENTO

    var sheet = excel_qr.getSheetByName("Conversacion");

    var rows = sheet.getRange(2, 1, sheet.getLastRow() - 1, sheet.getLastColumn()).getValues();

    var evento = rows.find((item) => item[1].split(";").includes((mensaje_buscar + "").toUpperCase()));

    var evento_error = rows.find((item) => item[0] === "Error");

    if (evento === undefined) {

      var filtroconversacion = conversaciones.filter((item) => item.numero == numero_enviar);

    sheet_informacion.appendRow(["filtroconversacion",new Date(),JSON.stringify(filtroconversacion)]);


      evento = evento_error;

      if (filtroconversacion.length > 0) {

        var evento_retorno = filtroconversacion[filtroconversacion.length - 1].retornar;

        var evento_retornar = rows.find((item) => evento_retorno != "" && item[0] === evento_retorno);

        if (evento_retornar !== undefined) {

          evento = evento_retornar;

        } else {

          // CASO SEAN ARREGLOS ::

          var evento_retorna_arreglo_menu = evento_retorno.split(";");

          if (evento_retorna_arreglo_menu.length > 1) {

            for (let jl = 0; jl < evento_retorna_arreglo_menu.length; jl++) {

              var evento_msj = evento_retorna_arreglo_menu[jl].split(",");

              if ((evento_msj[1] + "") === ("" + mensaje_buscar)) {

                var evento_retornar_menu = rows.find((item) => item[0] === evento_msj[0]);

                if (evento_retornar_menu !== undefined) {

                  evento = evento_retornar_menu;

                  break;

                }

              }

            }

          }

        }

      }

    }

    if (evento[0] == "Error" && evento_start && evento_start[1].includes("%%%")) {

        evento = evento_start;

    }

    var conversacion_ingresado = { status: "0", tipo: "mensaje", numero: numero_enviar, mensaje_entrada: mensaje_buscar, evento: evento[0], retornar: evento[3], mensaje_salida: evento[2] };

    var flag_close = false;

    sheet_informacion.appendRow(["evento",new Date(),JSON.stringify(conversacion_ingresado)]);

    if (conversacion_ingresado.evento == "Start") {

      // VALIDAMOS SI EXISTE NOMBRE   

      var evento_nombre = rows_solicitud.findLast((item) => item[2]+"" === ""+numero_enviar);

      var mensajes_ = [];

      if(evento_nombre){

        conversacion_ingresado.temporal_nombre = evento_nombre[3];

        var mensaje_evento = rows.find((item) => item[0] === "MenuInicio");

        mensajes_.push({ "tipo": "mensaje", "mensaje_salida": conversacion_ingresado.mensaje_salida.replace("@nombre@",evento_nombre[3])});

        mensajes_.push({ "tipo": "mensaje", "mensaje_salida": mensaje_evento[2]});

        conversacion_ingresado.retornar=mensaje_evento[3];

      }else{  

        var mensaje_evento = rows.find((item) => item[0] === "Solicitar_Nombre");

        mensajes_.push({ "tipo": "mensaje", "mensaje_salida": conversacion_ingresado.mensaje_salida.replace("@nombre@","") })

        mensajes_.push({ "tipo": "mensaje", "mensaje_salida": mensaje_evento[2] })

        conversacion_ingresado.retornar=mensaje_evento[3];

      }

      conversacion_ingresado.tipo = "";

      conversacion_ingresado.mensaje_salida = "";

      conversacion_ingresado.mensajes = mensajes_;

    } else if (conversacion_ingresado.evento == "Deseo_Que_Me_Atienda_Una_Persona") {

      flag_close = true;

    } else if (conversacion_ingresado.evento == "End_Ver_Mis_Reservas") {

      var mensaje_ = rows.find((item) => item[0] === "End_Ver_No_Existe_Mis_Reservas")[2];

      var contador = 0;

      for (var i = 0; i < rows_solicitud.length; i++) {

        var dataRow = rows_solicitud[i];

        if ((dataRow[2] + "") === "" + numero_enviar && dataRow[7] === "Pendiente") {

          if (contador == 0) {

            mensaje_ = conversacion_ingresado.mensaje_salida +"\n";

          }

          mensaje_ += (i + 1) + " " + dataRow[1] + " " + dataRow[6] + "\n";

          contador = contador + 1;

        }

      }

      conversacion_ingresado.mensaje_salida = mensaje_;

      flag_close = true;

    } else if (conversacion_ingresado.evento == "End_Solicitar_Taxi_Ahora" || conversacion_ingresado.evento == "End_Solicitar_Taxi_Reservar") {

      var direccion_cliente = "";

      if (mensaje_json.mensaje === "ubicacion_send") {

        ubicacion_cliente = mensaje_json.documento.latitud + "," + mensaje_json.documento.longitud;

        var response = Maps.newGeocoder().reverseGeocode(mensaje_json.documento.latitud, mensaje_json.documento.longitud);

        for (var iz = 0; iz < response.results.length; iz++) {

          direccion_cliente = response.results[iz].formatted_address;

          break;

        }

      }

      var conversaciones_final = conversaciones.filter((item) => item.numero == conversacion_ingresado.numero);

      var tipo_vehiculo = "Auto";

      var evento_tipo_vehiculo = (conversaciones_final.find((item) => item.evento == "Solicitar_Vehiculo_Tipo_Ahora"));

      if (evento_tipo_vehiculo && evento_tipo_vehiculo.mensaje_entrada == "2") {

        tipo_vehiculo = "Moto";

      }

      var nombre = "";

      var evento_nombre = (conversaciones_final.find((item) => item.evento == "MenuInicio"));

      var evento_start = (conversaciones_final.find((item) => item.evento == "Start"));

      nombre = (evento_nombre && evento_nombre.mensaje_entrada ? evento_nombre.mensaje_entrada : evento_start.temporal_nombre);

      var fecha_solicitud = "." + Utilities.formatDate(new Date(), gmt, "yy-MM-dd HH:mm");

      if (conversacion_ingresado.evento == "End_Solicitar_Taxi_Reservar") {

        var evento_reserva = (conversaciones_final.find((item) => item.evento == "Solicitar_Taxi_Reservar"));

        fecha_solicitud = (evento_reserva ? evento_reserva.mensaje_entrada : "Sin Fecha");

      }

      var mensaje = (conversacion_ingresado.mensaje_salida + "").replace("@fechahora@", fecha_solicitud).replace("@celular@", numero_enviar).replace("@nombre@", nombre).replace("@direccion_cliente@", direccion_cliente).replace("@gps@", "https://maps.google.com/?q="+ubicacion_cliente).replace("@tipo@", ubicacion_cliente);

      if (tipo_vehiculo == "Moto") {

        conversacion_ingresado.numeroreenviar = sheet_qr.getRange(4, 2).getValue();

      } else {

        conversacion_ingresado.numeroreenviar = sheet_qr.getRange(5, 2).getValue();

      }

      conversacion_ingresado.mensaje_salida = mensaje;

      conversacion_ingresado.reenviar = mensaje;

      sheet_solicitud.appendRow([new Date(), fecha_solicitud, numero_enviar, nombre, tipo_vehiculo, ubicacion_cliente, direccion_cliente, 'Pendiente', JSON.stringify(conversaciones_final)]);

      flag_close = true;

    }


    // SE PONE PUSH

    conversaciones.push(conversacion_ingresado);

    // FIN DE ENVIO A TELEGRAM

    if (evento[0].includes("Start") || flag_close) {

      var result_numero = conversaciones.filter(item => item.numero !== numero_enviar);

      if (result_numero === undefined || result_numero.length == 0) {

        conversaciones = [];

      } else {

        conversaciones = result_numero;

      }

      conversaciones.push(conversacion_ingresado);

    }

    cache.put('conversaciones', JSON.stringify(conversaciones), 240);

  } catch (e) {

    sheet_qr.getRange(11, 11).setValue(e.toString());

    conversacion_ingresado = { status: "-1", message: e.toString() };

  }

  // CALCULO DEL TIPO DE MENSAJE

  if (conversacion_ingresado.tipo == "mensaje" && (conversacion_ingresado.mensaje_salida + "").includes("@@@")) {

    var mensajes_ = [];

    var _lst_ = (conversacion_ingresado.mensaje_salida).split("@@@");

    for (var ii = 0; ii < _lst_.length; ii++) {

      if (_lst_[ii]) {

        if (_lst_[ii].includes("http")) {

          mensajes_.push({ "tipo": "url", "mensaje_salida": _lst_[ii] })

        } else if (_lst_[ii].length > 5) {

          mensajes_.push({ "tipo": "mensaje", "mensaje_salida": _lst_[ii] })

        }

      }

    }

    conversacion_ingresado.tipo = "";

    conversacion_ingresado.mensaje_salida = "";

    conversacion_ingresado.mensajes = mensajes_;

  }

  return JSON.stringify(conversacion_ingresado);

}


function generar(informacion) {

  try {

    var qr = JSON.parse(informacion);

    sheet_qr.getRange(2, 2).setValue(encodeURIComponent(qr.qr));

    var result, jo = {};

    if (qr.numero && qr.qr == "CONECTADO") {

      sheet_qr.getRange(3, 2).setValue(qr.session);

    }

    jo.status = '0';

    jo.message = ' Se grabo el registro';


  } catch (e) {

    jo.status = '-1';

    jo.message = e.toString();

  }

  var result = JSON.stringify(jo);

  return result;

}

function qrwhatsapp() {

  var response = "No"

  try {

    //        sheet_qr.getRange(3, 2).setValue("");

    var response = Browser.msgBox('Seguro que quiere generar QR ahora ?', Browser.Buttons.YES_NO);

  } catch (e) {

    Browser.msgBox('La acción no se ha realizado', Browser.Buttons.OK);

  }

  if (response == "yes") {

    enviar();

    Browser.msgBox('La acción ha sido realizada, escanear registros luego de 10 segundos', Browser.Buttons.OK);

  }

}

function enviar() {

  var appscript = sheet_qr.getRange(1, 2).getValue();

  var payload = { "op": "iniciarqr", "app_script": appscript, "sheet_id": excel_qr.getId(), "fechahora": Utilities.formatDate(new Date(), "GMT-5", "yyMMddHHmmss") };

  var options =

  {

    'headers': { "Content-Type": "application/json" },

    'method': "POST",

    'payload': JSON.stringify(payload)

  };

  try {

    var response = UrlFetchApp.fetch(api_interna, options);

    var json = JSON.parse(response.getContentText());

  } catch (e) {

  }

}

function enviarconversacion_v2() {

  var response = "No"

  try {

    var response = Browser.msgBox('Seguro que quiere habilitar el BOT con la conversacion, el token de session sera : ' + token_session + ' ?', Browser.Buttons.YES_NO);

  } catch (e) {

    Browser.msgBox('La acción no se ha realizado', Browser.Buttons.OK);

  }

  if (response == "yes") {

    var appscript = sheet_qr.getRange(1, 2).getValue();

    var dataConversacion = [{ "inicio": "datos" }, { "inicio": "datos" }];

    var payload = { "op": "sendmessagewk", "error_en_grupos": sheet_qr.getRange(4, 8).getValue(), "token_qr": token_session, "conversacion_bot": dataConversacion, "app_script": appscript };

    var options =

    {

      'headers': { "Content-Type": "application/json" },

      'method': "POST",

      'payload': JSON.stringify(payload)

    };

    try {

      var response = UrlFetchApp.fetch(api_interna, options);

      var json = JSON.parse(response.getContentText());

      if (json.status == "0") {

        Browser.msgBox('Se habilito el BOT inicie la conversacion ', Browser.Buttons.OK);

      } else {

        Browser.msgBox('Error al iniciar : ' + json.message, Browser.Buttons.OK);

      }

    } catch (e) {

      Browser.msgBox('Se habilito el BOT inicie la conversacion ', Browser.Buttons.OK);

    }

  }

}



SI DESEA HABILITAR EL BOT 24 x 7 ?

La solución BOT emplea Web Whatsapp  para recibir y enviar mensajes , por lo cual es necesario la contratación de un servidor para el BOT este operativo 24 x 7  , debido a ello existe un pago mensual de $ 8.00 .

IR a PAGAR 8 DOLARES

ASESORIA PERSONALIZADA :

En caso necesites alguna asesoría personalizada agéndame un espacio.

https://reservarasesoriaanlusoft.blogspot.com/

WHATSAPP BOT con IA GPT-4o

  Hola a continuación le dejo material para que puedan implementar un BOT whatsapp usando IA de Chat GPT modelo 4o Pasos: 1) Crear usuario y...