martes, 7 de enero de 2020

miércoles, 6 de noviembre de 2019

sábado, 24 de marzo de 2012

Actualizando Sugar CRM CE 6.2.1 a 6.4.2

En este ultimo año he estado trabajando con Sugar CRM CE, y he realizado al menos una actualización mediante el panel de administración. Esto ocurría mientras la empresa para la que trabajo no tenia tantos datos almacenados. Pero ahora creo que este procedimiento lo tengo que llevar a cabo con mucho cuidado.
Como toda actualización que he llevado en la vida, la primer prueba actualización de Sugar CRM que la lleve a cabo la realice sin leer el change log de la nueva versión, y como resultado me encuentro que ciertas cosas han cambiado y que al querer ocupar el sistema, ¡Sorpresa! Han dejado de funcionar módulos. Lo bueno es que la actualización la hice sobre una copia. Siempre hay que seguir esta regla, hacer una copia de los archivos y también una copia de la base de datos.
Una cosa que me ayudo también a realizar la actualización es tener versionado el directorio de Sugar con Git :). Como siempre hacemos el primer commit.
Ahora tengo una versión que después de realizar cambios puedo regresar al punto donde se encuentra sin modificar. Como la copia que tengo es del Sugar que ocupo en producción, he creado una base de datos de prueba a la que he restaurado los datos de la base de producción, la cual montare cada que quiera volver a hacer una nueva prueba. Y por logica debo de modificar el archivo config.php con la información de la base de datos de pruebas.
Ahora si, ha empezar la actualización.

Actualización con el Wizard del panel de administración

Para empezar realice el intento mediante la interfaz gráfica descargando el parche de actualización correspondiente a la versión 6.2.x a 6.4.0. Entro al panel de administración y escojo la opción Asistente de Actualización. Una vez dentro, se realiza una comprobación automática del sistema y me encuentro con el primer problema. Los archivos que se generan con al inicializar el repositorio git no tienen permiso de escritura. Como fue el unico problema que se me presentó en este paso por medio de la consola de mi navegador ejecuto el script del botón siguiente, para continuar con la instalación, el codigo es el siguiente:
En el siguiente paso tenemos que cargar el archivo de actualización, y aqui viene el siguiente error. Una vez que termino de cargar el archivo SugarCR-Upgrade-6.2.x-to-6.4.0, no aparece en la lista de parches.

Y el problema no acaba ahí, una vez que actualizo la pagina aparece el siguiente mensaje de error:
Fatal error: Class 'UploadFile' not found in C:\xampp\htdocs\sugarcrm_s\sugarcrm\modules\UpgradeWizard\upload.php on line 85
Ahora ¿¡Que hago!?

Actualización con silentUpgrade

Y cuando el mundo se cierra y parece todo perdido, Sugar CRM proporciona una solución alterna para actualizar. Desde la versión 6.2 existe silentUpgrade, el cual es una herramienta para evitar algunas limitaciones con las que se puede topar uno al tratar de realizar una actualización con la interfaz gráfica, por ejemplo el limite de carga de archivos de php, permisos de escritura, tiempos de espera limite.
Primero descargamos el paquete de la pagina de Sugar CRM que corresponde con la versión que tenemos y hacia la que vamos a actualizar, de preferencia en una carpeta de fácil acceso. Posteriormente extraemos el contenido del paquete y mediante linea de comandos ejecutamos la siguiente linea:
Con forme a la documentación de Sugar CRM los parametros son los siguientes
    upgradeZipFile
    Ruta física donde se encuentra el archivo Zip de la actualización
    logFile
    Ruta física donde se almacenará el archivo de bitacora de la actualización
    pathToSugarInstance
    Ruta física donde se encuentra la instancia de Sugar CRM a actualizar
    adminUser
    Usuario administrador que esta realizando la actualización
Aqui me encuentro con un pequeño problema, la versión vigente es 6.4.2 y no existe paquete para realizar actualización de la versión 6.2.x a la versión 6.4.2, apenas hace unos dias habia descargado la actualización SugarCE-6.2.x-to-6.4.0.zip y ahora no aparece, con lo cual realizaríamos una actualización escalando primero a la versión 6.4.0, para posteriormente realizar una actualización a la versión 6.4.2.
Por lo tanto el comando para la actualización quedaría de la siguiente forma:
Al iniciar la ejecución nos aparecerá un mensaje como el siguiente:
Tal y como indica el mensaje, realmente toma varios minutos en terminar la actualización, al rededor de 20 minutos. Si todo sale bien, aparece el siguiente mensaje:
Y como indica el mensaje, debemos de entrar a Sugar CRM y realizar una reparación para reconstruir las relaciones entre los módulos. Pero como habíamos prometido actualizar a la versión 6.4.2, haríamos los pasos anteriores pero con el paquete SugarCE-6.4.x-to-6.4.2.zip

Listo, ya tenemos actualizado Sugar CRM CE a la versión 6.4.2, primero a revisar que las extensiones de terceros sirvan y posteriormente a disfrutar las mejoras de esta nueva versión

Saludos

martes, 7 de septiembre de 2010

Doodle de Google, con jQuery


Tanto misterio rodea el nuevo doodle de Google, tanto que medio mucha curiosidad. La semana pasada nos presentaba un doodle al parecer con canvas en el cual se animaba la molecula de carbono, pero gran sorpresa me dio ver que este doodle estaba hecho con puros div's.

Despues de muchas vesiones, logre que quedara algo similar, mis respetos para los desarrolladores de Gooogle. Mi version la pueden checar en este link.

HTML
El codigo html ha sido algo de lo mas sencillo, un conjunto de div's, los cuales van a estar colocados en la posicion deseada, como es un copia de la idea, el tamaño de los mismos es aleatorio.


CSS
En este punto basta con indicarle que tendra una posicion se absoluta, y sobre todo, las clases para los colores. El top y left asi como el ancho y alto los he definido en el atributo style de cada div.

Javascript
Primer paso: Almacenar posicion y tamaño. Como la idea que es las particulas(div's) anden volando por toda la pantalla, y para que se vea mas espectacular, cambien de tamaño, es necesario el almacenamiento de los datos iniciales de cada particula. Con la funcion data(), asigno un objeto que contiene dichos datos para recuperarlos porteriormente.

$('#mip').find('div.particle').each(function(){
var oPosition = $(this).position();
oPosition.width = $(this).width();
$(this).data('offset',oPosition);
});

[Inicio de Actualizacion]
Paso 1.1: Deten la propagacion del evento: Refinando el codigo, encontre que cuando de casualidad el mouse llega a tocar una particula genera un evento mousemove, el cual por Bubbling es capturado por el evento mousemove del contenedor de las particulas, con los cual es importante detener la progagacion del evento

$('#mip div.particle').mousemove(function(e){
e.stopPropagation();
});

[Fin de Actualizacion]
Segundo paso: Escuchador del evento. Asigno un escuchado al evento mousemove del div que contiene a las particulas.

$('#mip').mousemove(function(e){//codigo});

Tercer paso: El movimiento de la particula. Una vez que se genera el evento mousemove se obtiene datos y se realizan los siguientes calculos:
a) ¿Donde esta la particula? Con la funcion position obtengo un objeto que me proporciona el top y left actual de la particulas dentro del div contenedor

o = $(this).position();

b) ¿Que tanto se va a alejar la particula? Por medio de dos numero generados aleatoriamente, rx y ry.

ry = Math.floor(Math.random()*200);
rx = Math.floor(Math.random()*200);

c) ¡Ahi viene el mouse! Tal parece que las particulas no va a ser amigas del mouse, se valida que el mouse este los suficientemente cerca de la particula, en este caso ocupo una variable m que define el margen alredor, entre comillas (toma el top y left a partir del cual esta dibujada la particula, pero casi no se nota), de la particula.

ex = e.layerX;
ey = e.layerY;
if(
((o.top<=ey&&(o.top+m)>ey)&&(o.left<=ex &&(o.left+m)>ex))||
((o.top>ey&&(o.top-m)<=ey)&&(o.left<=ex &&(o.left+m)>ex))||
((o.top<=ey&&(o.top+m)>ey)&&(o.left>ex &&(o.left-m)<=ex))||
((o.top>ey&&(o.top-m)<=ey)&&(o.left>ex &&(o.left-m)<=ex))
)

d) ¿De que lado viene el mouse? Se determina de que lado de la particula se genero el evento,
con lo cual los valores almacenado en rx y ry se sumaran o restaran en el sentido contrario
con respecto al punto donde se genero el evento.

y = o.top<=ey?((o.top+m)<=ey?o.top:o.top-(ry+m)):
((o.top-m)>ey?o.top:o.top+(ry+m));
x = o.left<=ex?((o.left+m)<=ex?o.left:o.left-(rx+m)):
((o.left-m)>ex?o.left:o.left+(rx+m));

e) ¡Muevete! Para animar las particulas ocupo la funcion animate, a la cual se le pasa como primer parametro los datos calculados(top,left,ancho,alto,opacidad) almacenados en un objeto, como segundo parametro otro objeto el cual va a tener la duracion, el tipo de movimiento para los estilos, en este caso el top y left; y por ultimo la funcion callback, la cual hara que regrese la particula a su lugar.

h = Math.floor(Math.random()*100);
op = {top:y,
left:x,
width:rx,
height:rx,
opacity:(Math.floor(Math.random()*100)/100)}
$(this)
.stop()
.animate(op,
{duration:randomFromTo(500,1000),
specialEasing:{top:'easeOutBounce',
left:'easeOutBounce'},
complete:function(){/*Regresa la particula*/});

Cuarto Paso: I'll be back. Por ultimo la particula debe de regresar al lugar que le corresponde y con la misma forma, con lo cual se obtiene los datos almacenados en la particula y asginarlos a sus correspondientes atributos de estilo.

y = $(this).data('offset').top;
x = $(this).data('offset').left;
h = $(this).data('offset').width;
$(this).animate({top:y,
left:x,
width:h,
height:h,
opacity:1},
{duration:randomFromTo(800,1000),
specialEasing:{top:'easeOutBounce',
left:'easeOutBounce'}});


He aqui el codigo completo

Me he divertido mucho haciendo este codigo. Cualquier duda, comentario o apartacion seran bien recibido.

Saludos.

sábado, 21 de agosto de 2010

Ocultar elemento flotante al dar click fuera de él con jQuery


Durante el desarrollo de un plugin de jQuery ya hace mucho tiempo me encontre con el problema de hacer desaparecer un elemento flotante cuando daban click fuera de él. Como la historia tiende a repetirse hoy me he encontrado con el mismo problema.

Elementos:
Lista - Elemento Flotante
Boton - Encargado de mandar a mostrar la lista

Solucion:

Asigno un manejador de eventos al click del document, en el cual valido 4 cosas
1) La lista este visible
2) El click no sea generado por la lista
3) El click no sea generado por el boton
4) El click no sea generado por algun elemento dentro de la lista

Si el conjunto de estas condiciones se cumple entonces oculto el elemento.

Bueno el primer paso es facil

var oMiLista = $('#foo');
$(document).bind('click',function(event){
if(oMiLista.is(':visible')){ //Facil
alert('Oculta la lista');
}
});

Comparacion de objetos.

Parace facil, solo comparo los objetos y ya quedo. Pero, ¡Oh sorpresa! no se puede ralizar una comparación de la forma:


var oMiLista = $('#foo');
$(document).bind('click',function(event){
if(oMiLista.is(':visible') && $(event.target) != oMiLista){
alert('Oculta la lista');
}
});

Esto es por que la comparación se debe de realizar con los objetos en bruto. Con lo cual la comparación quedaria de la siguiente manera:

var oMiLista = $('#foo');
$(document).bind('click',function(event){
if(oMiLista.is(':visible') && event.target != oMiLista[0]){//event.target == oMiElemento.get(0)
alert('Oculta la lista');
}
});

Bueno, con esto se solucionan los pasos 2 y 3, ahora hay que buscar entre los elementos de la lista. Para esto busco los elementos padres del event.target con la funcion parents(), mapeo los elementos resultantes y los devuelvo en bruto, generando un arreglo con ellos. Por ultimo valido que la lista no se encuentre dentro del arreglo con la funcion inArray(), la cual tiene que devolver el valor -1. Asi que todo esto quedaria de la siguiente manera:


var oMiLista = $('#foo');
var oMiBoton = $('#bar');
$(document).bind('click',function(event){
if(oMiElemento.is(':visible') &&
event.target != oMiLista[0]&&
event.target != oMiBoton[0]&&
jQuery.inArray(oMiLista[0],$(event.target).parents().map(function(){return this}).get()) == -1
{
alert('Oculta la lista');
}
});


Les dejo un ejemplo practico aqui, espero que les sea de ayuda.

Saludos

jueves, 19 de agosto de 2010

Empezando con C#, no hay de otra


Empezando con un nuevo captitulo de programación, expandiendo el conocimiento y abriendo los horizontes. Gracias a una señal, el dia de hoy voy a empezar a recorer mi camino en los senderos de C#.

Es un lenguaje con el que tuve mi primer contacto en la universidad. Solo fueron un par de meses lo que tuve para conocerlo, no le di seguimiento, pero a esta altura de mi vida, he visto la necesidad que tengo por aprenderlo.

Ya que cuento con Ubuntu y no me vere en la situación de iniciar mi maquina en Window$, ya que gracias a Mono, podré practicar.

Siguiendo los pasos que encontre aqui.

Luego entonces escribir y ejecutar el programa mas escrito en la historia de la computación:


using System;
namespace HolaMundo
{
public class HolaMundo
{
public static void Main(String [] args){
System.Console.WriteLine("Hola mundo");
}
}
}



"Hola mundo". Jejeje ha sido un buen comienzo

martes, 17 de agosto de 2010

Como ser un Javascript Ninja y si tu quieres mas...


He aqui un buen articulo que nos descubre algunas de las tecnicas para ser un Javascript Ninja.

http://bit.ly/9QpFzW

Este articulo me inviata a la constancia y perseverancia, al fin al cabo no aprendere todo en el mundo, pero espero aprender los conocimientos necesarios para enfrentarme a lo que me pongan en frente.