コード例 #1
0
        private async Task <FECAEResponse> FECAESolicitarAsync(Order order)
        {
            var payerData = new PayerDataRevenue(order, _config.GetValue <int>("LimiteFacturaB"));

            var requestInfo = new FECAERequestInfo(payerData, _calendar.LocalTime(), _config.GetValue <int>("Iva"), _config.GetValue <long>("CUIT"), await GetSignTicket(AfipWsFe, _isProd), await GetTokenTicket(AfipWsFe, _isProd), _config.GetValue <int>("PtoVtaAfip"));

            FECAEResponse result = await FECAESolicitarAsync(requestInfo);

            return(result);
        }
コード例 #2
0
        public async Task <InvoiceData> Facturar(Order order)
        {
            var invoiceData = new InvoiceData();

            try
            {
                FECAEResponse factura = await FECAESolicitarAsync(order);

                invoiceData = _mapper.Map <FECAEResponse.FECAECabResponse, InvoiceData>(factura.FeCabResp);

                if (factura.Errs != null)
                {
                    invoiceData.AddInvoiceDetailRange(factura.Errs.Select(x => new InvoiceDetail("Error", invoiceData, x)));
                }
                if (factura.Events != null)
                {
                    invoiceData.AddInvoiceDetailRange(factura.Errs.Select(x => new InvoiceDetail("Evento", invoiceData, x)));
                }

                if (factura.FeDetResp != null)
                {
                    var obs = new List <FECAEResponse.CodeMessage>();
                    foreach (var ob in factura.FeDetResp.Where(o => o.Observaciones != null))
                    {
                        obs.AddRange(ob.Observaciones);
                    }
                    invoiceData.AddInvoiceDetailRange(obs.Select(x => new InvoiceDetail("Observacion", invoiceData, x)));
                    invoiceData.AddCaeRange(factura.FeDetResp.Select(x => { var cae         = _mapper.Map <FECAEResponse.FECAEDetResponse, Cae>(x);
                                                                            cae.InvoiceData = invoiceData;
                                                                            return(cae); }));
                }
            }
            catch (Exception ex)
            {
                var errs = new List <FECAEResponse.CodeMessage>
                {
                    new FECAEResponse.CodeMessage {
                        Code = ex.HResult, Msg = ex.Message
                    }
                };
                invoiceData.AddInvoiceDetailRange(errs.Select(x => new InvoiceDetail("Excepción", invoiceData, x)));
            }
            finally
            {
                invoiceData.Order   = order;
                invoiceData.OrderId = order.OrderId;
                invoiceData.Created = _calendar.LocalTime();
            }
            await _dbCtx.InvoiceData.AddAsync(invoiceData);

            await _dbCtx.SaveChangesAsync();

            return(invoiceData);
        }
コード例 #3
0
        private static string consultarAfip(int p_pv, int p_codigo, double p_importe, double p_iva, double p_total, DateTime p_fecha, long doc, int concepto, int tipo_doc, int tipo_iva, string moneda)
        {
            numero_comprobante = 0;
            cae_comprobante    = "";
            cae_vencimiento    = "";
            mensaje_afip       = "";
            mensaje_obs        = "";
            mensaje_error      = "";
            string m = "";

            resultado = "R";

            try
            {
                if (Main.authRequest == null)
                {
                    Main.authRequest       = new FEAuthRequest();
                    Main.authRequest.Cuit  = Main.CUIT;
                    Main.authRequest.Sign  = Main.SING;
                    Main.authRequest.Token = Main.TOKEN;
                }

                AFIP.TEST.WSFE.Service service = getServicio();
                service.ClientCertificates.Add(Main.certificado);

                /*
                 * if (Main.Testing == 1)
                 * {
                 *  AFIP.TEST.WSFE.Service service = getServicioTest();
                 *  service.ClientCertificates.Add(Main.certificado);
                 * }
                 * else
                 * {
                 *  AFIP.WSFE.Service service = getServicioProducion();
                 *  service.ClientCertificates.Add(Main.certificado);
                 * }*/
                //PtoVenta pvObj = ptos_venta_cm.SelectedItem;
                //int pv = p_pv;//pvObj.Nro;
                //CbteTipo cm = p_codigo;//TiposComprobantesCMB.SelectedItem;

                FECAERequest    req = new FECAERequest();
                FECAECabRequest cab = new FECAECabRequest();
                FECAEDetRequest det = new FECAEDetRequest();

                cab.CantReg  = 1;
                cab.PtoVta   = p_pv;
                cab.CbteTipo = p_codigo;//cm.Id;
                req.FeCabReq = cab;

                FECAEDetRequest bar = det;
                //ConceptoTipo concepto = TipoConcepto.SelectedItem;
                bar.Concepto = concepto; //concepto.ID;
                //DocTipo doctipo = TipoDocCMB.SelectedItem;
                bar.DocTipo = tipo_doc;  //doctipo.Id
                bar.DocNro  = doc;       //long.Parse(DocTX.Text)

                //Buscar el ultimo numero
                try
                {
                    FERecuperaLastCbteResponse lastRes = service.FECompUltimoAutorizado(Main.authRequest, p_pv, p_codigo);
                    int last = lastRes.CbteNro;

                    bar.CbteDesde = last + 1;
                    bar.CbteHasta = last + 1;
                }
                catch
                {
                    bar.CbteDesde = p_codigo;
                    bar.CbteHasta = p_codigo;
                }

                bar.CbteFch = p_fecha.ToString("yyyyMMdd");              //FechaDTP.Value.ToString("yyyyMMdd");

                bar.ImpNeto  = Double.Parse(p_importe.ToString("0.00")); //NetoTX.Text;
                bar.ImpIVA   = Double.Parse(p_iva.ToString("0.00"));     // ImpIvaTx.Text;
                bar.ImpTotal = Double.Parse(p_total.ToString("0.00"));   // TotalTx.Text;

                bar.ImpTotConc = 0;
                bar.ImpOpEx    = 0;
                bar.ImpTrib    = 0;

                //Moneda mon = MonedaCMB.SelectedItem;
                bar.MonId    = moneda;// mon.Id
                bar.MonCotiz = 1;

                AlicIva alicuota = new AlicIva();
                //IvaTipo ivat = TipoIVACmb.SelectedItem;
                alicuota.Id      = tipo_iva;                             // ivat.Id
                alicuota.BaseImp = p_importe;                            // NetoTX.Text
                alicuota.Importe = Double.Parse(p_iva.ToString("0.00")); // ImpIvaTx.Text

                bar.Iva = new AlicIva[] { alicuota };
                //bar.Iva.Append(alicuota);

                req.FeDetReq = new FECAEDetRequest[] { bar };
                //req.FeDetReq.Append(bar);


                try
                {
                    FECAEResponse r      = service.FECAESolicitar(Main.authRequest, req);
                    string        vbCrLf = "\n";

                    resultado = r.FeDetResp[0].Resultado;

                    m  = "Estado Cabecera: " + r.FeCabResp.Resultado + vbCrLf;
                    m += "Estado Detalle: " + r.FeDetResp[0].Resultado;
                    m += vbCrLf;
                    m += "CAE: " + r.FeDetResp[0].CAE;
                    m += vbCrLf;
                    m += "Vto: " + r.FeDetResp[0].CAEFchVto;
                    m += vbCrLf;
                    m += "Numero de comprobante: " + r.FeDetResp[0].CbteDesde;
                    m += vbCrLf;

                    numero_comprobante = r.FeDetResp[0].CbteDesde;
                    cae_comprobante    = r.FeDetResp[0].CAE;
                    cae_vencimiento    = r.FeDetResp[0].CAEFchVto;

                    if (r.FeDetResp[0].Observaciones != null)
                    {
                        foreach (var o in r.FeDetResp[0].Observaciones)
                        {
                            mensaje_obs += string.Format("Obs: {0} ({1})", o.Msg, o.Code) + vbCrLf;
                            m           += mensaje_obs;
                        }
                    }
                    if (r.Errors != null)
                    {
                        foreach (var er in r.Errors)
                        {
                            mensaje_error += string.Format("Er: {0}: {1}", er.Code, er.Msg) + vbCrLf;
                            m             += mensaje_error;
                        }
                    }
                    if (r.Events != null)
                    {
                        foreach (var ev in r.Events)
                        {
                            mensaje_afip += string.Format("Ev: {0}: {1}", ev.Code, ev.Msg) + vbCrLf;
                            m            += mensaje_afip;
                        }
                    }
                }
                catch (Exception e)
                {
                    LogHelper.Log(LogTarget.File, DateTime.Now.ToString() + " - ERROR COMPROBANTE AFIP: " + e.Message + " - " + e.StackTrace);
                    m = "ERROR";
                    return(m);
                }



                //Resultado.Text = m
                LogHelper.Log(LogTarget.File, DateTime.Now.ToString() + " - Consultando en AFIP: " + resultado);
            }
            catch (Exception e)
            {
                LogHelper.Log(LogTarget.File, DateTime.Now.ToString() + " - ERROR COMPROBANTE AFIP: " + e.Message + " - " + e.StackTrace);
                //MessageBox.Show("ERROR: "+e.Message+"\n"+e.StackTrace);
            }

            return(m);
        }
コード例 #4
0
        public CorridaAutorizacionDto AutorizarComprobantes(CorridaAutorizacionDto corridaDto)
        {
            try
            {
                this.corridaDto = corridaDto;
                string pathArchivoOrigen = corridaDto.PathArchivo;

                if (string.IsNullOrEmpty(corridaDto.PathArchivo))
                {
                    this.Log("ERROR: No se ha ingresado el path del archivo");
                }

                // Cambio para el WSFEX

                bool procesarFacturaExportacion = false;
                using (StreamReader reader = new StreamReader(corridaDto.PathArchivo))
                {
                    string line = reader.ReadLine();
                    line = reader.ReadLine();
                    if (line.Contains("FacturaExportacion"))
                    {
                        procesarFacturaExportacion = true;
                    }
                    reader.Close();
                }

                if (procesarFacturaExportacion)
                {
                    corridaDto = AutorizarComprobantesParaWsFeX(this.corridaDto);
                }
                else
                {
                    // Fin Cambio para el WSFEX

                    // Marco la corrida como en proceso en la base de datos
                    if (this.corridaSvc.MarcarCorridaEnProceso(corridaDto.Id))
                    {
                        // Inicio Proceso
                        this.Log(string.Format("Iniciando procesamiento de archivo {0}...", this.nombreDeArchivo));

                        // Valido el Esquema de Xml
                        this.Log(string.Format("Validando esquema de archivo"));
                        string xmlSchemaPath = "";

                        if (!this.ValidarEsquemaXml(corridaDto.PathArchivo, xmlSchemaPath))
                        {
                            StringBuilder sb = new StringBuilder();
                            sb.AppendLine("ERROR: el formato del archivo es invalido");
                            sb.AppendLine(this.validacionesEsquema.ToString());
                            this.Log(sb.ToString());
                            return(null);
                        }

                        // Leo archivo XML y lo paso a string
                        this.Log("Leyendo archivo...");
                        string xmlString = LeerArchivo(corridaDto.PathArchivo);

                        // Reemplazo <Lote></Lote> por <FeCAEReq></FeCAEReq>
                        xmlString = xmlString.Replace("<Lote>", "<FECAERequest>").Replace("</Lote>", "</FECAERequest>");

                        // Deserealizo el XML y obtengo solo la parte del request
                        FECAERequest feCAERequest = null;
                        try
                        {
                            feCAERequest = DeserializarXml <FECAERequest>(xmlString);
                        }
                        catch (Exception ex)
                        {
                            this.Log("El formato del archivo es inválido.");
                            return(null);
                        }

                        // Obtengo Ticket de Autorizacion
                        this.Log("Iniciando comunicacion con la AFIP");
                        FEAuthRequest feAuthRequest = this.ObtenerTicket();

                        // Cargo los comprobantes que estan autorizados en la AFIP
                        // pero que no fueron cargados en la DB por problemas en
                        // la comunicacion
                        this.CargarComprobantesYaAutorizados(feAuthRequest, feCAERequest);

                        // Remover Comprobantes que ya han sido autorizados
                        string resultado = this.RemoverComprobantesAutorizados(feAuthRequest, feCAERequest);
                        if (!string.IsNullOrEmpty(resultado))
                        {
                            this.Log(resultado);
                            feCAERequest.FeCabReq.CantReg = feCAERequest.FeDetReq.Count();
                        }

                        if (feCAERequest.FeDetReq != null && feCAERequest.FeDetReq.Count() > 0)
                        {
                            // Autorizar Comprobantes con la AFIP
                            this.Log("Autorizando Comprobantes con la AFIP...");
                            FECAEResponse feCAEResponse = this.AutorizarComprobantes(feAuthRequest, feCAERequest);

                            // Proceso Resultado AFIP
                            this.Log("Procesando respuesta de la AFIP...");
                            corridaDto = this.corridaSvc.ProcesarCorrida(corridaDto, feCAEResponse);
                        }
                        else
                        {
                            // Todos los comprobantes del archivo ya tienen un CAE asignado
                            // y existen en DB
                            this.Log("Todos los comprobantes del archivo ya han sido autorizados");
                        }

                        // Muevo el archivo a una carpeta de procesados
                        GuardarArchivoProcesado(pathArchivoOrigen);

                        this.Log("Fin procesamiento de archivo.");
                    }
                    else
                    {
                        this.Log("La corrida ya se está ejecutando");
                    }
                }

                return(corridaDto);
            }
            catch (Exception ex)
            {
                string detalle = string.Format("ex.Message: {0} ex.StackTrace: {1}", ex.Message, ex.StackTrace);
                this.Log(string.Format("ERROR: Se ha producido un error. Contactese con el administrador. Error: {0}", ex.Message), detalle);
                return(null);
            }
            finally
            {
                this.Log(CorridaService.FinCorridaMsg);
            }
        }
コード例 #5
0
        public CorridaAutorizacionDto ProcesarCorrida(CorridaAutorizacionDto corridaDto, FECAEResponse feCAEResponse)
        {
            using (var ctx = new FacturaElectronicaEntities())
            {
                CorridaAutorizacion corrida = ctx.CorridaAutorizacions.Where(c => c.Id == corridaDto.Id).First();

                // Procesar Cabecera
                DetalleCabecera cabecera  = new DetalleCabecera();
                FECabResponse   feCabResp = feCAEResponse.FeCabResp;
                cabecera.CantReg    = feCabResp.CantReg;
                cabecera.CUIT       = feCabResp.Cuit;
                cabecera.CbteTipo   = feCabResp.CbteTipo;
                cabecera.FchProceso = DateTimeHelper.ConvertyyyyMMddhhmmssToDate(feCabResp.FchProceso);
                cabecera.Resultado  = feCabResp.Resultado;
                cabecera.PtoVta     = feCabResp.PtoVta;

                corrida.DetalleCabeceras.Add(cabecera);

                TipoComprobanteDto tipoCbteDto = cbteSvc.ObtenerTipoComprobantePorCodigoAfip(cabecera.CbteTipo);
                int tipoCbteId;
                if (tipoCbteDto != null)
                {
                    tipoCbteId = tipoCbteDto.Id;
                }

                if (feCAEResponse.FeDetResp != null && feCAEResponse.FeDetResp.Count() > 0)
                {
                    // Procesar Comprobantes
                    DetalleComprobante     detalleCbte       = null;
                    ObservacionComprobante observacionesCbte = null;
                    foreach (FECAEDetResponse cbte in feCAEResponse.FeDetResp)
                    {
                        detalleCbte           = new DetalleComprobante();
                        detalleCbte.Concepto  = cbte.Concepto;
                        detalleCbte.DocTipo   = cbte.DocTipo;
                        detalleCbte.DocNro    = cbte.DocNro;
                        detalleCbte.CbteDesde = cbte.CbteDesde;
                        detalleCbte.CbteHasta = cbte.CbteHasta;
                        detalleCbte.CbteFch   = DateTimeHelper.ConvertyyyyMMddToDate(cbte.CbteFch);
                        detalleCbte.Resultado = cbte.Resultado;


                        if (cbte.Resultado == ResultadoCbte.Aprobado)
                        {
                            detalleCbte.CAE       = cbte.CAE;
                            detalleCbte.CAEFchVto = DateTimeHelper.ConvertyyyyMMddToDate(cbte.CAEFchVto);

                            // Si fue aprobado agrego una entidad Comprobante
                            Comprobante comprobante = new Comprobante();
                            comprobante.CAE = detalleCbte.CAE;
                            comprobante.CAEFechaVencimiento = detalleCbte.CAEFchVto;
                            comprobante.CbteDesde           = detalleCbte.CbteDesde;
                            comprobante.CbteHasta           = detalleCbte.CbteHasta;
                            comprobante.CbteFecha           = detalleCbte.CbteFch;
                            comprobante.PtoVta          = cabecera.PtoVta;
                            comprobante.FechaDeCarga    = DateTime.Now;
                            comprobante.TipoComprobante = ctx.TipoComprobantes.Where(tc => tc.CodigoAfip == cabecera.CbteTipo).FirstOrDefault();
                            if (detalleCbte.DocTipo == 80) // CUIT
                            {
                                ClienteDto clienteDto = clienteSvc.ObtenerClientePorCuit(detalleCbte.DocNro);
                                if (clienteDto != null)
                                {
                                    comprobante.ClienteId = clienteDto.Id;
                                }
                            }
                            // #TODO: borrar
                            //EstadoComprobanteDto estadoDto = this.cbteSvc.ObtenerEstado(CodigoEstadoCbte.NoVisualizado);
                            //if (estadoDto != null)
                            //{
                            //    comprobante.EstadoId = estadoDto.Id;
                            //}
                            detalleCbte.Comprobantes.Add(comprobante);
                        }
                        else
                        {
                            if (cbte.Observaciones != null && cbte.Observaciones.Count() > 0)
                            {
                                foreach (Obs obs in cbte.Observaciones)
                                {
                                    observacionesCbte      = new ObservacionComprobante();
                                    observacionesCbte.Code = obs.Code;
                                    observacionesCbte.Msg  = obs.Msg;
                                    detalleCbte.ObservacionComprobantes.Add(observacionesCbte);
                                }
                            }
                        }
                        corrida.DetalleComprobantes.Add(detalleCbte);
                    }
                }
                if (feCAEResponse.Events != null && feCAEResponse.Events.Count() > 0)
                {
                    // Procesar Eventos
                    DetalleEvento detalleEvento = null;
                    foreach (Evt evento in feCAEResponse.Events)
                    {
                        detalleEvento      = new DetalleEvento();
                        detalleEvento.Code = evento.Code;
                        detalleEvento.Msg  = evento.Msg;
                        corrida.DetalleEventos.Add(detalleEvento);
                    }
                }
                if (feCAEResponse.Errors != null && feCAEResponse.Errors.Count() > 0)
                {
                    // Procesar Errores
                    DetalleError detalleError = null;
                    foreach (Err error in feCAEResponse.Errors)
                    {
                        detalleError      = new DetalleError();
                        detalleError.Code = error.Code;
                        detalleError.Msg  = error.Msg;
                        corrida.DetalleErrores.Add(detalleError);
                    }
                }

                corrida.Procesada = true;

                ctx.SaveChanges();
                return(ToCorridaDto(corrida, ctx.TipoDocumentoes.ToList(), ctx.TipoComprobantes.ToList(), ctx.TipoConceptoes.ToList()));
            }
        }
コード例 #6
0
        public string comprobante_electronico(int tipocomprobante, long nrodoc, double total, double neto21, double civa21, double neto105, double civa105, ref string cae, ref string fechavto, ref string tipofactura, ref string puntoventa)
        {
            try
            {
                LoginClass miloginclase = new LoginClass("wsfe", NegocioConfigEmpresa.urllogin, @"C:\CertificadodonVito\certificado.pfx", "");
                miloginclase.hacerLogin(miloginclase);
                int doctipoid = 96;
                authRequest       = new FEAuthRequest();
                authRequest.Cuit  = NegocioConfigEmpresa.emcuit;
                authRequest.Sign  = miloginclase.Sing;
                authRequest.Token = miloginclase.Token;

                Service servicio = new Service();
                servicio     = getServicio();
                servicio.Url = NegocioConfigEmpresa.urlservicio;
                //servicio.ClientCertificates.Add(certificado);

                //ver conceptoid
                int conceptoid = CONCEPTO_PRODUCTO;
                if (nrodoc.ToString().Length == 11)
                {
                    doctipoid = 80;
                }


                //  Service service = getServicio();
                servicio.ClientCertificates.Add(miloginclase.Certificado);
                FECAERequest    req = new FECAERequest();
                FECAECabRequest cab = new FECAECabRequest();
                FECAEDetRequest det = new FECAEDetRequest();

                cab.CantReg  = 1;
                cab.PtoVta   = Convert.ToInt32(NegocioConfigEmpresa.puntoventa);
                cab.CbteTipo = tipocomprobante;
                req.FeCabReq = cab;

                det.Concepto = conceptoid;
                det.DocTipo  = doctipoid;
                det.DocNro   = nrodoc;

                // ultimo comprobante autorizado

                FERecuperaLastCbteResponse lastres = servicio.FECompUltimoAutorizado(authRequest, 3, tipocomprobante);
                int last = lastres.CbteNro;
                det.CbteDesde = last + 1;
                det.CbteHasta = last + 1;
                int nrocomprobante = last + 1;

                det.CbteFch = DateTime.Now.ToString("yyyyMMdd");
                if (tipocomprobante == 1 || tipocomprobante == 6)
                {
                    decimal totalneto = decimal.Round(Convert.ToDecimal(neto21 + neto105), 2);
                    decimal totaliva  = decimal.Round(Convert.ToDecimal(civa21 + civa105), 2);
                    det.ImpNeto = Convert.ToDouble(totalneto);
                    det.ImpIVA  = Convert.ToDouble(totaliva);
                }
                else
                {
                    det.ImpNeto = total;
                    det.ImpIVA  = 0;
                }

                det.ImpTotal = total;

                det.ImpTotConc = 0.00;
                det.ImpOpEx    = 0.00;
                det.ImpTrib    = 0.00;

                det.MonId    = "PES";
                det.MonCotiz = 1;
                int     tipoalicuota = ID_TASA_IVA_NINGUNO;
                AlicIva alicuota     = new AlicIva();
                if (tipocomprobante == TIPOCOMPROBANTE_FACTURA_A || tipocomprobante == TIPOCOMPROBANTE_FACTURA_B)
                {
                    tipoalicuota     = ID_TASA_IVA_21_00;
                    alicuota.Id      = tipoalicuota;
                    alicuota.BaseImp = neto21;
                    alicuota.Importe = civa21;
                    if (neto105 > 0)
                    {
                        AlicIva alicuota2 = new AlicIva();
                        tipoalicuota      = ID_TASA_IVA_10_50;
                        alicuota2.Id      = tipoalicuota;
                        alicuota2.BaseImp = neto105;
                        alicuota2.Importe = civa105;
                        det.Iva           = new[] { alicuota, alicuota2 };
                    }
                    else
                    {
                        det.Iva = new[] { alicuota };
                    }
                }
                else
                {
                    alicuota.Id      = tipoalicuota;
                    alicuota.BaseImp = 0;
                    alicuota.Importe = 0;
                    det.Iva          = new[] { alicuota };
                }



                req.FeDetReq = new[] { det };

                FECAEResponse r = servicio.FECAESolicitar(authRequest, req);
                cae = r.FeDetResp[0].CAE; //string CAE
                string ESTADO    = r.FeCabResp.Resultado;
                string resultado = r.FeDetResp[0].Resultado;
                fechavto = r.FeDetResp[0].CAEFchVto;//string vto

                puntoventa  = NegocioConfigEmpresa.puntoventa;
                tipofactura = tipocomprobante.ToString("00");


                string m = "ok";

                {
                    if (r.FeDetResp[0].Observaciones is object)
                    {
                        foreach (var o in r.FeDetResp[0].Observaciones)
                        {
                            m += string.Format("Obs: {0} ({1})", o.Msg, o.Code) + Constants.vbCrLf;
                        }
                    }
                }
                {
                    if (r.Errors is object)
                    {
                        foreach (var er in r.Errors)
                        {
                            m += string.Format("Er: {0}: {1}", er.Code, er.Msg) + Constants.vbCrLf;
                        }
                    }
                }
                {
                    if (r.Events is object)
                    {
                        foreach (var ev in r.Events)
                        {
                            m += string.Format("Ev: {0}: {1}", ev.Code, ev.Msg) + Constants.vbCrLf;
                        }
                    }
                }
                if (m == "ok")
                {
                    m = m + nrocomprobante.ToString();
                }
                return(m);
            }
            catch (Exception)
            {
                throw;
            }


            // string error = r.error;
            //  string desde = r.FeDetResp[0].CbteDesde;
            //  string hasta = r.FeDetResp[0].CbteHasta;
            // string OBSERVACION = r.FeDetResp[0].Observaciones;
        }
コード例 #7
0
        public static void SolicitarCAE(this IComprobanteElectronico comprobante, string ta_path, Hamekoz.Core.ICallBack callback)
        {
            var service = new Service();

            //HACK para cambiar de produccion a homologacion
                        #if DEBUG
            service = new Service(homo_url);
                        #endif
            var ta = TA(ta_path);

            //TODO ahora podria utilizar comprobante.Tipo.Codigo validando que sea un valor adecuado
            int tipo           = ComprobanteTipo(comprobante);
            int punto_de_venta = int.Parse(comprobante.Tipo.Pre);

            var fECompUltimoAutorizado = service.FECompUltimoAutorizado(ta, punto_de_venta, tipo);
            int numero = fECompUltimoAutorizado.CbteNro;
            numero++;

            var feCabReq = new FECAECabRequest {
                CantReg  = 1,
                CbteTipo = tipo,
                PtoVta   = punto_de_venta
            };

            var fEDetRequest = new FECAEDetRequest {
                CbteDesde   = numero,
                CbteFch     = comprobante.Emision.ToString("yyyyMMdd"),
                CbteHasta   = numero,
                CbtesAsoc   = null,               //TODO en caso de que sean comprobantes vinculados
                Compradores = null,               //TODO revisar porque no encuentro documentacion
                //HACK producto
                Concepto = 1,
                DocNro   = long.Parse(comprobante.Responsable.CUIT.Limpiar()),
                //HACK CUIT
                DocTipo  = 80,
                ImpIVA   = (double)comprobante.IVA,               //TODO debe excluirse el importe exento, para tipo C debe ser 0
                ImpNeto  = (double)(comprobante.Gravado - comprobante.Exento),
                ImpOpEx  = (double)comprobante.Exento,
                ImpTotal = (double)comprobante.Total,
                //TODO en caso de ser de tipo C debe ser siempre 0
                ImpTotConc = (double)comprobante.NoGravado,
                ImpTrib    = (double)comprobante.Tributos,
                Iva        = comprobante.FEIVAS().ToArray(),
                MonCotiz   = 1,               //TODO pasar la cotizacion correcta
                MonId      = "PES",           //TODO pasar la moneda correcta
                Opcionales = null,
                Tributos   = comprobante.Tributos > 0 ? comprobante.FETributos().ToArray() : null,
            };

            var feDetReq = new List <FECAEDetRequest> ();
            feDetReq.Add(fEDetRequest);

            var solicitud = new  FECAERequest {
                FeCabReq = feCabReq,
                FeDetReq = feDetReq.ToArray()
            };

            FECAEResponse fECAEResponse = service.FECAESolicitar(ta, solicitud);

            if (fECAEResponse.Events != null)
            {
                foreach (var evento in fECAEResponse.Events)
                {
                    string mensaje = string.Format("Código: {0}. Mensaje: {1}", evento.Code, evento.Msg);
                    callback.CallBack.OnMessage("Evento AFIP", mensaje);
                }
            }

            if (fECAEResponse.Errors != null)
            {
                var errores = new StringBuilder();
                foreach (var error in fECAEResponse.Errors)
                {
                    errores.AppendFormat("Código: {0}. Mensaje: {1}", error.Code, error.Msg);
                    errores.AppendLine();
                }
                throw new AFIPException(errores.ToString());
            }

            //TODO refactorizar para soportar un lote de comprobantes

            var observaciones = new StringBuilder();
            if (fECAEResponse.FeDetResp [0].Observaciones != null)
            {
                foreach (var observacion in fECAEResponse.FeDetResp[0].Observaciones)
                {
                    observaciones.AppendFormat("Código: {0}. Mensaje: {1}", observacion.Code, observacion.Msg);
                    observaciones.AppendLine();
                }

                callback.CallBack.OnWarning("Comprobante con observaciones", observaciones.ToString());
            }

            if (fECAEResponse.FeDetResp [0].Resultado == "R")
            {
                string errorAfip = string.Format("Comprobante rechazado.\n{0}", observaciones);
                throw new AFIPException(errorAfip);
            }

            //TODO ver si el formato seria correcto
            comprobante.Tipo.UltimoNumero = numero;
            comprobante.NumeroAFIP        = string.Format("{0:0000}-{1:00000000}", punto_de_venta, numero);
            comprobante.Numero            = comprobante.NumeroAFIP;
            comprobante.CAE             = fECAEResponse.FeDetResp [0].CAE;
            comprobante.VencimientoCAE  = fECAEResponse.FeDetResp [0].CAEFchVto;
            comprobante.ComentariosAFIP = observaciones.ToString();
        }