Blog alskare

.Net y lo que surja

Validar Número de IVA VIES

Posted by alskare en 07/09/2009

El otro día, hablando con la contable de la empresa, me comentó la posibilidad de añadir en las aplicaciones la validación de unos “NIF” un poco especiales. Digo un poco especiales porque en principio no se trata de un número de identificación sino más bien es un registro de aquellas empresas “legalizadas” para poder trabajar con IVAs a nivel intracomunitario. Digo legalizada entre comillas puesto que desconozco totalmente si el medio para entrar en esa base de datos se realiza automáticamente al trabajar con empresas intracomunitarias o hace falta algún tipo de registro especial.

Bueno, el caso es que mala validación podemos crear si el origen es una base de datos, así que no me queda más remedio que empezar a buscar y encuentro lo que andaba buscando en lo que creo que es la AEAT Europea: http://ec.europa.eu/taxation_customs/vies/lang.do?fromWhichPage=vieshome&selectedLanguage=ES.

Dentro de los servicios informáticos con los que he trabajado, quizás éste sea uno de los más originales. De hecho, no existe una base de datos centralizada. Se trata de bases de datos con un ámbito del país local que va “replicando” con el resto de países (igual me he pasado al escribir “replicando”). Por otro lado, resulta que no todos los países atienden las 24 horas del día (igual los ordenadores se van a tomar un café): http://ec.europa.eu/taxation_customs/vies/viesspec.do

Al fin y al cabo, somos programadores y nuestros profes siempre nos han enseñado que debemos desglosar un problema gordo en problemas más pequeños para poder afrontarlos con mayor destreza, así que eso voy a hacer en estos momentos. Imagino que al final pasará como ha ocurrido con otra entrada en el blog (Validar NIF, NIE, CIF ), que empezó con una pequeña validación y se ha ido ampliando y mejorando con el tiempo. Así, el objetivo inicial será el de comprobar si el NIF introducido es correcto o no, siempre según el servicio de Fiscalidad y Unión Aduanera.

La primera me la doy en la frente. Resulta que para solicitar la validez de un Número de IVA, necesitamos el código del país y… ¿cómo no?, no encuentro ningún servicio que devuelva los países aceptados, así que hay que hacer una lectura del código HTML de la página para poder tenerlos todos. Para poder trabajar con los países y poder ponerlos como origen de datos de los controles se me ocurre hacer lo más sencillo, una clase List<T>.

Paises

using System;
using System.Collections.Generic;

namespace ValidacionVies
{
    class Pais : IComparable 
    {
        public string CodigoPais { get; set; }
        public string NombrePais { get; set; }

        public Pais(string codigoPais, string pais)
        {
            this.CodigoPais = codigoPais;
            this.NombrePais  = pais;
        }


        // Se implementa la interfaz IComparable para poder ordenar por el país 
        public int CompareTo(object obj)
        {
            return this.NombrePais.CompareTo(((Pais)obj).NombrePais);
        }
    }


    class Paises : List<Pais>
    {
        public Paises()
        {
            this.Add(new Pais("AT", "Austria"));
            this.Add(new Pais("BE", "Bélgica"));
            this.Add(new Pais("BG", "Bulgaria"));
            this.Add(new Pais("CY", "Chipre"));
            this.Add(new Pais("CZ", "Chequia"));
            this.Add(new Pais("DE", "Alemania"));
            this.Add(new Pais("DK", "Dinamarca"));
            this.Add(new Pais("EE", "Estonia"));
            this.Add(new Pais("EL", "Grecia"));
            this.Add(new Pais("ES", "España"));
            this.Add(new Pais("FI", "Finlandia"));
            this.Add(new Pais("FR", "Francia"));
            this.Add(new Pais("GB", "Reino Unido"));
            this.Add(new Pais("HU", "Hungría"));
            this.Add(new Pais("IE", "Irlanda"));
            this.Add(new Pais("IT", "Italia"));
            this.Add(new Pais("LT", "Lituania"));
            this.Add(new Pais("LU", "Luxemburgo"));
            this.Add(new Pais("LV", "Letonia"));
            this.Add(new Pais("MT", "Malta"));
            this.Add(new Pais("NL", "Países Bajos"));
            this.Add(new Pais("PL", "Polonia"));
            this.Add(new Pais("PT", "Portugal"));
            this.Add(new Pais("RO", "Rumania"));
            this.Add(new Pais("SE", "Suecia"));
            this.Add(new Pais("SI", "Eslovenia"));
            this.Add(new Pais("SK", "Eslovaquia"));

            this.Sort();
        }
    }

}

 

El problema lo encontraré el día que haya que hacer alguna modificación, así que tomo nota de la mejora que podría hacerse creando un XML o un simple TXT para poder almacenar los países.

Una vez tenemos los países, conociendo los resultados que nos devuelve el WebService, es cuestión de empezar a preparar un entorno de interacción con el usuario:

- <element name="checkVatResponse">
- <complexType>
- <sequence>
  <element name="countryCode" type="xsd:string" /> 
  <element name="vatNumber" type="xsd:string" /> 
  <element name="requestDate" type="xsd:date" /> 
  <element name="valid" type="xsd:boolean" /> 
  <element name="name" type="xsd:string" /> 
  <element name="address" type="xsd:string" /> 
  </sequence>
  </complexType>
  </element>

Como que me hace gracia jugar un poco con las llamadas asíncronas al Web Service, opto por crear una aplicación WinForms que me permita realizar las primeras pruebas, así, me sale algo así como lo siguiente (ya dice mi jefe que lo mío no es el diseño):

image

 

De hecho, en el formulario no hay nada raro, un combo en el que se cargan los países (cboPaises), un textBox en el que deberá teclearse el número a validar (txtVatNumber) y los textBox de resultado (rstXXXX).

Al lío:

Código del formulario

using System;
using System.Windows.Forms;
using ValidacionVies.eu.europa.ec;


namespace ValidacionVies
{
    public partial class Form1 : Form
    {
        checkVatService cvs;

        public Form1()
        {
            InitializeComponent();

            // Asignación de eventos
            this.Load += new EventHandler(Form1_Load);
            this.cmdValida.Click += new EventHandler(cmdValida_Click);
        }

        void Form1_Load(object sender, EventArgs e)
        {
            lblProgreso.Text = string.Empty;

            // Carga de paises y asignación al combo
            Paises paises = new Paises();
            cboPaises.DataSource = paises;
            cboPaises.DisplayMember = "NombrePais";
            cboPaises.ValueMember = "CodigoPais";
            cboPaises.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
            cboPaises.AutoCompleteSource = AutoCompleteSource.ListItems;

            // Asignación del evento IndexChanged para el combo.
            cboPaises.SelectedIndexChanged += new EventHandler(cboPaises_SelectedIndexChanged);
            txtCountryCode.Text = cboPaises.SelectedValue.ToString();
        }


        void cboPaises_SelectedIndexChanged(object sender, EventArgs e)
        {
            ComboBox cbo = (ComboBox)sender;
            txtCountryCode.Text = cbo.SelectedValue.ToString();
        }


        void cmdValida_Click(object sender, EventArgs e)
        {
            lblProgreso.Text = "Consultando";

            // Llamada asíncrona al WebService
            cvs = new checkVatService();
            cvs.checkVatCompleted += new checkVatCompletedEventHandler(cvs_checkVatCompleted);
            cvs.checkVatAsync(txtCountryCode.Text, txtVatNumber.Text);
        }


        void cvs_checkVatCompleted(object sender, checkVatCompletedEventArgs e)
        {
            // Respuesta de la llamada asíncrona al WebService
            try
            {
                if (!e.Cancelled)
                {
                    lblProgreso.Text = string.Empty;
                    rstAddress.Text = e.address;
                    rstCountryCode.Text = e.countryCode;
                    rstName.Text = e.name;
                    rstResult.Text = e.Result.ToShortDateString();
                    rstCorrecto.Text = e.valid ? "Sí" : "No";
                }
                else
                {
                    lblProgreso.Text = string.Empty;
                    rstAddress.Text = string.Empty;
                    rstCountryCode.Text = string.Empty;
                    rstName.Text = string.Empty;
                    rstResult.Text = string.Empty;
                    rstCorrecto.Text = string.Empty;
                }
            }
            catch (System.Reflection.TargetInvocationException ex)
            {
                lblProgreso.Text = ex.Message;
            }
            catch (Exception ex)
            {
                lblProgreso.Text = "Se ha producido un error " + ex.GetType().ToString();

            }
        }
    }
}

Ya está. ¡Qué bonitas se ven las cosas cuando están acabadas!

Por cierto, se si alguien tiene interés, puede descargar el proyecto en VisualStudio2008: Descargar

3 comentarios to “Validar Número de IVA VIES”

  1. Santi said

    Gracias por tu respuesta.
    Cuando tenga tiempo me instalo el 2008 o lo paso a 2005.

    Un saludo

  2. alskare said

    Sí que es cierto que el ejemplo está desarrollado en VS2008.

    Por un lado, si sigues el código del post, verás que no tiene mucho problema implementar la solución directamente desde tu código. Por otro lado, estoy preparando un Servicio Web que nos sirva a todos, tanto a quien quiera, como a mí mismo, para poder validar un NIF VIES desde cualquier aplicación que permita una lectura “WebServices” o “Soap”, que, a estas alturas, ya no sé cómo llamarla.

  3. Santi said

    Es una utilidad muy buena pero no tengo vs2008. Tengo vs2005 pero parece que no puede con el.
    Podrias poner el ejecutable o pack de instalacion para utilizarlo?

    Gracias.

Sorry, the comment form is closed at this time.

 
A %d blogueros les gusta esto: