package factura40;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;
import javax.xml.datatype.XMLGregorianCalendar;
import factura40.*;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {"informacionGlobal", "cfdiRelacionados",
    "emisor", "receptor", "conceptos", "impuestos", "complemento", "addenda"})
@XmlRootElement(name = "cfdi:Comprobante")
public class Comprobante40 implements Cloneable, Serializable {
    
     //Se crean los cabezaces del XML
    @XmlAttribute(name ="xmlns:cfdi")
    protected String xmlnsCfdi;
    @XmlAttribute(name ="xmlns:xsi")
    protected String xmlnsXsi;
    @XmlAttribute(name ="xsi:schemaLocation")
    protected String xsiSchemaLocation;
    //Se termina la creacion de los cabezales XML
    private static final long serialVersionUID = 1L;
    @XmlElement(name = "cfdi:InformacionGlobal")
    protected Comprobante40.InformacionGlobal informacionGlobal;
    @XmlElement(name = "cfdi:CfdiRelacionados")
    protected List<Comprobante40.CfdiRelacionados> cfdiRelacionados;
    @XmlElement(name = "cfdi:Emisor", required = true)
    protected Comprobante40.Emisor emisor;
    @XmlElement(name = "cfdi:Receptor", required = true)
    protected Comprobante40.Receptor receptor;
    @XmlElement(name = "cfdi:Conceptos", required = true)
    protected Conceptos conceptos;
    @XmlElement(name = "cfdi:Impuestos")
    protected Comprobante40.Impuestos impuestos;
    @XmlElement(name = "cfdi:Complemento")
    protected Comprobante40.Complemento complemento;
    @XmlElement(name = "cfdi:Addenda")
    protected Comprobante40.Addenda addenda;
    @XmlAttribute(name = "Version", required = true)
    protected String version;
    @XmlAttribute(name = "Serie")
    protected String serie;
    @XmlAttribute(name = "Folio")
    protected String folio;
    @XmlAttribute(name = "Fecha", required = true)
    protected String fecha;
    @XmlAttribute(name = "Sello", required = true)
    protected String sello;
    @XmlAttribute(name = "FormaPago")
    protected String formaPago;
    @XmlAttribute(name = "NoCertificado", required = true)
    protected String noCertificado;
    @XmlAttribute(name = "Certificado", required = true)
    protected String certificado;
    @XmlAttribute(name = "CondicionesDePago")
    protected String condicionesDePago;
    @XmlAttribute(name = "SubTotal", required = true)
    protected double subTotal;
    @XmlAttribute(name = "Descuento")
    protected double descuento;
    @XmlAttribute(name = "Moneda", required = true)
    protected CMoneda moneda;
    @XmlAttribute(name = "TipoCambio")
    protected int tipoCambio;
    @XmlAttribute(name = "Total", required = true)
    protected double total;
    @XmlAttribute(name = "TipoDeComprobante", required = true)
    protected CTipoDeComprobante tipoDeComprobante;
    @XmlAttribute(name = "Exportacion", required = true)
    protected String exportacion;
    @XmlAttribute(name = "MetodoPago")
    protected CMetodoPago metodoPago;
    @XmlAttribute(name = "LugarExpedicion", required = true)
    protected String lugarExpedicion;
    @XmlAttribute(name = "Confirmacion")
    protected String confirmacion;

    public Comprobante40() {
    }

    public String getXmlnsCfdi() {
        return xmlnsCfdi;
    }

    public void setXmlnsCfdi(String xmlnsCfdi) {
        this.xmlnsCfdi = xmlnsCfdi;
    }

    public String getXmlnsXsi() {
        return xmlnsXsi;
    }

    public void setXmlnsXsi(String xmlnsXsi) {
        this.xmlnsXsi = xmlnsXsi;
    }

    public String getXsiSchemaLocation() {
        return xsiSchemaLocation;
    }

    public void setXsiSchemaLocation(String xsiSchemaLocation) {
        this.xsiSchemaLocation = xsiSchemaLocation;
    }
    
    public Comprobante40.InformacionGlobal getInformacionGlobal() {
        return informacionGlobal;
    }

    public void setInformacionGlobal(Comprobante40.InformacionGlobal value) {
        this.informacionGlobal = value;
    }

    public List<Comprobante40.CfdiRelacionados> getCfdiRelacionados() {
        if (cfdiRelacionados == null) {
            cfdiRelacionados = new ArrayList<Comprobante40.CfdiRelacionados>();
        }
        return this.cfdiRelacionados;
    }

    public Comprobante40.Emisor getEmisor() {
        return emisor;
    }

    public void setEmisor(Comprobante40.Emisor value) {
        this.emisor = value;
    }

    public Comprobante40.Receptor getReceptor() {
        return receptor;
    }

    public void setReceptor(Comprobante40.Receptor value) {
        this.receptor = value;
    }

    public Conceptos getConceptos() {
        return conceptos;
    }

    public void setConceptos(Conceptos value) {
        this.conceptos = value;
    }

    public Comprobante40.Impuestos getImpuestos() {
        return impuestos;
    }

    public void setImpuestos(Comprobante40.Impuestos value) {
        this.impuestos = value;
    }

    public Comprobante40.Complemento getComplemento() {
        return complemento;
    }

    public void setComplemento(Comprobante40.Complemento value) {
        this.complemento = value;
    }

    public Comprobante40.Addenda getAddenda() {
        return addenda;
    }

    public void setAddenda(Comprobante40.Addenda value) {
        this.addenda = value;
    }

    public String getVersion() {
        if (version == null) {
            return "4.0";
        } else {
            return version;
        }
    }

    public void setVersion(String value) {
        this.version = value;
    }

    public String getSerie() {
        return serie == null ? "" : serie;
    }

    public void setSerie(String value) {
        this.serie = value;
    }

    public String getFolio() {
        return folio == null ? "" : folio;
    }

    public void setFolio(String value) {
        this.folio = value;
    }

    public String getFechaComprobante() {
        return fecha;
    }

    public void setFecha(String value) {
        this.fecha = value;
    }

    public String getSello() {
        return sello == null ? "" : sello;
    }

    public void setSello(String value) {
        this.sello = value;
    }

    public String getFormaPago() {
        return formaPago == null ? "" : formaPago;
    }

    public void setFormaPago(String value) {
        this.formaPago = value;
    }

    public String getNoCertificado() {
        return noCertificado == null ? "" : noCertificado;
    }

    public void setNoCertificado(String value) {
        this.noCertificado = value;
    }

    public String getCertificado() {
        return certificado == null ? "" : certificado;
    }

    public void setCertificado(String value) {
        this.certificado = value;
    }

    public String getCondicionesDePago() {
        return condicionesDePago == null ? "" : condicionesDePago;
    }

    public void setCondicionesDePago(String value) {
        this.condicionesDePago = value;
    }

    public double getSubTotal() {
        return subTotal;
    }

    public void setSubTotal(double value) {
        this.subTotal = value;
    }

    public double getDescuento() {
        return descuento;
    }

    public void setDescuento(double value) {
        this.descuento = value;
    }

    public CMoneda getMonedaComprobante() {
        return moneda;
    }

    public void setMonedaComprobante(CMoneda value) {
        this.moneda = value;
    }

    public void setTipoCambio(int value) {
        this.tipoCambio = value;
    }

    public double getTotal() {
        return total;
    }

    public void setTotal(double value) {
        this.total = value;
    }

    public CTipoDeComprobante getTipoDeComprobante() {
        return tipoDeComprobante;
    }

    public void setTipoDeComprobante(CTipoDeComprobante value) {
        this.tipoDeComprobante = value;
    }

    public String getExportacion() {
        return exportacion;
    }

    public void setExportacion(String value) {
        this.exportacion = value;
    }

    public CMetodoPago getMetodoPago() {
        return metodoPago;
    }

    public void setMetodoPago(CMetodoPago value) {
        this.metodoPago = value;
    }

    public String getLugarExpedicion() {
        return lugarExpedicion == null ? "" : lugarExpedicion;
    }

    public void setLugarExpedicion(String value) {
        this.lugarExpedicion = value;
    }

    public String getConfirmacion() {
        return confirmacion == null ? "" : confirmacion;
    }

    public void setConfirmacion(String value) {
        this.confirmacion = value;
    }

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {"any"})
    public static class Addenda implements Serializable {

        private static final long serialVersionUID = 1L;
        @XmlAnyElement(lax = true)
        protected List<Object> any;

        public List<Object> getAny() {
            if (any == null) {
                any = new ArrayList<Object>();
            }
            return this.any;
        }

    }

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {"cfdiRelacionado"})
    public static class CfdiRelacionados implements Serializable {

        private static final long serialVersionUID = 1L;
        @XmlElement(name = "CfdiRelacionado", required = true)
        protected List<Comprobante40.CfdiRelacionados.CfdiRelacionado> cfdiRelacionado;
        @XmlAttribute(name = "TipoRelacion", required = true)
        protected String tipoRelacion;

        public List<Comprobante40.CfdiRelacionados.CfdiRelacionado> getCfdiRelacionado() {
            if (cfdiRelacionado == null) {
                cfdiRelacionado = new ArrayList<Comprobante40.CfdiRelacionados.CfdiRelacionado>();
            }
            return this.cfdiRelacionado;
        }

        public String getTipoRelacion() {
            return tipoRelacion == null ? "" : tipoRelacion;
        }

        public void setTipoRelacion(String value) {
            this.tipoRelacion = value;
        }

        @XmlAccessorType(XmlAccessType.FIELD)
        @XmlType(name = "")
        public static class CfdiRelacionado implements Serializable {

            private static final long serialVersionUID = 1L;
            @XmlAttribute(name = "UUID", required = true)
            protected String uuid;

            public String getUUID() {
                return uuid == null ? "" : uuid;
            }

            public void setUUID(String value) {
                this.uuid = value;
            }

        }

    }

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {"any","timbreFiscal"})
    public static class Complemento implements Serializable {
        
        
        private static final long serialVersionUID = 1L;
        @XmlElement(name = "tfd:TimbreFiscalDigital")
        protected Comprobante40.Complemento.TimbreFiscalDigital timbreFiscal; 
        
        @XmlAnyElement(lax = true)
        protected List<Object> any;

        public List<Object> getAny() {
            if (any == null) {
                any = new ArrayList<Object>();
            }
            return this.any;
        }

        public TimbreFiscalDigital getTimbreFiscal() {
            return timbreFiscal;
        }

        public void setTimbreFiscal(TimbreFiscalDigital timbreFiscal) {
            this.timbreFiscal = timbreFiscal;
        }
        
        
        
        @XmlAccessorType(XmlAccessType.FIELD)
        @XmlType(name = "")
        public static class TimbreFiscalDigital implements Serializable {
        @XmlAttribute(name = "xmlns:tfd", required = true)
        protected String xmlnsFtd;
        @XmlAttribute(name = "xsi:schemaLocation", required = true)
        protected String xsiSchemaLocation;
        @XmlAttribute(name = "Version", required = true)
        protected String version;
        @XmlAttribute(name = "UUID")
        protected String uuid;
        @XmlAttribute(name = "FechaTimbrado")
        protected String fechaTimbrado;
        @XmlAttribute(name = "RfcProvCertif", required = true)
        protected String rfcProvCertif;
        @XmlAttribute(name = "SelloCFD", required = true)
        protected String selloCFD;
        @XmlAttribute(name = "NoCertificadoSAT", required = true)
        protected String noCertificadoSAT;
        @XmlAttribute(name = "SelloSAT")
        protected String selloSAT;
        
        
        public String getXmlnsFtd() {
            return xmlnsFtd;
        }

        public void setXmlnsFtd(String xmlnsFtd) {
            this.xmlnsFtd = xmlnsFtd;
        }

        public String getXsiSchemaLocation() {
            return xsiSchemaLocation;
        }

        public void setXsiSchemaLocation(String xsiSchemaLocation) {
            this.xsiSchemaLocation = xsiSchemaLocation;
        }

        public String getVersion() {
            return version;
        }

        public void setVersion(String version) {
            this.version = version;
        }

        public String getUuid() {
            return uuid;
        }

        public void setUuid(String uuid) {
            this.uuid = uuid;
        }

        public String getRfcProvCertif() {
            return rfcProvCertif;
        }

        public void setRfcProvCertif(String rfcProvCertif) {
            this.rfcProvCertif = rfcProvCertif;
        }

        public String getSelloCFD() {
            return selloCFD;
        }

        public void setSelloCFD(String selloCFD) {
            this.selloCFD = selloCFD;
        }

        public String getNoCertificadoSAT() {
            return noCertificadoSAT;
        }

        public void setNoCertificadoSAT(String noCertificadoSAT) {
            this.noCertificadoSAT = noCertificadoSAT;
        }

        public String getSelloSAT() {
            return selloSAT;
        }

        public void setSelloSAT(String selloSAT) {
            this.selloSAT = selloSAT;
        }

        public String getFechaTimbrado() {
            return fechaTimbrado;
        }

        public void setFechaTimbrado(String fechaTimbrado) {
            this.fechaTimbrado = fechaTimbrado;
        }
        }

        
        
        

    }

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "")
    public static class Emisor implements Serializable {

        private static final long serialVersionUID = 1L;
        @XmlAttribute(name = "Rfc", required = true)
        protected String rfc;
        @XmlAttribute(name = "Nombre", required = true)
        protected String nombre;
        @XmlAttribute(name = "RegimenFiscal", required = true)
        protected String regimenFiscal;
        @XmlAttribute(name = "FacAtrAdquirente")
        protected String facAtrAdquirente;

        public String getRfc() {
            return rfc == null ? "" : rfc;
        }

        public void setRfc(String value) {
            this.rfc = value;
        }

        public String getNombre() {
            return nombre == null ? "" : nombre;
        }

        public void setNombre(String value) {
            this.nombre = value;
        }

        public String getRegimenFiscal() {
            return regimenFiscal == null ? "" : regimenFiscal;
        }

        public void setRegimenFiscal(String value) {
            this.regimenFiscal = value;
        }

        public String getFacAtrAdquirente() {
            return facAtrAdquirente == null ? "" : facAtrAdquirente;
        }

        public void setFacAtrAdquirente(String value) {
            this.facAtrAdquirente = value;
        }

    }

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {"retenciones", "traslados"})
    public static class Impuestos implements Serializable {

        private static final long serialVersionUID = 1L;
        @XmlElement(name = "Retenciones")
        protected Comprobante40.Impuestos.Retenciones retenciones;
        @XmlElement(name = "cfdi:Traslados")
        protected Comprobante40.Impuestos.Traslados traslados;
        @XmlAttribute(name = "TotalImpuestosRetenidos")
        protected BigDecimal totalImpuestosRetenidos;
        @XmlAttribute(name = "TotalImpuestosTrasladados")
        protected BigDecimal totalImpuestosTrasladados;

        public Comprobante40.Impuestos.Retenciones getRetenciones() {
            return retenciones;
        }

        public void setRetenciones(Comprobante40.Impuestos.Retenciones value) {
            this.retenciones = value;
        }

        public Comprobante40.Impuestos.Traslados getTraslados() {
            return traslados;
        }

        public void setTraslados(Comprobante40.Impuestos.Traslados value) {
            this.traslados = value;
        }

        public BigDecimal getTotalImpuestosRetenidos() {
            return totalImpuestosRetenidos;
        }

        public void setTotalImpuestosRetenidos(BigDecimal value) {
            this.totalImpuestosRetenidos = value;
        }

        public BigDecimal getTotalImpuestosTrasladados() {
            return totalImpuestosTrasladados;
        }

        public void setTotalImpuestosTrasladados(BigDecimal value) {
            this.totalImpuestosTrasladados = value;
        }

        @XmlAccessorType(XmlAccessType.FIELD)
        @XmlType(name = "", propOrder = {"retencion"})
        public static class Retenciones implements Serializable {

            private static final long serialVersionUID = 1L;
            @XmlElement(name = "Retencion", required = true)
            protected List<Comprobante40.Impuestos.Retenciones.Retencion> retencion;

            public List<Comprobante40.Impuestos.Retenciones.Retencion> getRetencion() {
                if (retencion == null) {
                    retencion = new ArrayList<Comprobante40.Impuestos.Retenciones.Retencion>();
                }
                return this.retencion;
            }

            @XmlAccessorType(XmlAccessType.FIELD)
            @XmlType(name = "")
            public static class Retencion implements Serializable {

                private static final long serialVersionUID = 1L;
                @XmlAttribute(name = "Impuesto", required = true)
                protected String impuesto;
                @XmlAttribute(name = "Importe", required = true)
                protected BigDecimal importe;

                public String getImpuesto() {
                    return impuesto == null ? "" : impuesto;
                }

                public void setImpuesto(String value) {
                    this.impuesto = value;
                }

                public BigDecimal getImporte() {
                    return importe;
                }

                public void setImporte(BigDecimal value) {
                    this.importe = value;
                }

            }

        }

        @XmlAccessorType(XmlAccessType.FIELD)
        @XmlType(name = "", propOrder = {"traslado"})
        public static class Traslados implements Serializable {

            private static final long serialVersionUID = 1L;
            @XmlElement(name = "cfdi:Traslado", required = true)
            protected List<Comprobante40.Impuestos.Traslados.Traslado> traslado;

            public List<Comprobante40.Impuestos.Traslados.Traslado> getTraslado() {
                if (traslado == null) {
                    traslado = new ArrayList<Comprobante40.Impuestos.Traslados.Traslado>();
                }
                return this.traslado;
            }
            
            public void setTranslado(Comprobante40.Impuestos.Traslados.Traslado traslado) {
                    getTraslado().add(traslado);
            }

            @XmlAccessorType(XmlAccessType.FIELD)
            @XmlType(name = "")
            public static class Traslado implements Serializable {

                private static final long serialVersionUID = 1L;
                @XmlAttribute(name = "Base", required = true)
                protected BigDecimal base;
                @XmlAttribute(name = "Impuesto", required = true)
                protected String impuesto;
                @XmlAttribute(name = "TipoFactor", required = true)
                protected CTipoFactor tipoFactor;
                @XmlAttribute(name = "TasaOCuota", required = true)
                protected BigDecimal tasaOCuota;
                @XmlAttribute(name = "Importe", required = true)
                protected BigDecimal importe;

                public BigDecimal getBase() {
                    return base;
                }

                public void setBase(BigDecimal value) {
                    this.base = value;
                }

                public String getImpuesto() {
                    return impuesto == null ? "" : impuesto;
                }

                public void setImpuesto(String value) {
                    this.impuesto = value;
                }

                public CTipoFactor getTipoFactor() {
                    return tipoFactor;
                }

                public void setTipoFactor(CTipoFactor value) {
                    this.tipoFactor = value;
                }

                public BigDecimal getTasaOCuota() {
                    return tasaOCuota;
                }

                public void setTasaOCuota(BigDecimal value) {
                    this.tasaOCuota = value;
                }

                public BigDecimal getImporte() {
                    return importe;
                }

                public void setImporte(BigDecimal value) {
                    this.importe = value;
                }

            }

        }

    }

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "")
    public static class InformacionGlobal implements Serializable {

        private static final long serialVersionUID = 1L;
        @XmlAttribute(name = "Periodicidad", required = true)
        protected String periodicidad;
        @XmlAttribute(name = "Meses", required = true)
        protected String meses;
        @XmlAttribute(name = "Año", required = true)
        protected Integer año;

        public String getPeriodicidad() {
            return periodicidad;
        }

        public void setPeriodicidad(String value) {
            this.periodicidad = value;
        }

        public String getMeses() {
            return meses;
        }

        public void setMeses(String value) {
            this.meses = value;
        }

        public Integer getAño() {
            return año;
        }

        public void setAño(Integer value) {
            this.año = value;
        }

    }

    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "")
    public static class Receptor implements Serializable {

        private static final long serialVersionUID = 1L;
        @XmlAttribute(name = "Rfc", required = true)
        protected String rfc;
        @XmlAttribute(name = "Nombre", required = true)
        protected String nombre;
        @XmlAttribute(name = "DomicilioFiscalReceptor", required = true)
        protected String domicilioFiscalReceptor;
        @XmlAttribute(name = "ResidenciaFiscal")
        protected CPais residenciaFiscal;
        @XmlAttribute(name = "NumRegIdTrib")
        protected String numRegIdTrib;
        @XmlAttribute(name = "RegimenFiscalReceptor", required = true)
        protected String regimenFiscalReceptor;
        @XmlAttribute(name = "UsoCFDI", required = true)
        protected CUsoCFDI usoCFDI;

        public String getRfc() {
            return rfc == null ? "" : rfc;
        }

        public void setRfc(String value) {
            this.rfc = value;
        }

        public String getNombre() {
            return nombre == null ? "" : nombre;
        }

        public void setNombre(String value) {
            this.nombre = value;
        }

        public String getDomicilioFiscalReceptor() {
            return domicilioFiscalReceptor == null ? "" : domicilioFiscalReceptor;
        }

        public void setDomicilioFiscalReceptor(String value) {
            this.domicilioFiscalReceptor = value;
        }

        public CPais getResidenciaFiscal() {
            return residenciaFiscal;
        }

        public void setResidenciaFiscal(CPais value) {
            this.residenciaFiscal = value;
        }

        public String getNumRegIdTrib() {
            return numRegIdTrib == null ? "" : numRegIdTrib;
        }

        public void setNumRegIdTrib(String value) {
            this.numRegIdTrib = value;
        }

        public String getRegimenFiscalReceptor() {
            return regimenFiscalReceptor == null ? "" : regimenFiscalReceptor;
        }

        public void setRegimenFiscalReceptor(String value) {
            this.regimenFiscalReceptor = value;
        }

        public CUsoCFDI getUsoCFDI() {
            return usoCFDI;
        }

        public void setUsoCFDI(CUsoCFDI value) {
            this.usoCFDI = value;
        }

    }

    public Object clone() {
        Object clone = null;
        try {
            clone = super.clone();
        } catch (CloneNotSupportedException e) {

            e.printStackTrace();
        }
        return clone;
    }

    public void setNeto(double value) {
        this.subTotal = value;
    }

}
