Últimas entradas del blog

GNU/Linux: automatizar backups de Mariadb/Mysql

2018-02-16 - Categorías: GNU/Linux
Historial

El software de gestión de servidores te puede automatizar esta y otras tareas. Pero si estas haciendo artesanalmente un servidor, para no gastar ni un bit innecesariamente en correr software de gestión de servidores, tendrás que automatizar esta tarea: el hacer copias de seguridad de la base de datos.

Sí, más vale prevenir que curar. Da por hecho que tarde o temprano los sistemas se rompen, así que más te vale haberte prevenido y tener una copia de seguridad por si acaso. Como me ha llevado un rato buscar entre los foros para construir esto, aquí que lo dejo por si a algún ubuntero le sirve.

Creando el script

Le idea es crear un sencillo Shell Script que automatice la copia de seguridad. Así que creo el fichero /home/ubuntu/backup.db.sh siguiente:

#!/bin/bash
mysqldump -h localhost -u usuario -pcontraseña nombre_base_de_datos | gzip > ~/backups/backup.db.$(date +%Y%m%d).sql.gz
find /home/ubuntu/backups/ -type f -mtime +30 -name 'backup.db.*.gz' -execdir rm {} \;

Este script hace 2 cosas. La primera es sacar una copia de la BD y la comprime a un fichero .gz. Lo segundo es que revisa si hay ficheros .gz de más de 30 días en el directorio de copias de seguridad, borrándolos.

Creando carpeta que almacenará los ficheros

De esta manera necesitaremos crear el directorio para alojar las copias de seguridad:

$ mkdir /home/ubuntu/backups/

Permisos de ejecución del script

Para poder ejecutar este script tendremos que darle permisos de ejecución así:

$ chmod +x /home/ubuntu/backup.db.sh

Ejecutando el script cada día

Sólo falta ejecutar este script cada día. Para esto ejecutamos desde el usuario ubuntu lo siguiente:

$ crontab -e

Nos saldrá una pantalla en donde podemos editar cada tarea programada. Cada línea de este fichero es una tarea programada. Así que tenemos que añadir aquí esta línea:

0 2 * * * /home/ubuntu/backup.db.sh > backup.db.lastLog

Guardamos y salimos del editor. Con esto ya se ejecutará dicho Shell Script cada noche a las 2:00 AM, dejando registro en el fichero backup.db.lastLog.

Terminando

Sólo me queda añadir que quizá quieres añadir a lo anterior una copia de ficheros. Para esto no tienes más que añadir en el script las líneas que te hagan dicha copia de ficheros. Puedes probar el script en cualquier momento así desde línea de comandos, como si fuera un .bat:

$ /home/ubuntu/backup.db.sh

Espero que sirva.
Un saludo.


PrEDA: cálculo empírico del coste temporal de Binomial

2018-02-04 - Categorías: PHP / PrEDA
Números

El coeficiente binomial es una función muy utilizada en combinatoria. Sirve para saber el número de combinaciones de elementos que podemos hacer. Se utiliza mucho en computación para estudiar la estrategia de programación dinámica, porque ejemplifica muy bien la mejora que supone utilizar dicha estrategia. Por ejemplo, la forma de escoger de entre 6 elementos 2 de ellos, es igual al coeficiente binomial (6 2).

Continuar leyendo..


PrEDA: esquemas de programación genéricos avanzados

2018-02-03 - Categorías: PHP / PrEDA
PrEDA algoritmos genericos

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..

Magento 1: cómo sacar las ventas por método de pago

2018-01-26 - Categorías: Magento / PHP
Magento ventas por mes y método de pago

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.

Métodos de pago usados en pedidos

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;

Ventas de los pedidos enviados

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.

El código completo

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.

Ejecutando

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.


PHP: qué es un Singleton y para qué nos puede servir

2018-01-21 - Categorías: General / PHP / Principios y patrones
Coding

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..

Magento 1: cómo cambiar la numeración de pedidos, envíos, facturas y abonos

2018-01-02 - Categorías: Magento
Magento logo

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.

La tabla con las numeraciones

Se trata de la tabla eav_entity_store, por ejemplo:

Magento Eav Entity Store

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.

Configurando por store

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:

  • entity_store_id: identificador interno de fila, sólo se usa para numerar cada fila.
  • entity_type_id: identificador de tipo de entidad. Estos tipos de entidades los tenemos en la tabla eav_entity_type, por ejemplo para la entidad de typo pedido tenemos un identificador 5.
  • store_id: identificador de store, podemos verlos todos en el backend de Magento, en ‘Sistema > Gestionar tiendas’. Si pasamos el ratón por encima del enlace de vista de tienda vermos los identificadores en la URL de enlace. Por ejemplo:
    ../admin/system_store/editStore/store_id/7/key/6196861892c917efe3c053d806cb7b1e/
    Al entrar a editar esta vista de tienda (store) tenemos que su ID es 7. Este es el valor que podremos usar.
  • increment_prefix: prefijo de este contador.
  • increment_last_id: último valor usado.

Espero que sirva.

Un saludo.


AWS: sirviendo un píxel de conversión con el CDN de CloudFront

2017-12-18 - Categorías: Amazon Web Services / General
Cloudfront logo

Una de las tareas más interesantes para saber si las cosas sirven para algo en tu negocio de Internet, consiste en seguir a las visitas. Es decir, consiste en el seguimiento de la conversión, mediante lo que se llaman píxeles de conversión. Es decir, si queremos saber si un canal de entrada a tu web convierte o no, si los anuncios que ponemos en otras webs, si los enlaces de redes sociales, emails, etc.. sirven de algo. Para esto debemos de llevar un seguimiento de dicha entrada a tu web.

Continuar leyendo..

PHP: cómo geolocalizar visitantes, IPs o nombres de dominio

2017-12-14 - Categorías: General / GNU/Linux / PHP
La Tierra

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..

En PHP5.6

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.

En PHP7

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.

Terminando

Sólo me queda dejar algunos enlaces interesantes:


Symfony: cómo montar una API REST de tu plataforma completa en menos de 1 hora

2017-11-27 - Categorías: PHP / Symfony
Symfony logo

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..


PrEDA: minimizando tiempo en el sistema

2017-11-22 - Categorías: PHP / PrEDA
Gantt

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:

  • Se establecen las tareas, fijando especificaciones.
  • Se estudian bien los tiempos que va a llevar cada tarea.
  • Se establece la estrategia para proceder.
  • Se resuelve el órden, con lo cual, aquí se obtienen las fechas de finalización de cada tarea y el tiempo total.
  • Se ejecuta el proyecto.

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..

© 2024 JnjSite.com - MIT license

Sitio hecho con WordPress, diseño y programación del tema por Jnj.