public JsonResult Create(ComprobanteCreateViewModel model)
        {
            try {
                if (String.IsNullOrEmpty(model.LugarExpedicion))
                    throw new ApplicationException("¡Ingrese el lugar de expedición!");
                else if (string.IsNullOrEmpty(model.TipoDeComprobante))
                    throw new ApplicationException("¡Ingrese el tipo de comprobante!");
                else if (model.EmisorId <= 0)
                    throw new ApplicationException("¡Ingrese el emisor!");
                else if (model.ReceptorId <= 0)
                    throw new ApplicationException("¡Ingrese el receptor!");
                else if (model.CertificadoId <= 0)
                    throw new ApplicationException("¡Ingrese el certificado!");
                else if (String.IsNullOrEmpty(model.FormaDePago))
                    throw new ApplicationException("¡Ingrese la forma de pago!");
                else if (String.IsNullOrEmpty(model.MetodoDePago))
                    throw new ApplicationException("¡Ingrese el método de pago!");
                else if ((model.MetodoDePago != "EFECTIVO" && model.MetodoDePago != "NO IDENTIFICADO") && (model.NumCtaPago == null || (model.NumCtaPago.Count() > 6 || model.NumCtaPago.Count() < 4)))
                    throw new ApplicationException("¡El valor de NumCtaPago debe contener entre 4 hasta 6 caracteres!");
                else if ((model.MetodoDePago != "EFECTIVO" && model.MetodoDePago != "NO IDENTIFICADO") && (string.IsNullOrEmpty(model.Banco)))
                    throw new ApplicationException("¡Ingrese el banco!");
                else if ((model.Conceptos != null || model.Conceptos.Count > 0)
                    && model.Conceptos.All(x => x.Cantidad < 0m || x.Unidad == null || x.Descripcion == null || x.ValorUnitario < 0m))
                    throw new ApplicationException("¡Ingrese al menos un concepto!");
                else if (model.SubTotal < 0m)
                    throw new ApplicationException("¡SubTotal no válido!");
                else if (model.TotalImpuestosTrasladados < 0m)
                    throw new ApplicationException("¡Total Impuestos Trasladados no válido!");
                else if (model.TotalImpuestosRetenidos < 0m)
                    throw new ApplicationException("¡Total Impuestos Retenidos no válido!");
                else if (model.Total < 0m)
                    throw new ApplicationException("¡Total no válido!");
                else {

                    var comprobante = new Comprobante();

                    Emisor emisor = DBContext.Emisores.Find(model.EmisorId);

                    ComprobanteEmisor comprobanteEmisor = null;

                    if (model.ExpedidoEn != null && model.ExpedidoEn.UbicacionId != null) {
                        comprobanteEmisor = DBContext.ComprobantesEmisores.Where(e => e.EmisorId == emisor.EmisorId && e.DomicilioFiscalId == emisor.DomicilioFiscalId && e.ExpedidoEnId == model.ExpedidoEn.UbicacionId).SingleOrDefault();
                    }
                    //else if () {
                    //}
                    else {
                        // crear o seleccionar la ubicación y agregarla
                        //comprobanteEmisor = DBContext.ComprobantesEmisores.Where(e => e.EmisorId == model.EmisorId && e.DomicilioFiscalId == model.DomicilioFiscalId && e.ExpedidoEnId == model.ExpedidoEnId);
                        comprobanteEmisor = DBContext.ComprobantesEmisores.Where(e => e.EmisorId == emisor.EmisorId && e.DomicilioFiscalId == emisor.DomicilioFiscalId && e.ExpedidoEnId == model.ExpedidoEn.UbicacionId).SingleOrDefault();
                    }

                    // Crear uno nuevo
                    if (comprobanteEmisor == null) {
                        comprobanteEmisor = new ComprobanteEmisor {
                            Emisor = emisor,
                            //EmisorId = emisor.EmisorId,
                            DomicilioFiscal = emisor.DomicilioFiscal
                            //,DomicilioId = receptor.DomicilioId
                            // TODO:
                            //RegimenFiscal = emisor.RegimenFiscal
                        };

                    }

                    comprobante.Emisor = comprobanteEmisor;

                    //comprobante.EmisorId = model.EmisorId;
                    //comprobante.Emisor = DBContext.Emisores.Find(model.EmisorId); // .Where(e => e.PublicKey == publicKey).SingleOrDefault();
                    //if (model.Emisor. .ExpedidoEnId != null) {
                    //    comprobante.Emisor = DBContext.ComprobantesEmisores.Where(e => e.EmisorId == model.EmisorId && e.DomicilioFiscalId == model.DomicilioFiscalId && e.ExpedidoEnId == model.ExpedidoEnId);
                    //}
                    //else {
                    //    comprobante.Emisor = DBContext.ComprobantesEmisores.Where(e => e.EmisorId == model.EmisorId && e.DomicilioFiscalId == model.DomicilioFiscalId && e.ExpedidoEnId == model.ExpedidoEnId);
                    //}

                    Receptor receptor = DBContext.Receptores.Find(model.ReceptorId);

                    ComprobanteReceptor comprobanteReceptor = DBContext.ComprobantesReceptores.Where(r => r.ReceptorId == receptor.ReceptorId && r.DomicilioId == receptor.DomicilioId).SingleOrDefault();

                    // Crear uno nuevo
                    if (comprobanteReceptor == null) {
                        comprobanteReceptor = new ComprobanteReceptor {
                            Receptor = receptor,
                            //ReceptorId = receptor.ReceptorId,
                            Domicilio = receptor.Domicilio
                            //,DomicilioId = receptor.DomicilioId
                        };
                    }

                    //comprobante.ReceptorId = model.ReceptorId;
                    //comprobante.Receptor = DBContext.Receptores.Find(model.ReceptorId); // .Where(e => e.PublicKey == publicKey).SingleOrDefault();
                    comprobante.Receptor = comprobanteReceptor;
                    comprobante.Serie = model.Serie;
                    comprobante.Folio = model.Folio;
                    comprobante.Fecha = DateTime.Now + SATManager.GetCFDIServiceTimeSpan();
                    comprobante.FormaDePago = model.FormaDePago;
                    comprobante.SubTotal = model.SubTotal;
                    comprobante.Total = model.Total;

                    //comprobante.NoCertificado;
                    //comprobante.Certificado;
                    comprobante.TipoDeComprobante = model.TipoDeComprobante;

                    comprobante.ExtendedIntValue1 = model.OrdenNumero;
                    comprobante.ExtendedIntValue2 = model.CteNumero;
                    comprobante.ExtendedStringValue2 = model.Notas;

                    comprobante.ViewTemplateId = model.TemplateId;

                    comprobante.FormaDePago = model.FormaDePago;
                    comprobante.MetodoDePago = model.MetodoDePago;
                    comprobante.LugarExpedicion = model.LugarExpedicion;
                    comprobante.TipoCambio = model.TipoCambio;
                    comprobante.Moneda = model.Moneda;
                    comprobante.NumCtaPago = model.NumCtaPago;
                    comprobante.ExtendedStringValue1 = model.Banco;
                    comprobante.Moneda = model.Moneda;

                    comprobante.Conceptos = new List<Concepto>();

                    foreach (var modelConcepto in model.Conceptos) {
                        if (!string.IsNullOrEmpty(modelConcepto.Descripcion)) {
                            comprobante.Conceptos.Add(new Concepto {
                                Cantidad = modelConcepto.Cantidad,
                                Unidad = modelConcepto.Unidad,
                                NoIdentificacion = modelConcepto.NoIdentificacion,
                                Descripcion = modelConcepto.Descripcion,
                                ValorUnitario = modelConcepto.ValorUnitario,
                                Importe = modelConcepto.Importe,
                                PublicKey = Guid.NewGuid(),
                                Ordinal = modelConcepto.Ordinal
                            });
                        }
                    }

                    comprobante.Impuestos = new Impuestos();
                    comprobante.Impuestos.Traslados = new List<Traslado>();

                    foreach (var modelTraslado in model.Traslados) {
                        if (modelTraslado.Tasa > 0 && modelTraslado.Importe > 0) {
                            comprobante.Impuestos.Traslados.Add(new Traslado {
                                Importe = modelTraslado.Importe,
                                Impuesto = modelTraslado.Impuesto,
                                Tasa = modelTraslado.Tasa,
                            });
                        }
                    }

                    comprobante.Impuestos.Retenciones = new List<Retencion>();
                    foreach (var modelRetencion in model.Retenciones) {
                        if (modelRetencion.Importe > 0) {
                            comprobante.Impuestos.Retenciones.Add(new Retencion {
                                Importe = modelRetencion.Importe,
                                Impuesto = modelRetencion.Impuesto,
                            });
                        }
                    }

                    if (model.TotalImpuestosRetenidos > 0)
                        comprobante.Impuestos.TotalImpuestosRetenidos = model.TotalImpuestosRetenidos;

                    if (model.TotalImpuestosTrasladados > 0)
                        comprobante.Impuestos.TotalImpuestosTrasladados = model.TotalImpuestosTrasladados;

                    comprobante.PublicKey = Guid.NewGuid();

                    Certificado certificado = DBContext.Certificados.Find(model.CertificadoId);

                    if (certificado != null) {
                        // comprobante.NoCertificado = certificado.NumSerie;
                        // comprobante.Certificado = certificado.CertificadoBase64;
                        comprobante.CertificadoId = certificado.CertificadoId;
                        comprobante.Certificado = certificado;
                        comprobante.HasNoCertificado = true;
                        comprobante.HasCertificado = true;
                    }

                    string cadenaOriginal = comprobante.GetCadenaOriginal();
                    comprobante.Sello = certificado.GetSello(cadenaOriginal);
                    //comprobante.Status = "P";
                    DBContext.Comprobantes.Add(comprobante);
                    DBContext.SaveChanges();

                    TempData["success"] = "Se ha creado el comprobante correctamente";
                    var data = new {
                        error = false,
                        errorMsg = "",
                        comprobanteId = comprobante.PublicKey
                    };
                    return Json(data);
                }
            }
            catch (System.Data.Entity.Validation.DbEntityValidationException dex) {
                string errorTxt = dex.Message.ToString();

                foreach (var valError in dex.EntityValidationErrors)
                {
                    foreach (var error in valError.ValidationErrors)
                    {
                        errorTxt = errorTxt + Environment.NewLine + error.ErrorMessage;
                    }
                }

                var data = new {
                    error = true,
                    errorMsg = errorTxt

                };

                return Json(data);
            }
            catch (Exception ex) {

                string errorTxt = ex.Message.ToString();

                foreach (ModelState modelState in ViewData.ModelState.Values)
                {
                    foreach (ModelError error in modelState.Errors)
                    {
                        errorTxt = errorTxt + Environment.NewLine + error.ErrorMessage;
                    }
                }

                var data = new {
                    error = true,
                    errorMsg = errorTxt

                };

                return Json(data);
            }
        }
        public ComprobanteEmisorDetailViewModel(ComprobanteEmisor emisor)
        {
            if (emisor == null)
                throw new ArgumentNullException("emisor");

            this.PublicKey = emisor.PublicKey;

            this.RFC = emisor.RFC;
            this.Nombre = emisor.Nombre;
            if (emisor.RegimenFiscal != null && emisor.RegimenFiscal.Count > 0)
                this.RegimenFiscal = emisor.RegimenFiscal[0].Regimen;

            if (emisor.DomicilioFiscal != null) {
                this.Calle = emisor.DomicilioFiscal.Calle;
                this.NoExterior = emisor.DomicilioFiscal.NoExterior;
                this.NoInterior = emisor.DomicilioFiscal.NoInterior;
                this.Colonia = emisor.DomicilioFiscal.Colonia;
                this.Localidad = emisor.DomicilioFiscal.Localidad;
                this.Municipio = emisor.DomicilioFiscal.Municipio;
                this.Estado = emisor.DomicilioFiscal.Estado;
                this.Pais = emisor.DomicilioFiscal.Pais;
                this.CodigoPostal = emisor.DomicilioFiscal.CodigoPostal;
                this.Referencia = emisor.DomicilioFiscal.Referencia;
            }
            //this.RegimenFiscal = emisor.RegimenFiscal;

            //  this.EmisorLogoUrl = comprobante.Emisor.LogoUrl;
            //this.EmisorTelefono = comprobante.Emisor.Telefono;
            //this.EmisorCorreo = comprobante.Emisor.Correo;
            //this.EmisorCifUrl = comprobante.Emisor.CifUrl;

            this.Correo = emisor.Correo;
            this.Telefono = emisor.Telefono;
            this.CifUrl = emisor.CifUrl;
            this.LogoUrl = emisor.LogoUrl;

            this.ViewTemplateId = emisor.ViewTemplateId;
        }