Blog

enctype = “multipart/form=data”

Formas de POSTear datos

Con HTTP hay dos formas de POSTear datos:
application/x-www-form-urlencoded: Utilizado por defecto.
multipart/form-data: Utilizado cuando se requieren archivos o un volumen abundante de datos. Debe incluirse en el formulario el atributo enctype=”multipart/form-data”.

Sin enctype=”multipart/form-data”

POST /home/uploadfiles HTTP/1.1
Content-Type: application/x-www-form-urlencoded
UA-CPU: x86
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64)
Content-Length: 13

submit=Submit

Con enctype=”multipart/form-data”

Significa que el formulario será enviado en múltiples partes, es necesario para enviar archivos.

POST /home/uploadfiles HTTP/1.1
Content-Type: multipart/form-data; boundary=---------------------------7d81b516112482 
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64)
Content-Length: 324

-----------------------------7d81b516112482 
Content-Disposition: form-data; name="file"; filename="\\SERVER\Users\Scott\test.txt"
Content-Type: text/plain

foo
-----------------------------7d81b516112482
Content-Disposition: form-data; name="submit"

Submit
-----------------------------7d81b516112482--

¿Por qué no utilizamos siempre enctype=”multipart/form-data”?

Al no utilizarlo, los datos enviados, simplemente consisten en una serie de “key:values”, y pueden ser parseados como GET o POST.
Al utilizarlo, el volumen de los datos se hace mayor y solo puede utilizarse POST.

Delegación de servicios AFIP de nic.ar

1) Obtener cuil

Puede obtener cuil a través de los siguientes enlaces:
Número de cuil rápido
Constancia de cuil

2) Obtener clave fiscal

Dirigirse a una dependencia de AFIP con original y fotocopia del DNI
Para evitar demoras puede solicitar un Turno Web

3) Delegar servicio de afip: “Trámites a Distancia” y “Administración de Dominios”

Delegar servicio de afip: “Trámites a Distancia” y “Administración de Dominios”

Permitir a otra persona que reserve dominios en mi nombre

Generar nueva relación

AngularJs $q service

Introducción

Asynchronous We will get a result from an action at some point in the future.

$q service

A service that helps you run functions asynchronously, and use their return values (or exceptions) when they are done processing.

Implementación 1
$q(function(resolve, reject, notify){
  ...
  var ok = ...
  resolve(ok);
  ...
  var error = ...
  reject(error)
  ...
  var notify = ...
  notify(error)
}
Implementación 2
var deferred = $q.defer();
...
var ok = ...
deferred.resolve(ok);
...
var error = ...
deferred.reject(error);
...
var notify = ...
deferred.notify(error);
Ejemplo Implementación 1
var app = angular.module("app", []);

app.controller("promiseController", function($scope, $q) {

  function okToGreet(name){
    return (Math.random() < 0.2) ? false : true;
  };
  
  function asyncGreet(name) {
    // perform some asynchronous operation, resolve or reject the promise when appropriate.
    return $q(function(resolve, reject) {
      setTimeout(function() {
        if (okToGreet(name)) {
          resolve('Hello, ' + name + '!');
        } else {
          reject('Greeting ' + name + ' is not allowed.');
        }
      }, 1000);
    });
  }

  var promise = asyncGreet('Robin Hood');
  promise.then(function(greeting) {
    alert('Success: ' + greeting);
  }, function(reason) {
    alert('Failed: ' + reason);
  });
});
Ejemplo Implementación 2
var app = angular.module("app", []);

app.controller("promiseController", function($scope, $q) {

  function okToGreet(name){
    return (Math.random() < 0.2) ? false : true;
  };
  
  function asyncGreet(name) {
    var deferred = $q.defer();

    setTimeout(function() {
      deferred.notify('About to greet ' + name + '.');

      if (okToGreet(name)) {
        deferred.resolve('Hello, ' + name + '!');
      } else {
        deferred.reject('Greeting ' + name + ' is not allowed.');
      }
    }, 1000);

    return deferred.promise;
  }

  var promise = asyncGreet('Robin Hood');
  promise.then(function(greeting) {
    alert('Success: ' + greeting);
  }, function(reason) {
    alert('Failed: ' + reason);
  }, function(update) {
    alert('Got notification: ' + update);
  });
});
Chaining Promises

Because calling the then method of a promise returns a new derived promise, it is easily possible to create a chain of promises:

  var promiseA = asyncGreet('Robin Hood').then(function(greeting) {
    alert('Success: ' + greeting);
    return true;
  }, function(reason) {
    alert('Failed: ' + reason);
    return false;
  });
  
  var promiseB = promiseA.then(
    function(response) { 
      if(true) alert("Welcome")
      else alert("Bye")
    },
    function(reason) { alert(reason); }
  );

Encadenamiento parámetro - respuesta
El encadenamiento de parámetros - respuesta tiene un comportamiento errático en angular, el siguiente código debería funcionar pero no me funcionó al ejecutarlo dentro de un servicio AngularJS. Me daba error de metodos no definidos.

//promesa 1
var promise1 = function(param1){
  ...
  return $q.when(response1);
}

//promesa 2
//"param2" tiene la misma estructura que "response1"
var promise2 = function(param2){
  ...
  return $q.when(response2);
}


var exec = function(){ 
  self.promise1().then(promise2).then(
    function(response2){ ... }
  );
);
$q.all

Combines multiple promises into a single promise that is resolved when all of the input promises are resolved.

* If you provide them as an array, then the values will be available as an array with the same corresponding order of the promises array.

var promises = [promiseAlpha(), promiseBeta(), promiseGamma()];

$q.all(promises).then(
  function(response){
    console.log(response[0]); // value alpha
    console.log(response[1]); // value beta
    console.log(response[2]); // value gamma
    console.log("complete");
  }
});


//if you provide an object literal to all(), the values are attached to an object with the same corresponding property names
var promises = {alpha: promiseAlpha(), beta: promiseBeta(), gamma: promiseGamma()}

$q.all(promises).then(
  function(response){
    console.log(response.alpha); // value alpha
    console.log(response.beta);  // value beta
    console.log(response.gamma); // value gamma
    console.log("complete");
  }
});


//si utilizamos un array de promesas vacio se considera como resuelta
var promises = [] 
$q.all(promises).then((values) => {
  console.log("complete");
});
$q.when
var deferred = $q.defer();
deferred.resolver("respuesta");
return deferred.promise;

Es lo mismo que:

return $q.when("respuesta");
Using promises in angular views

Podemos asignar directamente la respuesta de una promesa a una variable del $scope y se mostraran los resultados en el html

angular.module('myModule', []).controller('HelloCtrl', function($timeout, $q, $scope) {
  var getMessages = function() {
    var deferred = $q.defer();
  
    $timeout(function() {
       deferred.resolve(['Hello', 'world']);
    }, 10000);
  
      return deferred.promise;
  };
   

  $scope.messages = getMessages().then(
    function(response){ return response; }
  });

<br /> <body ng-app="myModule" ng-controller="HelloCtrl"></p> <h1>Messages</h1> <ul> <li ng-repeat="message in messages">{{ message }}</li> </ul> <p></body><br />
Fuente
https://docs.angularjs.org/api/ng/service/$q
http://www.martin-brennan.com/using-q-all-to-resolve-multiple-promises/
http://markdalgleish.com/2013/06/using-promises-in-angularjs-views/
http://taoofcode.net/promise-anti-patterns/

Patrón de Diseño Builder

Builder

Introducción

Centraliza el proceso de creación de un objeto complejo en un único objeto.

Builder Structure

Builder: Interfaz abstracta para crear productos.
Concrete Builder: Implementación del Builder. Construye y reúne las partes necesarias para construir los productos
Director: Construye un objeto usando el patrón Builder
Product: El objeto complejo bajo construcción

Product
class Pizza {
    private String masa = "";
    private String salsa = "";
    private String relleno = "";
 
    public void setMasa(String masa){ 
        this.masa = masa;
    }

    public void setSalsa(String salsa){ 
        this.salsa = salsa; 
    }
    
    public void setRelleno(String relleno){
        this.relleno = relleno;
    }
}
Abstract Builder
abstract class PizzaBuilder {
    protected Pizza pizza;
 
    public Pizza getPizza() { 
        return pizza; 
    }

    public void crearNuevaPizza() {
        pizza = new Pizza();
    }
 
    public abstract void buildMasa();
    public abstract void buildSalsa();
    public abstract void buildRelleno();
}
ConcreteBuilder
class HawaiPizzaBuilder extends PizzaBuilder {
    public void buildMasa(){
        pizza.setMasa("suave"); 
    }

    public void buildSalsa(){ 
        pizza.setSalsa("dulce"); 
    }
    
    public void buildRelleno() {
        pizza.setRelleno("chorizo+alcachofas"); 
    }
}
Director
class Cocina {
    private PizzaBuilder pizzaBuilder;
 
    public void setPizzaBuilder(PizzaBuilder pb) { 
        pizzaBuilder = pb; 
    }

    public Pizza getPizza() { }
        return pizzaBuilder.getPizza(); 
    }
 
    public void construirPizza() {
       pizzaBuilder.crearNuevaPizza();
       pizzaBuilder.buildMasa();
       pizzaBuilder.buildSalsa();
       pizzaBuilder.buildRelleno();
    }
}
Un cliente pidiendo una pizza
class BuilderExample {
    public static void main(String[] args) {
        Cocina cocina = new Cocina();
        PizzaBuilder hawai_pizzabuilder = new HawaiPizzaBuilder();
        PizzaBuilder picante_pizzabuilder = new PicantePizzaBuilder();
 
        cocina.setPizzaBuilder( hawai_pizzabuilder );
        cocina.construirPizza();
 
        Pizza pizza = cocina.getPizza();
    }
}
2da opción para el abstract builder quizá más transparente para su uso

Dentro del crear se llaman los métodos build.
Es válido siempre y cuando no se necesite alterar el orden del llamado a los “build’s”

abstract class OtroPizzaBuilder {
    protected Pizza pizza;
 
    public Pizza getPizza() { return pizza; }
    public void crearNuevaPizza() { 
           pizza = new Pizza(); 
           buildMasa();
           buildSalsa();
           buildRelleno();
    }
 
    public abstract void buildMasa();
    public abstract void buildSalsa();
    public abstract void buildRelleno();
}
Director
class OtraCocina {
    private OtroPizzaBuilder pizzaBuilder;
 
    public void setPizzaBuilder(OtroPizzaBuilder pb) { pizzaBuilder = pb; }
    public Pizza getPizza() { return pizzaBuilder.getPizza(); }
 
    public void construirPizza() {
       pizzaBuilder.crearNuevaPizza();
       //notar que no se necesita llamar a cada build.
    }
}

WordPress: Cambiar Tema

1) Apariencia -> Temas (A la izquierda)

wordpress_apariencia_temas

2) Añadir nuevo

wordpress_apariencia_anadir_nuevo

3) Seleccionar pestaña Recientes

wordpress_apariencia_recientes

4) Buscar y seleccionar tema

wordpress_apariencia_seleccionar_tema

5) Instalar tema

wordpress_apariencia_instalar_tema

6) Activar tema

wordpress_apariencia_activar_tema

7) Personalizar tema: Las opciones de personalización del tema pueden diferir entre un tema y otro.

wordpress_apariencia_personalizar_tema

Nota: La opción de personalizar puede ser accedida desde el menú a la izquierda: Apariencia -> Personalizar

wordpress_apariencia_personalizar

WordPress: Agregar nueva entrada

1) Nueva entrada (arriba a la izquierda)

wordpress_nueva_entrada

2) Escribir el título de la entrada

wordpress_entrada_titulo

3) Seleccionar la opción “Visual”

wordpress_opcion_visual

4) Seleccionar la opción “Más Herramientas”

wordpress_mas_herramientas

5) Escribir el contenido de la entrada

wordpress_contenido_entrada

6) Seleccionar Categoría (a la derecha)

wordpress_categoria

7) Opcional: Asignar Imagen Destacada (abajo a la derecha)

wordpress_imagen_destacada_entrada

8) Publicar (arriba a la derecha)

wordpress_publicar_entrada

Cálculos de montos para combustibles

Introducción

A continuación se incluye un script en PHP para calcular los valores de un item correspondiente a un combustible, de forma tal que sea aceptado por los WebServices de facturación electrónica de AFIP y al mismo tiempo, los valores sean exactos con una impresora fiscal.
A un combustible se asocian dos valores que serán utilizados para calcular impuestos internos: “coeficiente” e “itc”.

Datos de entrada
$cantidad //cantidad vendida. Si es 0 se calcula en base al precio total
$precio //precio total vendido. Si es 0 se calcula en base a la cantidad
$itc //valor entre 0 (si no posee) y 1
$coeficiente //valor entre 1 (si no posee) y 2
$ivaValor //valor del iva, ej 0.21 para 21%
$precioArticulo //precio total del articulo.
Script
$precioNetoArticulo = $precioArticulo * (1 - $ivaValor);

if(!empty($precio)) { 
  $cantidad = round($precio / $precioArticulo, 2); 
} else {
  $precio = round($cantidad * $precioArticulo, 2); 
}

if($coeficiente != 1){
  $precioNeto = round($precio / $coeficiente, 2);
  $importeIva = round($ivaValor * $precioNeto, 2);
  $importeItc = round($itc * $precioNeto, 2);
  $alicuotaItc = round($importeItc * 100 / $precioNeto, 2);
  $impuestoInterno =  $precio - $precioNeto - $importeIva - $importeItc;
  $alicuotaImpuestoInterno = round($impuestoInterno * 100 / $precioNeto, 2);
  $importeTributo = $importeItc + $impuestoInterno;
  $tasaAjuste = $precioNeto / ($precioNeto + $impuestoInterno + $importeItc);
  
} else {
  $ivaAux = round($precio / (1 + $ivaValor), 2);
  $importeIva = $precio - $ivaAux;
  $precioNeto = $precio - $importeIva;
  $impuestoInterno = 0;
  $alicuotaImpuestoInterno = 0;
  $importeItc = 0;
  $alicuotaItc = 0;
  $tasaAjuste = 0;
  $importeTributo = 0;
}

$ret = array(); //array con los valores de retorno
$ret["precio_articulo"] = number_format($precioArticulo, 2, ".", "");
$ret["precio_neto_articulo"] = number_format($precioNetoArticulo, 2, ".", "");
$ret["precio"] = number_format($precio, 2, ".", "");
$ret["cantidad"] = number_format($cantidad, 2, ".", "");
$ret["precio_neto"] = number_format($precioNeto, 2, ".", "");
$ret["importe_iva"] = number_format($importeIva, 2, ".", "");
$ret["impuesto_interno"] = number_format($impuestoInterno, 2, ".", "");
$ret["alicuota_impuesto_interno"] = number_format($alicuotaImpuestoInterno, 2, ".", "");    
$ret["importe_itc"] = number_format($importeItc, 2, ".", "");
$ret["alicuota_itc"] = number_format($alicuotaItc, 2, ".", "");
$ret["importe_tributo"] = number_format($importeTributo, 2, ".", "");    
$ret["tasa_ajuste"] = number_format($tasaAjuste, 8, ".", "");
Prestar especial atención a los valores de redondeo.

En las impresoras fiscales, los calculos son realizados por el mismo controlador fiscal, para tener una concordancia de valores se recomienda utilizar cantidad = 1 y precio_neto en vez de cantidad y precio_neto_articulo. Luego el detalle de la cantidad total vendida y el precio neto del articulo pueden ser incluídos en algun string con información adicional

Contratos Ágiles

 

Introducción
  • Las especificaciones nunca se entenderán completamente.
  • El usuario no sabrá lo que quiere hasta que el sistema esté en producción
  • Un sistema nunca puede ser totalmente especificado, ni totalmente testado
  • No se puede determinar el costo ni el tiempo que durará un proyecto
Contrato

Cuando un CLIENTE necesita de un SERVICIO que ofrece un PROVEEDOR para completar un PROYECTO se define un CONTRATO, que consiste en un ACUERDO entre ambas partes en el cual debe indicarse:

  • PARTES
  • CAUSA
  • SERVICIO
  • CONSENTIMIENTO (firma)
  • REGLAS: Regirán el servicio y permitirán mantener el acuerdo durante la prestación

EN TEORÍA: Las reglas se acuerdan libremente por ambas partes para crear condiciones óptimas que permitan completar con éxito el proyecto. En este acuerdo las dos partes “ganan”.

EN PRÁCTICA: Cada parte tratará de sacar ventaja.

Triángulo de Hierro

Triángulo de Hierro
* Si se modifica una variable, alguna otra también tiene que ser modificada. En caso contrario se pone en riesgo la calidad.
* En un contrato ágil el acuerdo entre las partes se tiene que poder revisar regularmente de manera ligera.
* Debe prestarse mucha atención en definir las reglas en base al alcance, costo y tiempo establecidos.

Metodología Ágil

Parte de los siguientes valores (definidos en el “Agile Manifesto”):

  • individuos y su interacción, por encima de los procesos y las herramientas.
  • software que funciona, por encima de la documentación exhaustiva.
  • Colaboración con el cliente, por encima de la negociación contractual.
  • Respuesta al cambio, por encima del seguimiento de un plan.

Se basa en el desarrollo de software iterativo. Se emplean ciclos cortos involucrando al cliente para definir y priorizar requerimientos, con el objetivo de que, a través de la colaboración con el equipo de desarrollo, se disponga de un producto potencialmente entregable al final de cada iteración.

El equipo de desarrollo es multifuncional y auto-organizado, es decir, es responsable de organizarse y gestionarse a sí mismo, siendo capaz de encontrar una solución a un problema sin que se le dictamine cómo debe resolverse.

La definición de un Contrato Agile supone un cambio de mentalidad que debe cubrir varios aspectos:

  • Colaboración estrecha y confianza mutua entre el cliente y el proveedor. La comunicación es esencial para facilitar la colaboración y creación de sinergias para obtener mejores soluciones.
  • Rápida capacidad de reacción ante imprevistos en el desarrollo
  • Flexibilidad en los requisitos del producto o servicio
  • Cobro por entrega de “valor”

Si en algún momento durante el proyecto hay que recurrir al contrato que se firmó al inicio, posiblemente esta sea una mala señal de que las cosas están empezando a ir mal y que la confianza se está deteriorando.

Desventajas de los contratos tradicionales

En el inicio del proyecto se intenta disponer de todos los requisitos detallados (abordar toda la complejidad funcional de una vez), elaborando un análisis funcional que formará parte del contrato.

Desventajas

  • Se deben plantear hipótesis antes de disponer de toda la información necesaria y de poder entender mejor el producto y contexto en que se va a desarrollar.
  • El cliente deberá pedir en el contrato todo lo que se imagine que en algún momento pueda ser necesario
  • Durante el desarrollo del proyecto aparecerán requisitos no relevantes
  • La verificación del cumplimiento de las expectativas del cliente, se deja para la última etapa, favoreciendo la imposibilidad de detectar requisitos no relevantes en etapas tempranas.
  • Las hipótesis que no hayan sido correctas y los requisitos no detectados a tiempo, llevarán a la necesidad de alterar drásticamente el triángulo de hierro, reduciendo notablemente la calidad del producto (o en el peor caso descartando al producto)
Contrato Marco

Permite incorporar anexos sin necesidad de una nueva negociación completa por las partes.

CONTENIDO:
Cláusulas comunes a cualquier contrato: Partes, fecha, dominio, etc.
Objeto del contrato: Debe especificar que las obligaciones se irán concretando a posteriori mediante la firma de anexos en los que se definirán las iteraciones.
Obligaciones de las partes: Además de las obligaciones comunes (formas y plazos de entrega, y de pago), hay que hacer hincapié en las obligaciones que derivan de trabajar con metodologías ágiles:

  • Duración del Sprint
  • Imposibilidad de modificar un sprint una vez definido
  • Periodicidad de reuniones
  • Pago por release
  • Procedimiento de cambio del product backlog, no solo para inlcuir nuevas funcionalidades sino también para priorizarlas y cuantificar en items el desarrollo de cada una de ellas

Glosario de términos Se recomienda incluir un glosario de términos
Product Backlog: El cliente es responsable de este documento y por tanto quien a definir y priorizar las funcionalidades de su producto/servicio. El proveedor establecerá el peso de cada funcionalidad. Si bien es mutable, el Product Backlog sirve como base inicial, se recomienda incluirlo como Anexo I.
Incumplimientos y sus consecuencias: Definir qué se considera incumplimiento de las obligaciones de cada una de las partes y que consecuencias tendrán. Por ejemplo se puede indicar las consecuencias que tendrá los retrasos en un sprint, o la cancelación anticipada del proyecto.
Pago inicial: Suele establecerse un pago por el asesoramiento técnico en la definición del Product Backlog y en la elaboración de presupuesto y contrato marco.
Cláusulas especificas de la prestación de servicios: Propiedad del código, mantenimiento de los desarrollos, backups, contratación de servidores, etc.

Tipos de Contrato

Contrato cerrado (AF CF)
* No ceptar cambios.
* Reducir feedback
* Descomponer el proyecto en varias fases de AC y CF.

Contrato Alcance No Vinculante (AV CF)
* Cambios sobre requisitos no desarrolldos que no modifiquen A
* Finalización anticipada (con retribución)
* Pago de tareas adicionales. Se recomienda primero completar los requisitos “baseline”
* Si se establece PF: Hacer tanto como se pueda en ese plazo

Contrato Objetivo (AF CV)
* Compartir ganancias y pérdidas: Fomenta que las partes colaboren y vayan mejorando.

Contrato Progresivo (AV y CV)
Dos alternativas:
* Pago fijo por iteración
* Pago por costo de iteración.

Aceptación del producto

Consta de dos pasos principales:
1) Revisión presencial.
2) Período de aceptación.

Uno de los riesgos concernientes al proceso de aceptación es que el cliente pierda la perspectiva de la globalidad del proyecto o del objetivo de la iteración, dando lugar reclamos. Se recomienda mostrar al finalizar cada iteración.
* Una visión del baseline, el trabajo ya realizado, pendiente, cambios o agregados respecto al alcance global, en forma de mapa del producto.
* La velocidad de desarrollo y la proyección de fecha estimada de finalización.

Referencias

WebService (WS)

Introducción

Concepto

Tecnología para el intercambio de información entre diferentes aplicaciones (clientes, consumidores) ejecutadas en cualquier plataforma.

Servidor

Un servidor que implementa un WS debe proveer un WSDL para que los clientes puedan obtener información de dónde y cómo conectarse.
Generalmente los lenguajes de programación permiten generar fácilmente un servidor de WS y generar automáticamente el WSDL.

Cliente

La conexión a un WS generalmente se realiza mediante el protocolo SOAP – Simple Object Access Protocol (que es una abstracción de HTTP) o directamente con HTTP, por ejemplo, a través de formularios web.
Generalmente los lenguajes de programación permiten codificar y decodificar mensajes a través del protocolo SOAP fácilmente sin la necesidad de conocer en detalle su estructura.

WebService Description Language: WSDL

Documento XML que especifica la ubicación del WS y sus métodos

Estructura del WSDL (EN CONSTRUCCIÓN)

Estructura básica

Para facilitar la visualización del árbol XML del WSDL y sus relaciones, podemos organizarlo en un diagrama correspondiente al siguiente ejemplo: http://www.w3schools.com/webservices/tempconvert.asmx?WSDL

Ver ejemplo en wsdl.xml (se recomienda abrirlo mediante un navegador porque facilita la visualización). El ejemplo se puede ver en la siguiente URL:
Descripción de los elementos principales
types: data type definitions. For maximum platform neutrality, WSDL uses XML Schema syntax to define data types.
message: Definition of the data being communicated. Each message can consist of one or more parts. The parts can be compared to the parameters of a function call in a traditional programming language.
portType: Description of a web service, the operations that can be performed, and the messages that are involved. It can be compared to a function library (or a module, or a class) in a traditional programming language.
binding: Data format and protocol for each port type.
service: Descripción del servicio y el acceso principal del webservice