Tengo un problema con mis XML y acabo de darme cuenta ahora. la verdad es que no sé cuándo pudo empezar, estoy revisando XML antiguos y son correctos, pero tras algún cambio me ocurre lo siguiente.
Algunos nodos del XML aparecen como <item> en vez del nombre correcto.
Por ejemplo este:
Código:
<Desglose>
<item>
<Impuesto>01</Impuesto>
<ClaveRegimen>04</ClaveRegimen>
<CalificacionOperacion>S2</CalificacionOperacion>
<TipoImpositivo>0</TipoImpositivo>
<BaseImponibleOimporteNoSujeto>33.64</BaseImponibleOimporteNoSujeto>
<CuotaRepercutida>0</CuotaRepercutida>
</item>
</Desglose>
Sin embargo, la forma de crear el RF es la de siempre y comparándolo con la DLL/SDK publicada en el foro, no hay ninguna diferencia, al menos que yo vea:
Aquí va una porción simplificada del código:
Código:
// Desglose de impuestos
ListaDesglose := DesgloseType.Create();
j:=0;
query2.First;
while not (query2.Eof) do
begin
DetalleDesglose := DetalleType.Create;
DetalleDesglose.Impuesto := ImpuestoType(combobox11.ItemIndex); //IVA, IPSI, IGIC, OTROS
DetalleDesglose.ClaveRegimen := GetOperationTypeFromCode('_'+copy(ComboBox3.text,1,2));
if (AdvOfficeCheckBox3.Checked) or (ComboBox6.ItemIndex=8) then //Inversión del sujeto pasivo
DetalleDesglose.CalificacionOperacion := CalificacionOperacionType.S2
else
DetalleDesglose.CalificacionOperacion := CalificacionOperacionType.S1;
DetalleDesglose.BaseImponibleOimporteNoSujeto := cambiaen(formatfloat('0.00',VeriFactuForm.query2.FieldByName('base_e').asfloat),',','.');
if ComboBox6.ItemIndex=9 then //No sujeta (no se incluyen las cuotas de iva)
begin
DetalleDesglose.CalificacionOperacion := CalificacionOperacionType(2);
end
else
if ComboBox6.ItemIndex=10 then //No sujeta (no se incluyen las cuotas de iva)
begin
DetalleDesglose.CalificacionOperacion := CalificacionOperacionType(3);
end
else // Sujeta + Inversión sujeto pasivo (cuotas iva a cero)
if DetalleDesglose.CalificacionOperacion=CalificacionOperacionType.S2 then
begin
DetalleDesglose.TipoImpositivo := '0';
DetalleDesglose.CuotaRepercutida := '0';
end
else
begin //No exenta/sujeta
DetalleDesglose.TipoImpositivo := cambiaen(VeriFactuForm.query2.FieldByName('porciento').asstring,',','.');
DetalleDesglose.CuotaRepercutida := cambiaen(formatfloat('0.00',VeriFactuForm.query2.FieldByName('IVA_E').asfloat),',','.');
if (Table1.fieldbyname('IVA_RE').asstring='R') and (query2.FieldByName('porciento_re').asfloat>0) then
begin
DetalleDesglose.TipoRecargoEquivalencia := cambiaen(formatfloat('0.00',query2.FieldByName('porciento_re').asfloat),',','.');
DetalleDesglose.CuotaRecargoEquivalencia := cambiaen(formatfloat('0.00',query2.FieldByName('RE_E').asfloat),',','.');
end;
end;
// colocar el desglose en la lista
SetLength(ListaDesglose, j+1 );
ListaDesglose[j] := DetalleDesglose;
inc(j);
query2.Next;
end;
// asignar los desgloses de IVA al objeto de factura
F.RegistroAlta.Desglose:= ListaDesglose;
La forma de armar el RF parece correcta (de hecho ahí no he cambiado nada). El problema creo que está a la hora de guardar el XML en un archivo (que luego tengo que abrir con la app externa que se encarga de enviar los RF a Hacienda).
Ese archivo XML ya está mal guardado, con los nodos <item>, así que creo que el problema en la forma de guardarlos.
Para guardar el RF como XML uso esta función que alguien publicó en el foro:
Código:
function ExtraerXMLdelRF(RegistroFactura: RegistroFacturaType): String;
var
RootNode, NewNode: IXMLNode;
RefId, Swdsl: string;
MyXML: TXMLDocument;
Resultado: string;
MOPToSoapDomConvert: TOPToSoapDomConvert;
begin
Resultado := '';
MyXML := TXMLDocument.Create(Application);
MOPToSoapDomConvert := TOPtoSoapDomConvert.Create(Application);
try
MyXML.Active := True;
MyXML.Encoding := 'utf-8';
// Creamos nodo raíz neutro
RootNode := MyXML.CreateNode('root');
MOPToSoapDomConvert.Encoding := 'utf-8';
MOPToSoapDomConvert.Options := [
TSOAPConvertOption.soDontSendEmptyNodes,
TSOAPConvertOption.soUTF8EncodeXML,
TSOAPConvertOption.soTryAllSchema,
TSOAPConvertOption.soSendUntyped,
TSOAPConvertOption.soSOAP12
];
Swdsl := 'https://prewww2.aeat.es/static_files/common/internet/dep/aplicaciones/es/aeat/tikeV1.0/cont/ws/SistemaFacturacion.wsdl';
// Aquí es donde se genera el XML sin duplicados
NewNode := RegistroFactura.ObjectToSOAP(RootNode, RootNode, MOPToSoapDomConvert,
'RegistroFactura', Swdsl, 'T',
[ocoDontPrefixNode, ocoDontPutTypeAttr], RefId);
// Reemplazamos el nodo raíz con el generado
MyXML.DocumentElement := NewNode;
MyXML.XML.Text := FormatXMLData(MyXML.XML.Text);
MyXML.XML.SaveToFile(extractfilepath(application.exename)+'VeriFactu/RF'+RegistroFactura.RegistroAlta.RefExterna+'.xml',TEncoding.UTF8); // Provisional
Resultado := MyXML.XML.Text;
// Eliminamos cabecera XML y envoltorios innecesarios si hicieran falta
Resultado := StringReplace(Resultado, '<?xml version="1.0"?>', '', [rfIgnoreCase]);
except
on E: Exception do
begin
Log('Error al guardar el XML: ' + E.Message);
ShowMessage('Error al guardar el XML: ' + E.Message);
Resultado := '';
end;
end;
MyXML.Free;
MOPToSoapDomConvert.Free;
Result := Resultado;
end;
¿Puede ser por la ruta de Swdsl := '
https://prewww2.aeat.es/static_files...cturacion.wsdl'; ,ahora que me fijo?
Agradecería cualquier pista, o si alguien usa otra forma de guardar el XML estaría agradecido de estudiarla y ver si me sirve, teniendo en cuenta que después tengo que volver a convertir ese XML en el RF para el envío.
Por cierto, aunque el XML tenga esos nodos <item>, los RF se envían sin problema a Hacienda y no da error, pero me preocupa por si en un futuro empiezan a fallar.