Continuando con post anteriores sobre esquemas algorítmicos. Dejo aquí unas pruebas empíricas sobre cómo calcular el Número de Fibonacci de números grandes. Si vemos la definición de Fibonacci es la siguiente:
Continuar leyendo..Continuando con post anteriores sobre esquemas algorítmicos. Dejo aquí unas pruebas empíricas sobre cómo calcular el Número de Fibonacci de números grandes. Si vemos la definición de Fibonacci es la siguiente:
Continuar leyendo..Otro HOWTO, code-kata, a traer vengo hoy..
XDD vengo con este post cargado de esquemas algorítmicos para programar. Estos esquemas algorítmicos son los que nos ayudan a programar las mejores soluciones. Así conseguimos llegar a las soluciones que a veces tenemos que encontrar, pero quizá no vemos en un principio cómo. Quizá el problema lo tenemos en que tarda mucho, o necesitamos demasiado espacio de almacenamiento.
Continuar leyendo..Hoy traigo otro code-kata, esta vez para Magento y hecho en PHP. Se trata de un simple script que se lanza en línea de comandos. Con este script obtendremos primero todos los métodos de pago que se han usado al hacer los pedidos. Después, haremos un listado, por método de pago, y entre ciertas fechas, del monto de pedidos completados por método de pago.
Es decir, supongamos que queremos saber cómo han ido las ventas con el método de pago por tarjeta de crédito. O quizá queremos saber si la financiación es un método de pago que funciona bien. O quizá simplemente queremos tener el total de ventas entre fechas.
Pues todo esto es bastante sencillo sabiendo donde está cada cosa.
A saber, los pedidos en Magento 1 guardan parte de sus datos principales en la tabla sales_flat_order. La información del método de pago utilizado en cada pedido se guarda en la tabla sales_flat_order_payment.
Entonces, sacando la columna method de la tabla sales_flat_order_payment tendremos todos los métodos de pago utilizados en los pedidos. Esto en lenguaje SQL queda así:
SELECT distinct(sfop.method) FROM sales_flat_order_payment sfop ORDER BY sfop.method ASC;
El siguiente paso será saber cómo sacar las cantidades de los pedidos completados. A saber, los pedidos completados se quedan con un status=complete y state=complete. Sí, es raro, Magento tiene internamente dos estados en cada pedido. Uno llamado status y otro llamado state. Estos estados están respectivamente en sus columnas. Así la consulta a la base de datos en SQL para sacar las ventas de un método de pago queda así:
SELECT sum(sfo.grand_total) total_sold FROM sales_flat_order sfo JOIN sales_flat_order_payment sfop ON sfop.parent_id = sfo.entity_id WHERE sfo.state = 'complete' AND sfo.state = 'complete' AND sfop.method LIKE '".$methodCode."' AND sfo.created_at > '".$startDate->format('Y-m-d H:i:s')."' AND sfo.created_at < '".$endDate->format('Y-m-d H:i:s')."'"
Fíjate que la tabla sales_flat_order_payment se relaciona con sales_flat_order de la forma que marco en negrita.
Ahora bien, haciendo un poco de ejercicio con un par de bucles, programando el script completo, nos queda algo tal que así:
<php require_once __DIR__.'/app/Mage.php'; Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID); // Loading arguments. if ($argc == 3) { $yearFrom = $argv[1]; $yearTo = $argv[2]; } else { echo 'ERROR: Incorrect number of arguments.'.PHP_EOL; exit; } $sqlConnection = Mage::getSingleton('core/resource')->getConnection('core_read'); // Loading available method codes. $query = 'SELECT distinct(sfop.method) FROM sales_flat_order_payment sfop ORDER BY sfop.method ASC;'; $methods = $sqlConnection->fetchAll($query); $methodCodes = array(); foreach ($methods as $method) { $methodCodes[] = $method['method']; } //var_dump($methodCodes); // Printing table in CSV format from January to December.. echo 'PAYMENT_METHOD'; for ($year = $yearFrom; $year <= $yearTo; ++$year) { for ($month = 1; $month <= 12; ++$month) { echo ','.$year.$month; } } echo PHP_EOL; foreach ($methodCodes as $methodCode) { echo $methodCode; for ($year = $yearFrom; $year <= $yearTo; ++$year) { for ($month = 1; $month <= 11; ++$month) { $startDate = new DateTime($year.'-'.$month.'-1 00:00:00'); //echo 'Date from: '.$startDate->format('Y-m-d H:i:s').PHP_EOL; $endDate = new DateTime($year.'-'.($month + 1).'-1 00:00:00'); //echo 'Date to: '.$endDate->format('Y-m-d H:i:s').PHP_EOL; $query = "SELECT sum(sfo.grand_total) total_sold FROM sales_flat_order sfo JOIN sales_flat_order_payment sfop ON sfop.parent_id = sfo.entity_id WHERE sfo.state = 'complete' AND sfo.state = 'complete' AND sfop.method LIKE '".$methodCode."' AND sfo.created_at > '".$startDate->format('Y-m-d H:i:s')."' AND sfo.created_at < '".$endDate->format('Y-m-d H:i:s')."'"; $amount = $sqlConnection->fetchOne($query); echo ','.$amount; } $startDate = new DateTime($year.'-12-1 00:00:00'); //echo 'Date from: '.$startDate->format('Y-m-d H:i:s').PHP_EOL; $endDate = new DateTime($year.'-12-31 23:59:59'); //echo 'Date to: '.$endDate->format('Y-m-d H:i:s').PHP_EOL; $query = "SELECT sum(sfo.grand_total) total_sold FROM sales_flat_order sfo JOIN sales_flat_order_payment sfop ON sfop.parent_id = sfo.entity_id WHERE sfo.state = 'complete' AND sfo.state = 'complete' AND sfop.method LIKE '".$methodCode."' AND sfo.created_at > '".$startDate->format('Y-m-d H:i:s')."' AND sfo.created_at < '".$endDate->format('Y-m-d H:i:s')."'"; $amount = $sqlConnection->fetchOne($query); echo ','.$amount; } echo PHP_EOL; }
Este script tendremos que ponerlo en el directorio raiz del proyecto Magento para que enganche al Magento. Fíjate que necesita de dos parámetros de entrada que son el año de inicio y el año de fin. Además he marcado un objeto que proporciona Magento para estas cosas, la conexión a la base de datos que se guarda en $sqlConnection.
Guardamos el script anterior en un fichero, por ejemplo llamado script.php. Si queremos las ventas desde el año 2017 al 2017, lo ejecutamos así desde línea de comandos:
$ php script.php 2017 2017
Veremos la salida por pantalla. Ahora bien, si redireccionamos la salida del script a un fichero, luego podremos visualizarlo mejor. Para esto lo ejecutamos así:
$ php script.php 2017 2017 > ventas_por_metodo_de_pago.csv
Ahora abrimos el fichero CSV con nuestro programa de hojas de cálculo favorito para ver los datos. Si no tienes, es muy recomendable el LibreOffice que lo puedes descargar gratis haciendo click aquí.
Así jugando un poco con los datos resultantes, podemos tener una gráfica de evolución de los métodos de pago. Como la imagen de cabecera de arriba. Podemos ver que algo está pasando en abril y por Navidades del año 2017 con uno de los métodos de pago.
Espero que sirva.
Un saludo.
Este es uno de los patrónes de diseño de software más sencillos de implementar. Se trata del Singleton, que simplemente es un tipo de objeto de programación. En Programación Orientada a Objetos (POO), tenemos este tipo de objetos que se usan para sólo instanciar uno y exclusivamente uno en todo el programa.
No sabemos cuántas veces ni en cuántos lugares se va a usar el objeto. Pero sí que sabemos que necesitamos que sólo exista uno como máximo. De aquí que viene su nombre de Singleton.
Se dice que viola los principios SOLID del diseño de software porque en sí mismo controla el proceso de creación, pero de hecho, en patrones más avanzados como en las fábricas es necesario implementarlos.
Continuar leyendo..Hoy traigo otro pequeño HOWTO para trabajar con las numeraciones internas de Magento 1.9. Los pedidos, envíos, facturas y abonos se pueden numerar. Se pueden poner prefijos por defecto, o a nivel de store, puedes seleccionar distintos prefijos y numeraciones.
En un Magento original sólo te permite hasta una numeración por store para facturas, abonos, envíos y pedidos. Esto incluso se puede mejorar haciendo varias numeraciones por store, pero ya no es una configuración normal. Para hacer 2 numeraciones de facturas en una misma store habrá que controlar el evento de creación de facturas, para así ir reenumerando ‘al vuelo’, mediante programación.
Se trata de la tabla eav_entity_store, por ejemplo:
Las numeraciones siguen todas la misma estrategia. En la columna increment_last_id tendremos el último elemento numerado. Por ejemplo, miremos el último pedido numerado es el P00127586, cuyo prefijo que lo tenemos en la columna increment_prefix es el P. Entonces nos queda que el número 00127586 es la numeración. Para calcular el siguiente le suma 1 y le vuelve a poner el prefijo.
Por ejemplo, si hacemos lo mismo con la última fila, tenemos A18X010000 es el último incremento usado. Su prefijo es el A18X, con lo que para calcular el siguiente le sumará 1 a 010000. Con lo que el siguiente será A18X010001.
Inicialmente no tenemos definidos valores y se numerarán sólo con números sin prefijos de letras. Pero para definirlos tenemos que tener en cuenta todas las columnas de la imagen:
Espero que sirva.
Un saludo.
No quiero perder las buenas costumbres, y esto de escribir en mi blog es una de ellas. Así que aquí estoy de nuevo con otro pequeño HOWTO para geolocalizar ordenadores por IP o servidores por nombre de dominio. Es realmente sencillo, un juego de niños, pero por si lo necesitas en algún proyecto aquí que lo dejo.
A continuación tienes cómo instalar en PHP5.6 las librerías en un sistema operativo Linux. Luego para PHP7 y enlaces a información sobre bases de datos relacionadas. Para geolocalizar dispositivos en Internet basta con utilizar uno de estos servicios. Quizá lo que necesitas es dar una traducción de tu sitio según la localización del visitante, mostrar mensajes por país, o desplegar países, regiones y localidades. También puedes usar las coordenadas de este servicio, pero no es muy fiable localizar con este sistema a tan bajo nivel pero por tener tendrás con esto unos datos orientativos para tu web.
Abajo del post tienes enlaces a Bases de Datos con países del mundo, regiones y localidades actualizadas. Lo mejor de todo, la versión simple es gratis para que puedas usarlo en tu proyecto. Sólo con nombrar en tu proyecto a la empresa autora.
También hay empresas que ofrecen bajo pago este servicio..
Aquí tenemos que instalar unas de librerías y la base de datos pública de GeoIP. En un servidor Linux con Ubuntu, Debian o compatible hacemos lo siguiente:
$ sudo apt-get install php-geoip $ wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz $ gunzip GeoLiteCity.dat.gz $ sudo mkdir /usr/share/GeoIP $ sudo mv GeoLiteCity.dat /usr/share/GeoIP/GeoIPCity.dat
Con esto ya podemos usarlo en cualquier script o programa hecho en PHP así:
<?php var_dump(geoip_record_by_name('jnjsite.com'));
Tenemos que ver por pantalla algo parecido a:
Array ( [continent_code] => EU [country_code] => IE [country_code3] => IRL [country_name] => Ireland [region] => 07 [city] => Dublin [postal_code] => [latitude] => 53.333099365234 [longitude] => -6.248899936676 [dma_code] => 0 [area_code] => 0 )
Tengo que decir que la latitud y longitud son bastante aproximadas. Y dependerá bastante de tu proveedor de servicios de Internet si está bien localizado en las bases de datos de MaxMind. Pero lo que es el país, región y ciudad son bastante fiables, sobretodo el país.
Ahora es más fácil incluso con PHP7. Sólo tendremos que instalar la siguiente librería y se nos instalará todo de una vez:
$ sudo apt-get install php-geoip
Ya está, simplemente con esto ya podemos usar en el ordenador la geolocalización mediante PHP. Hay mucha funciones disponibles.
Sólo me queda dejar algunos enlaces interesantes:
Hoy traigo un pequeño HOWTO con una joya de Symfony. Se trata de un bundle, plugin o módulo (como prefieras llamarlo) para Symfony. Es una plataforma completa en origen, pero podemos sólo usar el núcleo de dicha plataforma en nuestro proyecto. Así en menos de 1 hora tendremos montada nuestra API en nuestro proyecto. Es decir, integrando el núcleo de este bundle en nuestro proyecto, se generarán automáticamente todas las funcionalidades clásicas de una API REST de todo lo que tengamos en nuestro proyecto.
Para los no duchos en el tema, una API es un punto de entrada a nuestro proyecto. Por ejemplo, si tenemos animales en nuestro proyecto, y dejamos en la API la gestión de estos animales, podremos listarlos, editarlos, crearlos o borrarlos.. Todo remotamente desde la API, desde una aplicación móvil, desde otra web, alimentando otros sistemas informáticos con esta información, cualquier cosa que se nos ocurra se puede hacer con una API.
Es decir, por excelencia las APIs son la mejor forma de interconectar sistemas informáticos. Y no es que ahora se hayan puesto de moda, sino que en el año 2000 se pusieron de moda. Y con Symfony mediante este proyecto se simplifica mucho su puesta en marcha.
Continuar leyendo..Continuando con el post anterior, y de nuevo a modo de code-kata, vengo a traer el siguiente paso al algoritmo. Si en el post anterior teníamos cómo minimizar el tiempo en el sistema de varias tareas con un sólo agente, ahora le añadimos la posibilidad de tener varios.
Continuar leyendo..La gestión de los proyectos es la clave: puede marcar la diferencia entre el éxito o el desastre. La gestión de las tareas no se puede hacer de cualquier forma. Por esto que se han estudiado y se han establecido muchas estrategias. No cualquier software puede ser un buen gestor de proyectos. Por esto que existen estudios que lo integran, técnicas de programación.. y sobretodo en informática, que existen multitud de estrategias, ya que dentro de los ordenadores esto se aplica constantemente.
Los pasos clásicos a seguir son los siguientes:
Como es obvio, en el primer paso se cierran especificaciones y cualquier modificación posterior invalida el algoritmo, y hay que recalcular todo.
A modo de code-kata traigo hoy una estrategia voraz para organizar un proyecto con el objetivo de minimizar el tiempo de espera de las tareas en el sistema. Suponiendo que todas las tareas son igual de importantes, se trata de hacer que esperen en total lo mínimo posible. Se trata de una estregia voraz porque simplemente se elige la siguientes tareas que menos tiempo se tarde en terminar, sin rectificar ni volver atrás. Así se terminarán primero las que menos se tarde, y más rápido se irán entregando las tareas. Otra cosa es el beneficio o la importancia que pueda tener cada tarea, pero para esto hay otro algoritmo 😉
Continuar leyendo..Cuando has valorado bien un proyecto, y es tal el nivel de personalización que se quiere alcanzar, no queda más remedio que hacer un desarrollo artesanal, o a la larga te arrepentirás. Ya que partir de un CMS prefabricado es, a veces, más que una ayuda un lastre. Cuando quieres la máxima flexibilidad, velocidad en las modificaciones.. y por supuesto, la máxima calidad.. tienes que ir al desarrollo sobre frameworks. Ya hablé sobre esto en otro post anterior..
Hoy vengo a empezar con una serie de plugins o bundles para Symfony, hoy con uno para programar tareas. Ya sea para enviar emails transaccionales, para programar tareas de marketing, crawleos de sitios web, generar sitemaps, o lo que sea que quieras automatizar.. Aquí verás como en un rato tienes montado un estupendo programador de tareas.
Con este programador de tareas ya tienes el panel de control hecho. Es decir, te evitas la construcción del panel, y podrás ir al siguiente paso en menos de una hora. Que será directamente el ir a crear las tareas tal y como las necesites para tu proyecto 🙂
Continuar leyendo..Puede ser que necesitemos en Magento alguna forma de almacenar datos globales, es decir, que no son relacionados con ningún otro elemento individual.
Todo o casi todo en Magento tiene atributos: los productos, clientes, pedidos, direcciones, facturas, abonos, etc.. Pero para almacenar estos atributos globales tenemos dos opciones, o los guardamos como variables de configuración o como variables del core de Magento.
La diferencia es que las variables de configuración se cachean y las del core no. Muchas de las variables de configuración se pueden gestionar desde el panel de control en Sistema > Configuración. Si modificamos mediante código las variables de configuración no se refrescarán los datos, sin embargo si modificamos las variables mediante el panel de control casi todas se refrescan en el momento. Sin embargo con las variables del core esto no pasa.. conforme se guardan se tienen actualizadas al consultarlas de nuevo. Usar variables del core provoca más consultas a la base de datos, sin embargo, las variables de configuración se actualizan sólo cuando se refresca la caché de variables de configuración.
Continuar leyendo..Vengo a traer una revisión del post anterior. Sobre el algoritmo de Dijkstra para cálculo de caminos mínimos entre nodos de un grafo, a modo de code-kata. Son unas modificaciones para hacer que se pueda elegir el nodo inicial desde el que arrancamos. Y una sencilla ordenación de los nodos de la lista de adyacencia.
Continuar leyendo..