Me podrían ayudar, tomé los códigos que han compartido en el foro para adaptarlos a la versión de halcón divino pero solo eh obtenido el siguiente mensaje:
" Error no se pudo obtener la cadena original. Utilice CFDProbarOpenSSL para verificar el funcionaiento de la libreria OpenSSL"
anexo los códigos de programación y adjunte el XML que está creando, si tiene oportunidad de apoyarme :-) Agradezco su apoyo!
--------------------------------------------------------------------Parte 1.
--------------------------------------------------------------------------------------------------------------------Parte 2.
#DEFINE CRLF CHR(13)+CHR(10)
#DEFINE True .T.
#DEFINE False .F.
*-- CFDInit (Procedure)
* Crea el objeto public CFDConf, el cual contiene
* configuraciones generales de uso en varios de
* los metodos y funciones de la libreria
*
* VES Dic 30, 2011
* Se aprovecha para declarar algunas enumeraciones de
* uso en la clase
*
PROCEDURE CFDInit
*
PUBLIC CFDVersions,CFDConf
CFDVersions = CREATE("CFDVersionsEnum")
CFDConf = CREATE("CFDConf")
DECLARE Sleep IN kernel32 INTEGER dwMilliseconds
DECLARE INTEGER GetShortPathName IN kernel32;
STRING lpszLongPath,;
STRING @ lpszShortPath,;
INTEGER cchBuffer
DECLARE INTEGER GenerateFile ;
IN BarCodeLibrary.dll;
STRING cData, ;
STRING cFileName
*
ENDPROC
*-- CFDVersionsEnum (Enumeracion)
* Lista de valores validos para Version
*
DEFINE CLASS CFDVersionsEnum AS Custom
*
CFD_20 = 2
CFD_22 = 22
CFDi_30 = 3
CFDi_32 = 32
CFDi_33 = 33 && Versión 3.3 ByVigar.
validVersionList = "[2][22][3][32][33]"
PROCEDURE ToString(pnVersion)
DO CASE
CASE pnVersion = THIS.CFD_20
RETURN "2.0"
CASE pnVersion = THIS.CFD_22
RETURN "2.2"
CASE pnVersion = THIS.CFDi_30
RETURN "3.0"
CASE pnVersion = THIS.CFDi_32
RETURN "3.2"
CASE pnVersion = THIS.CFDi_33 && Versión 3.3 ByVigar.
RETURN "3.3"
OTHERWISE
RETURN ""
ENDCASE
ENDPROC
PROCEDURE FromString(pcVersion)
DO CASE
CASE pcVersion = "2.0"
RETURN THIS.CFD_20
CASE pcVersion = "2.2"
RETURN THIS.CFD_22
CASE pcVersion = "3.0"
RETURN THIS.CFDi_30
CASE pcVersion = "3.2"
RETURN THIS.CFDi_32
CASE pcVersion = "3.3"
RETURN THIS.CFDi_33 && Versión 3.3 ByVigar.
OTHERWISE
RETURN 0
ENDCASE
ENDPROC
PROCEDURE ToLongString(pcVersion)
DO CASE
CASE pcVersion = THIS.CFD_20
RETURN "CFD 2.0"
CASE pcVersion = THIS.CFD_22
RETURN "CFD 2.2"
CASE pcVersion = THIS.CFDi_30
RETURN "CFDi 3.0"
CASE pcVersion = THIS.CFDi_32
RETURN "CFDi 3.2"
CASE pcVersion = THIS.CFDi_33 && Versión 3.3 ByVigar.
RETURN "CFDi 3.3"
OTHERWISE
RETURN "Valor incorrecto (" + pcVersion + ")"
ENDCASE
ENDPROC
PROCEDURE Validate(vNewVal, puCurValue)
*
LOCAL uValue
IF VARTYPE(m.vNewVal)="N"
m.vNEwVal = CFDVersions.ToString(m.vNewVal)
ENDIF
uValue = CFDVersions.FromString(m.vNewVal)
IF EMPTY(uValue)
uValue = puCurValue
MESSAGEBOX("El valor de version indicado no es correcto.",16,"CFD")
ENDIF
RETURN uValue
*
ENDPROC
*
ENDDEFINE
*-- CFDConf (Clase)
* Configuraciones generales de uso en la libreria
*
DEFINE CLASS CFDConf AS Custom
*
Version = "3.7"
OpenSSL = ""
SMTPServer = ""
SMTPPort = ""
SMTPUseSSL = .T.
SMTPAuthenticate = .T.
SMTPUserName = ""
SMTPPassword = ""
MailSender = ""
UltimoError = ""
modoPruebas = .F.
metodoDigest = "md5"
ubicacionRepositorio = ".\CFD"
ultimoCertificado = NULL
formatoImpresion = "CFD.FRX"
XMLVersion = 0
incluirBOM = .F.
NTOCMoneda = "Pesos"
NTOCPrefijo = ""
nTOCSufijo = "M.N."
usarPrint2PDF = .T.
PROCEDURE Init
THIS.Version = CFDVersions.CFDi_33
THIS.OpenSSL = ADDBS(FULLPATH(".\SSL"))
THIS.XMLVersion = CFDVersions.CFDi_33
ENDPROC
PROCEDURE Version_Assign(vNEwVal)
ENDPROC
PROCEDURE XMLVersion_Assign(vNewVal)
THIS.XMLVersion = CFDVersions.Validate(m.vNewVal, THIS.XMLVersion)
ENDPROC
*
ENDDEFINE
*-- CFDComprobante (Clase)
* Representa a un comprobante digital
*
DEFINE CLASS CFDComprobante AS Custom
*
*-- Atributos requeridos
*
* ARC Dic 20, 2011: Se agregan las nuevas versiones
*
Version = "" && VES Dic 30, 2011: Se elimino el valor por omision para establecerlo en el constructor
Folio = 0
Fecha = {}
Sello = ""
FormaPago = "" && Versión 3.3 ByVigar. se cambio de formadePago a FormaPago
noAprobacion = 0
anoAprobacion = 0
NoCertificado = "" && Versión 3.3 ByVigar.
SubTotal = 0.00
Total = 0.00
TipoDeComprobante = "" && Se sustituye tipoDeComprobante por TipoDeComprobante Requerido en v.3.3 ByVigar.
Emisor = NULL
Receptor = NULL
Conceptos = NULL
formaDePago = "Pago en una sola exhibición"
*-- Atributos opcionales
Serie = ""
Certificado = ""
CondicionesDePago = ""
Descuento = 0.00
motivoDescuento = ""
Impuestos = NULL
Addenda = NULL
CfdiRelacionados = NULL && Pagos UUDI Relacionados v.3.3 ByVigar
*-- Atributos CFD 2.2 y CFDI 3.2 opcionales
MontoFolioFiscalOrig = NULL
FechaFolioFiscalOrig = {}
SerieFolioFiscalOrig = NULL
FolioFiscalOrig = NULL
NumCtaPago = NULL
Moneda = NULL
TipoCambio = NULL
*-- Atributos CFD 2.2 y CFDI 3.2 requeridos
LugarExpedicion = NULL
*metodoDePago = "" && ARC Dic 20, 2011: es requerido en CFD 2.2 y CFDI 3.2
MetodoPago = "" && ARC Dic 20, 2011: es requerido en CFD 2.2 y CFDI 3.2
*-- Propiedades
cadenaOriginal = "" && Solo-lectura
ubicacionOpenSSL = ".\SSL"
*-- Getters / Setters
PROCEDURE cadenaOriginal_Access
RETURN THIS._genCadenaOriginal()
ENDPROC
PROCEDURE cadenaOriginal_Assign(vNewVal)
ENDPROC
*-- Constructor de la clase
*
* VES Dic 30, 2011: Se incluyo el parametro opcional pnVersion
*
PROCEDURE Init(pnVersion)
*
IF PCOUNT() = 0 && Si no se indico una version, se asume la version indicada en CFDConf.XMLVersion
pnVersion = CFDConf.XMLVersion
ENDIF
THIS.Version = pnVersion
THIS.Emisor = CREATEOBJECT("CFDPersona")
THIS.Receptor = CREATEOBJECT("CFDPersona")
THIS.CfdiRelacionados = CREATEOBJECT("CfdiRelacionados")
THIS.Conceptos = CREATEOBJECT("CFDConceptos")
THIS.Impuestos = CREATEOBJECT("CFDImpuestos")
THIS.ubicacionOpenSSL = CFDConf.OpenSSL
*
ENDPROC
*-- Setter para propiedad Version
*
PROCEDURE Version_Assign(vNewVal)
LOCAL nVersion
nVersion = CFDVersions.Validate(m.vNewVal, 0)
IF nVersion > 0
THIS.Version = CFDVersions.ToString(nVersion)
ENDIF
ENDPROC
*-- Metodos
*-- _genCadenaOriginal (Metodo)
* Genera la cadena original que sirve de base para generar el sello digital. El codigo original
* pertenece al amigo Halcon Divino, y fue adaptado para el uso dentro de esta clase.
*
* VES Ene 4, 2011
* Se cambio el codigo para obtener la cadena original directametne del XML aplicando el archivo
* XSLT proporcionado por el SAT. De esta forma nos garantizamos que no haya diferencia entre
* la cadena original generada por la clase y la que genera el SAT a partir del XML, lo cual
* elimina los problemas de sellado por diferencia en la cadena original.
*
PROCEDURE _genCadenaOriginal()
*
LOCAL cTempFile
cTempFile = GetTempFile("XML")
THIS.CrearXML(cTempFile)
LOCAL cStr
cStr = CFDExtraerCadenaOriginal(cTempFile)
ERASE (cTempFile)
RETURN cStr
*
ENDPROC
*-- _fixStr (Metodo)
* Recibe una cadena y realiza los siguientes cambios:
* a) Sustituye cualquier caracter invalido por el caracter "."
* b) Elimina los espacios en blanco al inicio y al final de la cadena
* c) Elimina cualquier secuencia de espacios en blanco repetidos dentro de la cadena
* d) Si la cadena resultante contiene al menos 1 caracter, se le anade la cadena
* indicada en el parametro pcSep
*
* La funcion fue reeacrita a partir de la funcion QtarChrInval() de Halcon Divino, a fin
* de simplificar el codigo y depurarlo. El metodo utilizado por Halcon Divino para incluir
* cada elemento en la cadena original implicaba una doble llamada a QtarChrInval() para
* cada valor en la cadena:
*
* cStr = cStr + Iif(Len(QtarChrInval(valor)) = 0, "" ,QtarChrInval(valor) + "|")
*
* Este codigo se simplifica y mejora haciendo una sola invocacion a fixStr:
*
* cStr = cStr + THIS._fixStr(valor, "|")
*
* Adicionalmente se incluyo codigo para permitir que la funcion reciba cualquier tipo
* de datos, haciendo la conversion adecuada segun el tipo. En los casos donde el parametro
* de entraada no sea un string, no se realiza la verificacion de caracteres invalidos
*
HIDDEN PROCEDURE _fixStr(puValue, pcSep)
*
IF PCOUNT() = 1
pcSep = ""
ENDIF
LOCAL cType
cType = VARTYPE(puValue)
DO CASE
CASE cType = "N"
IF EMPTY(puValue)
RETURN ""
ENDIF
RETURN ALLT(STR(puValue,15,2)) + pcSep
CASE cType = "D"
IF EMPTY(puValue)
RETURN ""
ENDIF
RETURN STR(YEAR(puValue),4) + "-" + PADL(MONTH(puValue),2,"0") + "-" + PADL(DAY(puValue),2,"0") + pcSEP
CASE cType = "T"
IF EMPTY(puValue)
RETURN ""
ENDIF
RETURN STR(YEAR(puValue),4) + "-" + PADL(MONTH(puValue),2,"0") + "-" + PADL(DAY(puValue),2,"0") + "T" + ;
PADL(HOUR(puValue),2,"0") + ":" + PADL(MINUTE(puValue),2,"0") + ":" + PADL(SEC(puValue),2,"0") + pcSEP
CASE cType = "X" && Valor NULL
RETURN ""
ENDCASE
LOCAL cFixed
cFixed = ALLTRIM(puValue)
cFixed = STRT(STRT(STRT(STRT(STRT(cFixed,[&],[&]),[<],[<]),[>],[>]),["],["]),['],['])
cFixed = STRT(cFixed, CHR(13)+CHR(10), "")
DO WHILE AT(SPACE(2), cFixed) <> 0
cFixed = STRTRAN(cFixed,SPACE(2),SPACE(1))
ENDDO
IF LEN(cFixed) > 0 AND !EMPTY(pcSep)
cFixed = cFixed + pcSep
ENDIF
RETURN cFixed
*
ENDPROC
*-- Sellar (Metodo)
* Genera el sello digital del comprobante y actualiza los atributos apropiados
*
PROCEDURE Sellar(pcArchivoKey, pcPassword)
*
CFDConf.ultimoError = ""
*-- Si la fecha del comprobante es igual o posterior al 1-1-2011, se cambia
* el metodo MD5 por SHA-256
*
LOCAL cMetodo
cMetodo = "md5"
IF YEAR(THIS.fecha) > 2010
cMetodo = "sha256"
ENDIF
CFDConf.metodoDigest = cMetodo
*-- Se obtiene la cadena original
*
LOCAL cCadenaOriginal
cCadenaOriginal = THIS.cadenaOriginal
IF EMPTY(cCadenaOriginal)
CFDConf.ultimoError = "No se pudo obtener la cadena original. Utilize CFDProbarOpenSSL() para verificar el funcionamiento de la libreria OpenSSL"
RETURN .F.
ENDIF
*-- Se genera el sello para la cadena original
*
THIS.Sello = CFDGenerarSello(cCadenaOriginal, pcArchivoKey, pcPassword, cMetodo, THIS.ubicacionOpenSSL)
RETURN !EMPTY(THIS.Sello)
*
ENDPROC
*-- leerCertificado
* Lee el archivo de certificado indicado y actualiza
* los atributos apropiados
*
* VES Ene 4, 2011
* Se utiliza la propiedad CFDConf.ultimoCertificado como
* un "cache" para evitar leer innecesariamente el mismo
* certificado varias veces seguidas
*
PROCEDURE leerCertificado(pcArchivoCER)
*
*-- Se lee el certificado (solo si es necesario)
LOCAL oCert
IF ISNULL(CFDConf.ultimoCertificado) OR CFDConf.ultimoCertificado.Archivo <> LOWER(pcArchivoCER)
oCert = CFDLeerCertificado(pcArchivoCER)
IF ISNULL(oCert)
RETURN NULL
ENDIF
CFDConf.ultimoCertificado = oCert
ELSE
oCert = CFDConf.ultimoCertificado
*?"Cached!"
ENDIF
IF oCert.Valido AND (oCert.Vigente OR CFDConf.modoPruebas)
THIS.Certificado = oCert.Certificado
THIS.noCertificado = oCert.Serial
ENDIF
RETURN oCert
*
ENDPROC
*-- CrearXML (Metodo)
* Crea el archivo XML que representa el comprobante
*
PROCEDURE CrearXML(pcArchivo, plValidar, pcArchivoKey, pcPassword, pcMetodo)
*
#DEFINE CFD_OPCIONAL .T.
CFDConf.ultimoError = ""
*!* EXIT &&Agregado para debugear por errores
LOCAL oParser,nVersion
oParser = CREATEOBJECT("XmlParser")
nVersion = CFDVersions.fromString(THIS.Version)
WITH oParser
*
.indentString = ""
.New()
*-- Nodo "Comprobante"
.XML.addNode("Comprobante")
IF INLIST(nVersion, CFDVersions.CFDi_32, CFDVersions.CFDi_33) && Versión 3.3 ByVigar.
.XML._Comprobante.NameSpace = "cfdi" && Al anadir el NS "Cfdi" al nodo comprobante, todos los subnodos lo heredaran automaticamente
ENDIF
WITH .XML._Comprobante
DO CASE
CASE nVersion = CFDVersions.CFD_20
CASE nVersion = CFDVersions.CFDi_30
CASE nVersion = CFDVersions.CFD_22
CASE nVersion = CFDVersions.CFDi_32
CASE nVersion = CFDVersions.CFDi_33 && Versión 3.3 ByVigar.
IF THIS.TipoDeComprobante='P'
ENDIF
ENDCASE
.addProp("Version",THIS._fixStr(THIS.version))
.addProp("Serie",THIS._fixStr(THIS.serie),CFD_OPCIONAL)
.addProp("Folio",THIS._fixStr(STR(THIS.folio,10,0)))
.addProp("Fecha",THIS._fixStr(THIS.fecha))
IF INLIST(nVersion, CFDVersions.CFD_20, CFDVersions.CFD_22)
.addProp("noAprobacion",THIS._fixStr(STR(THIS.noAprobacion,10,0)))
.addProp("anoAprobacion",THIS._fixStr(STR(THIS.anoAprobacion,10,0)))
ENDIF
IF INLIST(nVersion, CFDVersions.CFD_22, CFDVersions.CFDi_30, CFDVErsions.CFDi_32)
.addProp("Moneda",THIS._fixStr(THIS.moneda),CFD_OPCIONAL)
.addProp("TipoCambio",THIS._fixStr(THIS.tipocambio),CFD_OPCIONAL)
ENDIF
IF INLIST(nVersion, CFDVersions.CFDi_33)
.addProp("MontoFolioFiscalOrig",THIS._fixStr(THIS.MontoFolioFiscalOrig),CFD_OPCIONAL)
.addProp("FechaFolioFiscalOrig",THIS._fixStr(THIS.FechaFolioFiscalOrig),CFD_OPCIONAL)
.addProp("SerieFolioFiscalOrig",THIS._fixStr(THIS.SerieFolioFiscalOrig),CFD_OPCIONAL)
.addProp("FolioFiscalOrig",THIS._fixStr(THIS.FolioFiscalOrig),CFD_OPCIONAL)
.addProp("NumCtaPago",THIS._fixStr(THIS.NumCtaPago),CFD_OPCIONAL)
.addProp("LugarExpedicion",THIS._fixStr(THIS.LugarExpedicion))
ENDIF
.addProp("MetodoPago",THIS._fixStr(THIS.MetodoPago),CFD_OPCIONAL)
IF THIS.TipoDeComprobante='I' && Versión 3.3 ByVigar. no para tipo 'P' Pago10
.addProp("FormaPago",THIS._fixStr(THIS.FormaPago)) && Versión 3.3 ByVigar.
ENDIF
.addProp("FormaDePago",THIS._fixStr(THIS.formaDePago))
*.addProp("",THIS._fixStr(THIS.))
.addProp("CondicionesDePago",THIS._fixStr(THIS.CondicionesDePago),CFD_OPCIONAL)
IF THIS.TipoDeComprobante='I' && ByVigar v.3.3
.addProp("SubTotal",THIS._fixStr(STR(THIS.SubTotal,15,2)))
ELSE
.addProp("SubTotal",THIS._fixStr('0'))
ENDIF
* IF m.imp_dscnt <> 0 && No debe de aparecer si es 0 V.3.3 ByVigar
IF DescuentoF <> 0 && No debe de aparecer si es 0 V.3.3 ByVigar
.addProp("Descuento",THIS._fixStr(TRANSFORM(THIS.Descuento,"@Z 999999999999.99")))
.addProp("motivoDescuento",THIS._fixStr(THIS.motivoDescuento),CFD_OPCIONAL)
ENDIF
IF THIS.TipoDeComprobante='I' && ByVigar v.3.3
.addProp("Total",THIS._fixStr(STR(THIS.Total,15,2)))
ELSE
.addProp("Total",THIS._fixStr('0'))
ENDIF
.addProp("TipoDeComprobante",THIS._fixStr(THIS.TipoDeComprobante))
.addProp("NoCertificado",THIS.noCertificado)
.addProp("Certificado",THIS.Certificado) && Versión 3.3 ByVigar.
.addProp("Sello",THIS.sello)
ENDWITH
*-- Nodo "Emisor"
.XML._Comprobante.addNode("Emisor")
WITH .XML._Comprobante._Emisor
.addProp("Rfc",CHRT(THIS._fixStr(THIS.Emisor.Rfc),".- ","")) && VES Nov 16, 2011
.addProp("RegimenFiscal",THIS._fixStr(THIS.Emisor.RegimenFiscal)) && ByVigar v.3.3 16/09/2017
IF INLIST(nVersion, CFDVersions.CFD_20, CFDVersions.CFDi_30) && ARC Ene 03, 2012: Nombre de Emisor opcional en 2.2 y 3.2
.addProp("Nombre",THIS._fixStr(THIS.Emisor.Nombre))
ELSE
IF NOT EMPTY(THIS.Emisor.Nombre)
.addProp("Nombre",THIS._fixStr(THIS.Emisor.Nombre))
ENDIF
ENDIF
IF NOT EMPTY(THIS.Emisor.domicilioFiscal.Pais) && ARC Dic 27, 2011: domiciolio del emisor es opcional en 2.2 y 3.2
.addNode("DomicilioFiscal")
WITH ._DomicilioFiscal
.addProp("calle",THIS._fixStr(THIS.Emisor.DomicilioFiscal.Calle))
.addProp("noExterior",THIS._fixStr(THIS.Emisor.DomicilioFiscal.noExterior),CFD_OPCIONAL)
.addProp("noInterior",THIS._fixStr(THIS.Emisor.DomicilioFiscal.noInterior),CFD_OPCIONAL)
.addProp("colonia",THIS._fixStr(THIS.Emisor.DomicilioFiscal.colonia),CFD_OPCIONAL)
.addProp("localidad",THIS._fixStr(THIS.Emisor.DomicilioFiscal.localidad),CFD_OPCIONAL)
.addProp("referencia",THIS._fixStr(THIS.Emisor.DomicilioFiscal.referencia),CFD_OPCIONAL)
.addProp("municipio",THIS._fixStr(THIS.Emisor.DomicilioFiscal.municipio))
.addProp("estado",THIS._fixStr(THIS.Emisor.DomicilioFiscal.estado))
.addProp("pais",THIS._fixStr(THIS.Emisor.DomicilioFiscal.pais))
.addProp("CodigoPostal",THIS._fixStr(THIS.Emisor.DomicilioFiscal.CodigoPostal))
ENDWITH
ENDIF
IF NOT EMPTY(THIS.Emisor.ExpedidoEn.Pais) && ARC Dic 27, 2011: Ya que Pais es el unico atributo requerido
.addNode("ExpedidoEn")
WITH ._ExpedidoEn
*!* .addProp("calle",THIS._fixStr(THIS.Emisor.ExpedidoEn.Calle))
*!* .addProp("noExterior",THIS._fixStr(THIS.Emisor.ExpedidoEn.noExterior),CFD_OPCIONAL)
*!* .addProp("noInterior",THIS._fixStr(THIS.Emisor.ExpedidoEn.noInterior),CFD_OPCIONAL)
*!* .addProp("colonia",THIS._fixStr(THIS.Emisor.ExpedidoEn.colonia),CFD_OPCIONAL)
*!* .addProp("localidad",THIS._fixStr(THIS.Emisor.ExpedidoEn.localidad),CFD_OPCIONAL)
*!* .addProp("referencia",THIS._fixStr(THIS.Emisor.ExpedidoEn.referencia),CFD_OPCIONAL)
*!* .addProp("municipio",THIS._fixStr(THIS.Emisor.ExpedidoEn.municipio))
*!* .addProp("estado",THIS._fixStr(THIS.Emisor.ExpedidoEn.estado))
*!* .addProp("pais",THIS._fixStr(THIS.Emisor.ExpedidoEn.pais))
.addProp("CodigoPostal",THIS._fixStr(THIS.Emisor.ExpedidoEn.CodigoPostal))
ENDWITH
ENDIF
*!* IF INLIST(nVersion, CFDVersions.CFDi_33) && Se integra como propiedad del Emisor.RegimenFiscal v.3.3 ByVigar
*!* LOCAL nRegimen,oRegimen,oNodoRegimen && VES Ene 12, 2012
*!* FOR nRegimen = 1 TO THIS.Emisor.RegimenFiscal.Count
*!* oRegimen = THIS.Emisor.RegimenFiscal.Items[nRegimen]
*!* oNodoRegimen = .addNode("RegimenFiscal")
*!* oNodoRegimen.addProp("RegimenFiscal",THIS._fixStr(oRegimen.RegimenFiscal))
*!* ENDFOR
*!* ENDIF
ENDWITH
*-- Nodo "Receptor"
.XML._Comprobante.addNode("Receptor")
WITH .XML._Comprobante._Receptor
.addProp("Rfc",CHRT(THIS._fixStr(THIS.Receptor.Rfc),".- ","")) && VES Nov 16, 2011
.addProp("UsoCFDI",THIS._fixStr(THIS.Receptor.UsoCFDI)) && v.3.3 ByVigar.
IF NOT EMPTY(THIS.Receptor.Nombre) && ARC Ene 03, 2012: Nombre de Receptor es opcional
.addProp("Nombre",THIS._fixStr(THIS.Receptor.Nombre))
ENDIF
IF NOT EMPTY(THIS.Receptor.DomicilioFiscal.pais) && ARC Ene 03, 2012: Ya que Pais es el unico atributo requerido
.addNode("Domicilio") && Es opcional en 3.0, 2.2 y 3.2
WITH ._Domicilio
.addProp("calle",THIS._fixStr(THIS.Receptor.DomicilioFiscal.Calle),CFD_OPCIONAL)
.addProp("noExterior",THIS._fixStr(THIS.Receptor.DomicilioFiscal.noExterior),CFD_OPCIONAL)
.addProp("noInterior",THIS._fixStr(THIS.Receptor.DomicilioFiscal.noInterior),CFD_OPCIONAL)
.addProp("colonia",THIS._fixStr(THIS.Receptor.DomicilioFiscal.colonia),CFD_OPCIONAL)
.addProp("localidad",THIS._fixStr(THIS.Receptor.DomicilioFiscal.localidad),CFD_OPCIONAL)
.addProp("referencia",THIS._fixStr(THIS.Receptor.DomicilioFiscal.referencia),CFD_OPCIONAL)
.addProp("municipio",THIS._fixStr(THIS.Receptor.DomicilioFiscal.municipio),CFD_OPCIONAL)
.addProp("estado",THIS._fixStr(THIS.Receptor.DomicilioFiscal.estado),CFD_OPCIONAL)
.addProp("pais",THIS._fixStr(THIS.Receptor.DomicilioFiscal.pais))
.addProp("codigoPostal",THIS._fixStr(THIS.Receptor.DomicilioFiscal.codigoPostal),CFD_OPCIONAL)
ENDWITH
ENDIF
ENDWITH
*-- Nodo "Conceptos"
*
* La clase XmlParser no reconoce que un nodo pueda contener dos subnodos con el mismo nombre. Para
* solucionar este impase, se le anade un contador al nombre de cada nodo Concepto, de modo que quede
* asi:
*
* <Conceptos>
* <Concepto001 ... />
* <Concepto002 ... />
* </Conceptos>
*
* Una vez generado el Xml, se cargara en memoria para quitar las secuencias y asi corregir el problema
*
* VES Nov 11, 2011
* La nueva propiedad createNodeLinks en la clas XMLNodeClass permite superar este problema
*
LOCAL i,oItem,oNodo,oxNodo
.XML._Comprobante.addNode("Conceptos")
WITH .XML._Comprobante._Conceptos
.createNodeLinks = .F. && Nov 11, 2011
FOR i = 1 TO THIS.Conceptos.Count
oItem = THIS.Conceptos.Items(i)
oNodo = .addNode("Concepto")
WITH oNodo
.addProp("ClaveProdServ",THIS._fixStr(oItem.ClaveProdServ))
.addProp("NoIdentificacion",THIS._fixStr(oItem.NoIdentificacion),CFD_OPCIONAL) && Cambio en Orden y de "noIdentificacion" a "NoIdentificacion" v.3.3 ByVigar.
IF THIS.TipoDeComprobante='P'
.addProp("Cantidad",THIS._fixStr(oItem.Cantidad)) && Fijo '1' Cambio de "cantidad" a "Cantidad" para v.3.3 ByVigar
ELSE
.addProp("Cantidad",THIS._fixStr(STR(oItem.Cantidad,10,2))) && Cambio de "cantidad" a "Cantidad" para v.3.3 ByVigar.
ENDIF
.addProp("ClaveUnidad",THIS._fixStr(oItem.ClaveUnidad)) && Nuevo y Obligatorio v.3.3 ByVigar.
.addProp("Unidad",THIS._fixStr(oItem.Unidad),CFD_OPCIONAL) && Sigue Opcional y Cambio de "unidad" a "Unidad" para v.3.3 ByVigar.
.addProp("Descripcion",THIS._fixStr(oItem.Descripcion)) && Cambio de "descripcion" a "Descripcion" para v.3.3 ByVigar.
IF THIS.TipoDeComprobante='P'
.addProp("ValorUnitario",THIS._fixStr(oItem.ValorUnitario)) && Fijo '0' Cambio de "valorUnitario" a "ValorUnitario" para v.3.3 ByVigar.
.addProp("Importe",THIS._fixStr(oItem.Importe)) && Fijo '0' Cambio de "importe" a "Importe" para v.3.3 ByVigar.
ELSE
.addProp("ValorUnitario",THIS._fixStr(STR(oItem.ValorUnitario,15,2))) && Cambio de "valorUnitario" a "ValorUnitario" para v.3.3 ByVigar.
.addProp("Importe",THIS._fixStr(STR(oItem.Importe,15,2))) && Cambio de "importe" a "Importe" para v.3.3 ByVigar.
ENDIF
IF THIS.TipoDeComprobante='I'
oNodo = .addNode("Impuestos")
WITH oNodo
oNodo = .addNode("Traslados")
WITH oNodo
.createNodeLinks = .F. && Nov 11, 2011
oNodo = .addNode("Traslado")
oNodo.addProp("Base",THIS._fixStr(STR(oItem.Base,15,2)))
oNodo.addProp("Impuesto",THIS._fixStr(oItem.Impuesto))
oNodo.addProp("TipoFactor",THIS._fixStr(oItem.TipoFactor))
oNodo.addProp("TasaOCuota",THIS._fixStr(STR((oItem.TasaOCuota/100),10,6))) && Nuevo u obligatorio v.3.3 ByVigar.
oNodo.addProp("Importe",THIS._fixStr(STR(oItem.Iimporte,15,2)))
ENDWITH
ENDWITH
ENDIF
IF !EMPTY(oItem.CuentaPredial.Numero)
.addNode("CuentaPredial")
WITH .Nodes[1] && ARC Feb 2, 2014
.addProp("numero",THIS._fixStr(oItem.CuentaPredial.numero))
ENDWITH
ENDIF
*-- VES Ene 12, 2012: Si el concepto contiene un complemento, se inserta como si
* fuera una addenda en el concepto
IF !ISNULL(oItem.Complemento) AND LOWER(oItem.Complemento.ParentClass) == "icfdaddenda"
oNodo = .addNode("ComplementoConcepto")
oNodo.Data = oItem.Complemento.ToString()
IF !EMPTY(oItem.Complemento.NSTag)
* VES Ago 3, 2012: Se valida que no se haya declarado el Namespace anteriormente, antes
* de anadir su declaracion en las propiedades del nodo Comprobante
IF NOT oParser.XML._Comprobante.isProp("xmlns:" + oItem.Complemento.NSTag)
oParser.XML._Comprobante.addProp("xmlns:" + oItem.Complemento.NSTag, oItem.Complemento.NSUrl)
ENDIF
ENDIF
IF !EMPTY(oItem.Complemento.schemaLocation)
WITH oParser.XML._Comprobante.Props["xsi:schemaLocation"]
.Value = .Value + SPACE(1) + oItem.Complemento.schemaLocation
ENDWITH
ENDIF
ENDIF
ENDWITH
ENDFOR
ENDWITH
IF THIS.TipoDeComprobante='I'
*-- Nodo "Impuestos"
*
* Tanto para los subnodos de Retenciones como de Impuestos se aplico la misma tecnica de enumeracion
* aplicada con los subnodos de Conceptos
*
* VES Nov 11, 2011
* Se aplica la nueva propiedad createNodeLinks para evitar este problema
*
.XML._Comprobante.addNode("Impuestos")
WITH .XML._Comprobante._Impuestos
IF THIS.Impuestos.Retenciones.Count > 0
.addProp("TotalImpuestosRetenidos",THIS._fixStr(STR(THIS.Impuestos.TotalImpuestosRetenidos,15,2)))
.addNode("Retenciones")
WITH ._Retenciones
.createNodeLinks = .F. && Nov 11, 2011
FOR i = 1 TO THIS.Impuestos.Retenciones.Count
oItem = THIS.Impuestos.Retenciones.Items(i)
oNodo = .addNode("Retencion")
oNodo.addProp("Impuesto",THIS._fixStr(oItem.Impuesto)) && 002 IVA v.3.3 ByVigar
oNodo.addProp("Importe",THIS._fixStr(STR(oItem.Importe,15,2)))
ENDFOR
ENDWITH
ENDIF
IF THIS.Impuestos.Traslados.Count > 0
.addProp("TotalImpuestosTrasladados",THIS._fixStr(STR(THIS.Impuestos.TotalImpuestosTrasladados,15,2)))
.addNode("Traslados")
WITH ._Traslados
.createNodeLinks = .F. && Nov 11, 2011
FOR i = 1 TO THIS.Impuestos.Traslados.Count
oItem = THIS.Impuestos.Traslados.Items(i)
oNodo = .addNode("Traslado")
oNodo.addProp("Impuesto",THIS._fixStr(oItem.Impuesto))
oNodo.addProp("TipoFactor",THIS._fixStr(oItem.TipoFactor))
oNodo.addProp("TasaOCuota",THIS._fixStr(STR((oItem.TasaOCuota/100),10,6))) && Nuevo u obligatorio v.3.3 ByVigar.
oNodo.addProp("Importe",THIS._fixStr(STR(oItem.Importe,15,2)))
ENDFOR
ENDWITH
ENDIF
ENDWITH
ENDIF
* set step on
*-- Nodo "Addenda"
*
* VES Nov 14, 2011
* Se reprogramo esta rutina para hacer uso de la nueva clase ICFDAddenda
*
IF !ISNULL(THIS.Addenda) AND LOWER(THIS.Addenda.ParentClass) == "icfdaddenda"
oNodo = oParser.XML._Comprobante.addNode(THIS.Addenda.nodeName)
oNodo.Data = THIS.Addenda.ToString()
IF !EMPTY(THIS.Addenda.NSTag)
oParser.XML._Comprobante.addProp("xmlns:" + THIS.Addenda.NSTag, THIS.Addenda.NSUrl)
ENDIF
IF !EMPTY(THIS.Addenda.schemaLocation)
WITH oParser.XML._Comprobante.Props["xsi:schemaLocation"]
.Value = .Value + SPACE(1) + THIS.Addenda.schemaLocation
ENDWITH
ENDIF
ENDIF
IF THIS.TipoDeComprobante='P' && ByVigar Foxlatino
.XML._Comprobante.addNode("Complemento")
WITH .XML._Comprobante._Complemento
oNodo = oParser.XML._Comprobante._Complemento.addNode("pago10:Pagos")
WITH oParser.XML._Comprobante._Complemento._Pagos
*WITH oParser.XML._Comprobante._Complemento._pago10._Pagos
*oNodo = oParser.XML._Comprobante._Complemento.addNode("pago10Pagos")
*WITH oParser.XML._Comprobante._Complemento._pago10Pagos
.addProp('Version',THIS._fixStr('1.0'))
oNodo = oParser.XML._Comprobante._Complemento._Pagos.addNode("pago10:Pago")
WITH oParser.XML._Comprobante._Complemento._Pagos._Pago
oNodo.addProp("FechaPago", THIS._fixStr(xfecpago))
oNodo.addProp("FormaDePagoP", THIS._fixStr(xfdpago))
oNodo.addProp("MonedaP", THIS._fixStr(xmoneda))
*oNodo.addProp("TipoCambioP", THIS._fixStr((STR(TipoCambioP,10,6)),_OPCIONAL))
oNodo.addProp("Monto", THIS._fixStr(STR(m.imp_net,15,2)))
*oNodo.addProp("NumOperacion", THSI._fixStr(NumOperacion),_OPCIONAL)
*oNodo.addProp("RfcEmisorCtaOrd", THIS._fixStr(RfcEmisorCtaOrd),_OPCIONAL)
*oNodo.addProp("NomBancoOrdExt", THIS._fixStr(NomBancoOrdExt))
*oNodo.addProp("CtaOrdenante", THIS._fixStr(CtaOrdenante),_OPCIONAL)
*oNodo.addProp("RfcEmisorCtaBen", THIS._fixStr(RfcEmisorCtaBen),_OPCIONAL)
*oNodo.addProp("CtaBeneficiario", THIS._fixStr(CtaBeneficiario),_OPCIONAL)
oNodo = oParser.XML._Comprobante._Complemento._Pagos._Pago.addNode("pago10:DoctoRelacionado")
WITH oParser.XML._Comprobante._Complemento._Pagos._Pago._DoctoRelacionado
oNodo.addProp("IdDocumento",this._fixStr(xtimbre))
*oNodo.addProp("Serie",this._fixStr(Serie))
*oNodo.addProp("Folio",this._fixStr(Folio))
oNodo.addProp("MonedaDR",this._fixStr(xmoneda))
*oNodo.addProp("TipoCambioDR",this.TipoCambioDR)
oNodo.addProp("MetodoDePagoDR",this._fixStr(xmetpago))
oNodo.addProp("NumParcialidad",this._fixStr(xnumparc))
oNodo.addProp("ImpSaldoAnt",THIS._fixStr(STR(xsdoant,15,2)))
oNodo.addProp("ImpPagado",THIS._fixStr(STR(m.imp_net,15,2)))
oNodo.addProp("ImpSaldoInsoluto",THIS._fixStr(STR(xinsoluto,15,2)))
ENDWITH
ENDWITH
ENDWITH
ENDWITH
ENDIF
IF swfetim
IF THIS.TipoDeComprobante<>'P'
.XML._Comprobante.addNode("Complemento")
ENDIF
WITH .XML._Comprobante._Complemento
.addNode("tfd:TimbreFiscalDigital")
ENDWITH
WITH .XML._Comprobante._Complemento._TimbreFiscalDigital
.addProp('Version',THIS._fixStr('1.1'))
.addProp('xsi:schemaLocation',THIS._fixStr(xtlcencabtfd))
.addProp('xmlns:tfd', THIS._fixStr(xtlcpietfd))
.addProp("UUID",THIS._fixStr(xtlcfolio))
.addProp("RfcProvCertif",THIS._fixStr(xtlrfcprocer))
.addProp("FechaTimbrado",THIS._fixStr(xtlcFechaTimbrado))
.addProp("SelloCFD",THIS._fixStr(xtlcselloCFD))
.addProp("NoCertificadoSAT",THIS._fixStr(xtlccertificadoSAT))
.addProp("SelloSAT",THIS._fixStr(xtlcselloSAT))
ENDWITH
ENDIF
*-- Se crea el archivo Xml
.Save(pcArchivo)
*-- Se carga el Xml en memoria de nuevo para eliminar los tags consecutivos
* de los nodos Concepto, Retenciones y Traslados, asi como eliminar los
* CRLF
LOCAL cBuff
cBuff = FILETOSTR(pcArchivo)
cBuff = STRT(cBuff, ">" + CHR(13)+CHR(10), ">")
cBuff = STRT(cBuff, "?>", "?>" + CHR(13) + CHR(10))
*-- Si es CFDI se agrega a los nodos el prefijo 'cfdi:'
*
* VES Nov 11, 2011
* Solucionado con la nueva propiedad NameSpace de la clase XMLNodeClass
*
*!* IF ALLTRIM(THIS.version) = "3.0"
*!* cBuff = STRT(cBuff, "<Comprobante", "<cfdi:Comprobante")
*!* cBuff = STRT(cBuff, "<Emisor", "<cfdi:Emisor")
*!* cBuff = STRT(cBuff, "<DomicilioFiscal", "<cfdi:DomicilioFiscal")
*!* cBuff = STRT(cBuff, "<ExpedidoEn", "<cfdi:ExpedidoEn")
*!* cBuff = STRT(cBuff, "</Emisor>", "</cfdi:Emisor>")
*!* cBuff = STRT(cBuff, "<Receptor", "<cfdi:Receptor")
*!* cBuff = STRT(cBuff, "<Domicilio", "<cfdi:Domicilio")
*!* cBuff = STRT(cBuff, "</Receptor>", "</cfdi:Receptor>")
*!* cBuff = STRT(cBuff, "<Conceptos>", "<cfdi:Conceptos>")
*!* cBuff = STRT(cBuff, "<Concepto ", "<cfdi:Concepto ")
*!* cBuff = STRT(cBuff, "<InformacionAduanera", "<cfdi:InformacionAduanera")
*!* cBuff = STRT(cBuff, "<CuentaPredial", "<cfdi:CuentaPredial")
*!* cBuff = STRT(cBuff, "<ComplementoConcepto", "<cfdi:ComplementoConcepto")
*!* cBuff = STRT(cBuff, "<Parte", "<cfdi:Parte")
*!* cBuff = STRT(cBuff, "</Concepto>", "</cfdi:Concepto>")
*!* cBuff = STRT(cBuff, "</Conceptos>", "</cfdi:Conceptos>")
*!* cBuff = STRT(cBuff, "<Impuestos", "<cfdi:Impuestos")
*!* cBuff = STRT(cBuff, "<Retenciones>", "<cfdi:Retenciones>")
*!* cBuff = STRT(cBuff, "<Retencion", "<cfdi:Retencion")
*!* cBuff = STRT(cBuff, "</Retenciones>", "</cfdi:Retenciones>")
*!* cBuff = STRT(cBuff, "<Traslados>", "<cfdi:Traslados>")
*!* cBuff = STRT(cBuff, "<Traslado", "<cfdi:Traslado")
*!* cBuff = STRT(cBuff, "</Traslados>", "</cfdi:Traslados>")
*!* cBuff = STRT(cBuff, "</Impuestos>", "</cfdi:Impuestos>")
*!* cBuff = STRT(cBuff, "<Addenda>", "<cfdi:Addenda>")
*!* cBuff = STRT(cBuff, "</Comprobante>", "</cfdi:Comprobante>")
*!* ENDIF
*-- Se graba de nuevo el Xml ya en su forma final
cBuff = CFDAsc2UTF8(cBuff)
*-- El 4 del tercer parámetro en STRTOFILE() agrega el BOM al XML en UTF-8
IF CFDConf.incluirBOM
* VES Jul 25, 2012
* Se sustituyo el codigo original por un codigo compatible con VFP 6
*
* Codigo original:
*STRTOFILE(cBuff,pcArchivo,4)
LOCAL cBOM
cBOM = CHR(0xEF) + CHR(0xBB) + CHR(0xBF)
STRTOFILE(cBOM + cBuff, pcArchivo)
ELSE
STRTOFILE(cBuff,pcArchivo)
ENDIF
cBuff=""
*-- Si se indico el parametro plValidar, se verifica que el XML este bien formado y que el sello sea valido
*
IF plValidar
*
*-- Se valida la sintaxis del XML
IF NOT CFDValidarXML(pcArchivo, pcArchivoKey, pcPassword, pcMetodo, THIS.ubicacionOpenSSL)
RETURN .F.
ENDIF
*
ENDIF
RETURN .T.
*
ENDWITH
*
ENDPROC
*
ENDDEFINE
*!* *-- CFDRegimenFiscal && Se sustituye por Emisor.RegimenFiscal v.3.3 ByVigar.
*!* * Datos de un regimen fiscal
*!* *
*!* DEFINE CLASS CFDRegimenFiscal AS Custom
*!* *
*!* RegimenFiscal = ""
*!* *
*!* ENDDEFINE
*!* *-- CFDRegimenFiscalCollection (Clase) && Se sustituye por Emisor.RegimenFiscal v.3.3 ByVigar.
*!* * Lista de regimenes fiscales de una persona
*!* *
*!* DEFINE CLASS CFDRegimenFiscalCollection AS CFDCollection
*!* *
*!* RegimenFiscal = "" && Regimen por omision
*!*
*!* *-- Regimen (Setter)
*!* PROCEDURE Regimen_Assign(vNewVal)
*!* IF THIS.Count = 0
*!* THIS.Add(m.vNewVal)
*!* ENDIF
*!* ENDPROC
*!*
*!* *-- Regimen (Getter)
*!* PROCEDURE Regimen_Access
*!* IF THIS.Count > 0
*!* RETURN THIS.Items[1].Regimen
*!* ELSE
*!* RETURN ""
*!* ENDIF
*!* ENDPROC
*!* *-- Add (Metodo)
*!* * Incluye un nuevo elemento en la coleccion
*!* PROCEDURE Add(pcRegimen)
*!* *
*!* LOCAL oItem
*!* oItem = CREATEOBJECT("CFDRegimenFiscal")
*!* WITH oItem
*!* .RegimenFiscal = pcRegimen
*!* ENDWITH
*!*
*!* RETURN DODEFAULT(oItem)
*!* *
*!* ENDPROC
*!*
*!* *
*!* ENDDEFINE
*-- CFDPersona (Clase)
* Representa los datos de una persona juridica especifica
* dentro de un comprobante digital
*
DEFINE CLASS CFDPersona AS Custom
*
*-- Atributos requeridos
Rfc = ""
RegimenFiscal = ""
UsoCfdi = ""
&& Se sustituye por Emisor.RegimenFiscal v.3.3 ByVigar.
* RegimenFiscal = NULL && ARC Dic 20, 2011: Requerido solo para Emisor
*-- Atributos opcionales
expedidoEn = NULL
Nombre = ""
domicilioFiscal = NULL
*-- Contructor de la clase
PROCEDURE Init
THIS.domicilioFiscal = CREATEOBJECT("CFDDireccion")
THIS.ExpedidoEn = CREATEOBJECT("CFDDireccion")
&& Se sustituye por Emisor.RegimenFiscal v.3.3 ByVigar.
*THIS.RegimenFiscal = CREATEOBJECT("CFDRegimenFiscalCollection")
ENDPROC
*
ENDDEFINE
*-- CFDDireccion (Clase)
* Representa una direccion fiscal dentro de un
* comprobante digital
*
DEFINE CLASS CFDDireccion AS Custom
*
*-- Atributos requeridos
Calle = ""
Municipio = ""
Estado = ""
Pais = ""
codigoPostal = ""
*-- Atributos opcionales
noExterior = ""
noInterior = ""
Colonia = ""
Localidad = ""
Referencia = ""
*
ENDDEFINE
DEFINE CLASS CfdiRelacionados AS CFDCollection
*
*-- Add (Metodo)
* Incluye un nuevo elemento en la coleccion. && Incluyo 2 Nuevos elementos en la colección ByVigar.
*
PROCEDURE Add(pcUUID)
*
LOCAL oCfdiRelacionado
oCfdiRelacionado = CREATEOBJECT("CfdiRelacionado")
WITH oCfdiRelacionado
.UUID = pcUUID && Nuevo Obligatorio v.3.3 ByVigar.
ENDWITH
RETURN DODEFAULT(oCfdiRelacionado)
*
ENDPROC
*
ENDDEFINE
*-- CfdiRelacionado (Clase)
* Representa una linea UUID'S Relacionados de un comprobante digital.
*
DEFINE CLASS CfdiRelacionado AS Custom
*
*-- Atributos requeridos
UUID = ""
ENDDEFINE
*-- CFDConceptos (Clase)
* Representa la lista de conceptos contenidos en el comprobante
*
DEFINE CLASS CFDConceptos AS CFDCollection
*
*-- Add (Metodo)
* Incluye un nuevo elemento en la coleccion. && Incluyo 2 Nuevos elementos en la colección ByVigar.
*
PROCEDURE Add(pcClaveProdServ, pcNoIdentificacion, pnCantidad, pcClaveUnidad, pcUnidad, pcDescripcion, pnPU, pnImporte, pnDescuento, PnBase, pcImpuesto, pcTipoFactor, pnTasaOCuota, pnIimporte)
*
LOCAL oConcepto
oConcepto = CREATEOBJECT("CFDConcepto")
WITH oConcepto
.ClaveProdServ = pcClaveProdServ && Nuevo Obligatorio v.3.3 ByVigar.
.NoIdentificacion = pcNoIdentificacion && Nuevo Opcional v.3.3 ByVigar.
.Cantidad = pnCantidad
.ClaveUnidad = pcClaveUnidad && Nuevo Obligatorio v.3.3 ByVigar.
.Unidad = pcUnidad
.Descripcion = pcDescripcion
.ValorUnitario = pnPU
.Importe = pnImporte
.Base = pnBase
.Impuesto = pcImpuesto
.TipoFactor = pcTipoFactor
.TasaOCuota = pnTasaOCuota
.Iimporte = pnIimporte
pnDescuento = 0
IF pnDescuento <> 0
.Descuento = pnDescuento && Nuevo Obligatorio v.3.3 ByVigar.
ENDIF
ENDWITH
RETURN DODEFAULT(oConcepto)
*
ENDPROC
*
ENDDEFINE
*-- CFDConcepto (Clase)
* Representa una linea de la factura dentro de un comprobante digital
*
DEFINE CLASS CFDConcepto AS Custom
*
*-- Atributos requeridos
ClaveProdServ = ''
NoIdentificacion = ''
Cantidad = 0.00
ClaveUnidad = ''
Unidad = ""
Descripcion = ""
ValorUnitario = 0.00
Importe = 0.00
Descuento = 0.00
Base = 0.00
Impuesto = ''
TipoFactor = ''
TasaOCuota = 0.00
Iimporte = 0.00
*-- Atributos opcionales
Impuestos = NULL
informacionAduanera = NULL
cuentaPredial = NULL
Complemento = NULL && VES Ene 12, 2012
*-- Constructor de la clase
PROCEDURE Init
THIS.Impuestos = CREATEOBJECT("CFDComplementoImpuestos")
THIS.InformacionAduanera = CREATEOBJECT("CFDInformacionAduanera")
THIS.CuentaPredial = CREATEOBJECT("CFDCuentaPredial")
THIS.Complemento = NULL && VES Ene 12, 2012
ENDPROC
*
ENDDEFINE