OBS/Makros und Scripting/Anwendungsbereiche/ZUGFERD
Zur Navigation springen
Zur Suche springen
ZUGFERD
Es gibt die Möglichkeit den Import und Export von ZUGFERD Dateien per Scripting zu ändern, falls der OBS-Standard nicht ausreichen sollte.
Felder/Strukturen
TZugPerson = class(TObject)
cZUG_PsNr : String;
cZUG_Bemerkung : String;
cZUG_Name : String;
cZUG_Zeile1 : String;
cZUG_Zeile2 : String;
cZUG_Zeile3 : String;
cZUG_Ort : String;
cZUG_PLZ : String;
cZUG_Land : String;
cZUG_AnspName : String;
cZUG_AnspTel : String;
cZUG_AnspEMail : String;
aFinanzIDs : TxFinazID;
Procedure AddFinanzID(cTmp1:String; cTmp2:String);
----------------------------------------
TZugPosition = class(TObject)
cZUP_UID : String;
cZUP_PosTyp : String;
cZUP_PosNr : String;
cZUP_ArtNr : String;
cZUP_ArtNrLief : String;
cZUP_ArtNrPsNr : String;
cZUP_ArtTyp : String;
cZUP_Bez1 : String;
cZUP_Bez2 : String;
cZUP_WGRName : String;
cZUP_LiefNr : String;
cZUP_Einheit : String;
cZUP_Text : String;
nZUP_Menge : Double;
nZUP_ENetto : Double;
nZUP_GNetto : Double;
nZUP_EBrutto : Double;
nZUP_MwstBetrag : Double;
nZUP_MwstSatz : Double;
cZUP_MWSTTyp : String;
cZUP_OBS_ERLKTO : String;
cZUP_OBS_Einheit : String;
cZUP_OBS_ArtNr : String;
cZUP_OBS_LiefNr : String;
cZUP_OBS_MwstSchl : String;
cZUP_Fehler : String;
----------------------------------------
TZugHeaderFinanzen = class(TObject)
oParent : TZugFerd;
cZUG_Waehrung : String;
nZUG_Netto : Double;
nZUG_Brutto : Double;
nZUG_MwstBetrag : Double;
nZUG_Netto1 : Double;
nZUG_Netto2 : Double;
nZUG_Netto3 : Double;
nZUG_Brutto1 : Double;
nZUG_Brutto2 : Double;
nZUG_Brutto3 : Double;
nZUG_MwstBetrag1 : Double;
nZUG_MwstBetrag2 : Double;
nZUG_MwstBetrag3 : Double;
nZUG_MwstSatz1 : Double;
nZUG_MwstSatz2 : Double;
nZUG_MwstSatz3 : Double;
cZUG_MwstSchl1 : String;
cZUG_MwstSchl2 : String;
cZUG_MwstSchl3 : String;
cZUG_Zahlbed : String;
dZUG_FDatum : TDateTime;
----------------------------------------
TxZugPosition = Class(TObjectList<TZugPosition>);
TZugFerd = class(TObject)
oMyDB : TxDB;
oPersonen : TZugHeaderPersonen;
oFinanzen : TZugHeaderFinanzen;
oLieferung : TZugHeaderLieferung;
oPositionen : TxZugPosition;
cError : String;
lError : Boolean;
cZUG_UID : String;
oZUG_XML : TStringList;
cZUG_PDFName : String;
cZUG_DMSTyp : String;
cZUG_MD5 : String;
cZUG_Nr : String;
cZUG_PDFData : String;
cZUG_Schema : String;
cZUG_TypCode : String;
cZUG_Fehler : String;
cZUG_Bestaetigt : String;
cZUG_SB : String;
cZUG_SysUID : String;
dZUG_RDatum : TDateTime;
dZUG_SDatum : TDateTime;
dZUG_ADatum : TDateTime;
function InsertToPositionen (nPos:Integer; oPos:TZugPosition):integer;
function AddToPositionen (oPos:TZugPosition):integer;
function nPosCnt ():Integer;
function GetPosition (nPos:Integer):TZugPosition;
function AddProto (const cMessage:String):Boolean;
function AddFile (const cFileName:String; const cDMSType:String):Boolean;
Import
Wenn es einen aktiven Eintrag in der Script Libary mit dem Namen IMPORT_ZUGFERD gibt wird der Import über die Pax Funktion ausgeführt.
Beispiel Script Import
//------------------------------------------------------------------------------
// Unit Name: IMPORT_ZUGFERD
// Author: JB
// Date: 09-12-2021
//------------------------------------------------------------------------------
var oZugFerd : TZugFerd;
oCW : TfrmCW;
//------------------------------------------------------------------------------
// Procedure: PersonHeader_Import_XML
// Author: JB
// Date: 09-12-2021
// Comment:
//------------------------------------------------------------------------------
function PersonHeader_Import_XML(oZugPersHeader:TZugPerson; cTradePartyXML:String):Boolean;
var nPos : Integer;
nStart : integer;
cTemp1 : String;
cTemp2 : String;
cTemp3 : String;
begin
CWPrintn(oCW, 'Importiere Header');
GetXMLToken(cTradePartyXML,'ram:Name', oZugPersHeader.cZUG_Name);
if (GetXMLToken(cTradePartyXML,'ram:PostalTradeAddress',cTemp1)) then begin
GetXMLToken(cTemp1,'ram:LineOne' , oZugPersHeader.cZUG_Zeile1);
GetXMLToken(cTemp1,'ram:CityName' , oZugPersHeader.cZUG_Ort);
GetXMLToken(cTemp1,'ram:PostcodeCode', oZugPersHeader.cZUG_PLZ);
GetXMLToken(cTemp1,'ram:CountryID' , oZugPersHeader.cZUG_Land);
end;
CWPrintn(oCW, 'Importiere Tax');
nPos := 1;
while (GetXMLToken(cTradePartyXML,'ram:SpecifiedTaxRegistration', nPos, cTemp1, False)) do begin
nStart := 1;
GetXMLTokenValue(cTemp1,'ram:ID', nStart, cTemp2, cTemp3); // value, key
oZugPersHeader.AddFinanzID(cTemp3, cTemp2);
end;
end;
//------------------------------------------------------------------------------
// Procedure: Personen_Import_XML
// Author: JB
// Date: 09-12-2021
// Comment:
//------------------------------------------------------------------------------
function Personen_Import_XML(cXMLTradeAgreement:String):Boolean;
var cTemp1 : String;
begin
CWPrintn(oCW, 'Importiere Auftragsnummer Kunde');
GetXMLToken(cXMLTradeAgreement,'ram:BuyerReference',oZugFerd.oPersonen.cAufNrKu);
if (GetXMLToken(cXMLTradeAgreement,'ram:BuyerTradeParty',cTemp1)) then begin
PersonHeader_Import_XML(oZugFerd.oPersonen.oZUG_Buyer, cTemp1);
end;
if (GetXMLToken(cXMLTradeAgreement,'ram:SellerTradeParty',cTemp1)) then begin
PersonHeader_Import_XML(oZugFerd.oPersonen.oZUG_Seller,cTemp1);
end;
end;
//------------------------------------------------------------------------------
// Procedure: Lieferung_Import_XML
// Author: JB
// Date: 09-12-2021
// Comment:
//------------------------------------------------------------------------------
function Lieferung_Import_XML(cXML:String):Boolean;
begin
//Wenn Benötigt
CWPrintn(oCW, 'Importiere Lieferung');
end;
//------------------------------------------------------------------------------
// Procedure: Positionen_Import_XML
// Author: JB
// Date: 09-12-2021
// Comment:
//------------------------------------------------------------------------------
function Positionen_Import_XML(oPos:TZugPosition; cXMLTradeLineItem:String):Boolean;
var cTemp1 : String;
cTemp2 : String;
cValue : String;
nPos : integer;
begin
nPos := 1;
CWPrintn(oCW, 'Importiere Positionen');
if (GetXMLToken(cXMLTradeLineItem,'ram:AssociatedDocumentLineDocument',cTemp1)) then begin
GetXMLToken(cTemp1,'ram:LineID',oPos.cZUP_PosNr);
end;
if (GetXMLToken(cXMLTradeLineItem,'ram:SpecifiedTradeProduct',cTemp1)) then begin
GetXMLToken(cTemp1,'ram:Name' , oPos.cZUP_Bez1 );
GetXMLToken(cTemp1,'ram:SellerAssignedID' , oPos.cZUP_ArtNrLief);
GetXMLTokenValue(cTemp1, 'ram:GlobalID' , nPos, oPos.cZUP_ArtNr, oPos.cZUP_ArtTyp);
GetXMLToken(cTemp1,'ram:Description' , oPos.cZUP_Text);
//Warengruppe
if GetXMLToken(cTemp1,'ram:DesignatedProductClassification', cTemp2) then begin
//nPos := 1;
GetXMLToken(cTemp2,'ram:ClassName', oPos.cZUP_WGRName);
end;
end;
if (GetXMLToken(cXMLTradeLineItem,'ram:SpecifiedLineTradeAgreement',cTemp1)) then begin
if (GetXMLToken(cTemp1,'ram:GrossPriceProductTradePrice',cTemp2)) then begin
GetXMLToken(cTemp2,'ram:ChargeAmount', cValue);
oPos.nZUP_EBrutto := fVAl(cValue);
end;
if (GetXMLToken(cTemp1,'ram:NetPriceProductTradePrice',cTemp2)) then begin
GetXMLToken(cTemp2,'ram:ChargeAmount', cValue);
oPos.nZUP_ENetto := fVAl(cValue);
end;
end;
if (GetXMLToken(cXMLTradeLineItem,'ram:SpecifiedLineTradeDelivery', cTemp1)) then begin
GetXMLTokenValue(cTemp1,'ram:BilledQuantity', nPos, cValue, oPos.cZUP_Einheit);
oPos.nZUP_Menge := fVAl(cValue);
end;
if (GetXMLToken(cXMLTradeLineItem,'ram:SpecifiedLineTradeSettlement',cTemp1)) then begin
if (GetXMLToken(cTemp1,'ram:ApplicableTradeTax',cTemp2)) then begin
GetXMLToken(cTemp2,'ram:RateApplicablePercent', cValue);
oPos.nZUP_MwstSatz := fVAl(cValue);
GetXMLToken(cTemp2,'ram:TypeCode', oPos.cZUP_MWSTTyp );
end;
GetXMLToken(cTemp1,'ram:LineTotalAmount', cValue);
oPos.nZUP_GNetto := fVAl(cValue);
end;
if (oPos.nZUP_ENetto > 0) and (oPos.nZUP_MwstSatz > 0) then begin
oPos.nZUP_MwstBetrag := oPos.nZUP_ENetto * (oPos.nZUP_MwstSatz / 100);
end;
oPos.cZUP_Fehler := '';
end;
//------------------------------------------------------------------------------
// Procedure: Finanzen_Import_XML
// Author: JB
// Date: 09-12-2021
// Comment:
//------------------------------------------------------------------------------
function Finanzen_Import_XML(oFinanzen:TZugHeaderFinanzen; cXMLTradeSettlement:String):Boolean;
var cTemp1 : String;
cTemp2 : String;
cTemp3 : String;
cTemp4 : String;
nPos : Integer;
oPos : TZugPosition;
oPosTmp : TZugPosition;
cIndikator : String;
lIndikator : Boolean;
cText : String;
nPosNr : Integer;
cPosNr : String;
i : integer;
begin
CWPrintn(oCW, 'Importiere Finanzen');
lIndikator := false;
if (GetXMLToken(cXMLTradeSettlement,'ram:InvoiceCurrencyCode',cTemp1)) then begin
GetXMLToken(cTemp1,'ram:InvoiceCurrencyCode', oFinanzen.cZUG_Waehrung);
end;
if (GetXMLToken(cXMLTradeSettlement,'ram:SpecifiedTradeSettlementPaymentMeans',cTemp1)) then begin
oPos := TZugPosition.Create();
oPos.cZUP_UID := TZugFerd(oFinanzen.oParent).cZUG_UID;
oPos.cZUP_PosTyp := ZUG_POSTYP_MEMO;
if (GetXMLToken(cTemp1,'ram:PayeePartyCreditorFinancialAccount',cTemp2)) then begin
if (GetXMLToken(cTemp2,'ram:IBANID',cTemp3)) then begin
cText := 'Betrag zu überweisen an:' + CRLF + 'IBAN ' + cTemp3;
end;
end;
oPos.cZUP_Text := cText;
//TObjectList(TZugFerd(oFinanzen.oParent).oPositionen).Insert(0, oPos);
TZugFerd(oFinanzen.oParent).InsertToPositionen(0, oPos);
end;
if (GetXMLToken(cXMLTradeSettlement,'ram:SpecifiedTradeSettlementHeaderMonetarySummation',cTemp1)) then begin
GetXMLToken(cTemp1,'ram:TaxBasisTotalAmount', cTemp2);
oZugFerd.oFinanzen.nZUG_Netto := fVal(cTemp2);
GetXMLToken(cTemp1,'ram:TaxTotalAmount', cTemp2);
oFinanzen.nZUG_MwstBetrag := fVal(cTemp2);
GetXMLToken(cTemp1,'ram:GrandTotalAmount', cTemp2);
oFinanzen.nZUG_Brutto := fVal(cTemp2);
end;
if (GetXMLToken(cXMLTradeSettlement,'ram:SpecifiedTradePaymentTerms',cTemp1)) then begin
GetXMLToken(cTemp1,'ram:Description', oFinanzen.cZUG_Zahlbed);
if (GetXMLToken(cTemp1,'ram:DueDateDateTime',cTemp2, False)) then begin
GetXMLTokenValue(cTemp2,'udt:DateTimeString', nPos,cTemp4, cTemp3);
oFinanzen.dZUG_FDatum := SToD(cTemp4);
end;
end;
nPos := 1;
if (GetXMLToken(cXMLTradeSettlement,'ram:ApplicableTradeTax', nPos, cTemp1)) then begin
GetXMLToken(cTemp1,'ram:CalculatedAmount', cTemp2);
oFinanzen.nZUG_MwstBetrag1 := fVal(cTemp2);
GetXMLToken(cTemp1,'ram:BasisAmount', cTemp2);
oFinanzen.nZUG_Netto1 := fVal(cTemp2);
oFinanzen.nZUG_Brutto1 := oFinanzen.nZUG_Netto1 + oFinanzen.nZUG_MwstBetrag1;
GetXMLToken(cTemp1,'ram:RateApplicablePercent', cTemp2);
oFinanzen.nZUG_MwstSatz1 := fVal(cTemp2);
end;
if (GetXMLToken(cXMLTradeSettlement,'ram:ApplicableTradeTax', nPos, cTemp1)) then begin
GetXMLToken(cTemp1,'ram:CalculatedAmount', cTemp2);
oFinanzen.nZUG_MwstBetrag2 := fVal(cTemp2);
GetXMLToken(cTemp1,'ram:BasisAmount', cTemp2);
oFinanzen.nZUG_Netto2 := fVal(cTemp2);
oFinanzen.nZUG_Brutto2 := oFinanzen.nZUG_Netto2 + oFinanzen.nZUG_MwstBetrag2;
GetXMLToken(cTemp1,'ram:RateApplicablePercent', cTemp2);
oFinanzen.nZUG_MwstSatz2 := fVal(cTemp2);
end;
if (GetXMLToken(cXMLTradeSettlement,'ram:ApplicableTradeTax', nPos, cTemp1)) then begin
GetXMLToken(cTemp1,'ram:CalculatedAmount', cTemp2);
oFinanzen.nZUG_MwstBetrag3 := fVal(cTemp2);
GetXMLToken(cTemp1,'ram:BasisAmount', cTemp2);
oFinanzen.nZUG_Netto3 := fVal(cTemp2);
oFinanzen.nZUG_Brutto3 := oFinanzen.nZUG_Netto3 + oFinanzen.nZUG_MwstBetrag3;
GetXMLToken(cTemp1,'ram:RateApplicablePercent', cTemp2);
oFinanzen.nZUG_MwstSatz3 := fVal(cTemp2);
end;
if (oFinanzen.nZUG_MWSTBetrag = 0) then begin
oFinanzen.nZUG_MWSTBetrag := oFinanzen.nZUG_MwstBetrag1 + oFinanzen.nZUG_MwstBetrag2 + oFinanzen.nZUG_MwstBetrag3;
end;
CWPrintn(oCW, 'Importiere Rabatte und Zusatzkosten');
// Rabatte und Zusatzkosten als Positionen erfassen
nPos := 1;
while (GetXMLToken(cXMLTradeSettlement, 'ram:SpecifiedTradeAllowanceCharge', nPos, cTemp1)) do begin
// Höchste Positionsnummer ermitteln, damit Zusatzkosten mit
// aufsteigender Pos-Nr erfasst werden können
nPosNr := 0;
//for i:=0 to TObjectList(TZugFerd(oFinanzen.oParent).oPositionen).Count do begin
for i:=0 to TZugFerd(oFinanzen.oParent).nPosCnt()-1 do begin
oPosTmp := TZugFerd(oFinanzen.oParent).GetPosition(i);
cPosNr := oPosTmp.cZUP_PosNr;
nPosNr := Max(nPosNr, iVal(cPosNr));
CWPrintn(oCW, 'MaxNr ' + cPosNr);
end;
oPos := TZugPosition.Create( TZugFerd(oFinanzen.oParent).cZUG_UID);
oPos := TZugPosition.Create();
oPos.cZUP_UID := TZugFerd(oFinanzen.oParent).cZUG_UID;
oPos.cZUP_PosNr := TStr(nPosNr + 1, 0, 0);
cText := '';
if (GetXMLToken(cTemp1,'ram:ChargeIndicator',cTemp2)) then begin
GetXMLToken(cTemp1,'udt:Indicator', cIndikator);
lIndikator := lower(cIndikator) = 'true';
if (lIndikator) then begin
cText := cText + 'Zusatzkosten' + CRLF;
end else begin
cText := cText + 'Rabatt' + CRLF;
end;
end;
GetXMLToken(cTemp1,'ram:Reason',oPos.cZUP_Bez1);
if (GetXMLToken(cTemp1,'ram:BasisAmount',cTemp2)) then begin
cText := cText + 'Grundlage: ' + cTemp2;
end;
if (GetXMLToken(cTemp1,'ram:ActualAmount',cTemp2)) then begin
oPos.nZUP_ENetto := fVal(cTemp2);
if (lIndikator) then begin // Rabatt
oPos.nZUP_Menge := 1;
end else begin
oPos.nZUP_Menge := -1;
end;
end;
if (GetXMLToken(cTemp1,'ram:CategoryTradeTax',cTemp2)) then begin
if (GetXMLToken(cTemp2,'ram:RateApplicablePercent',cTemp3)) then begin
opos.nZUP_MwstSatz := fVal(cTemp3);
end;
end;
oPos.cZUP_Text := cText;
oPos.nZUP_GNetto := oPos.nZUP_Menge * oPos.nZUP_ENetto;
TZugFerd(oFinanzen.oParent).AddToPositionen(oPos);
//TObjectList(TZugFerd(oFinanzen.oParent).oPositionen).Add(oPos);
end;
end;
//------------------------------------------------------------------------------
// Procedure: Startproc
// Author: JB
// Date: 09-12-2021
// Comment: Startfunction
//------------------------------------------------------------------------------
function Startproc(oOBJ:TZugFerd; cXMLData:String):Boolean;
var cTemp1 : String;
cTemp2 : String;
cTemp3 : String;
nPos : Integer;
oPos : TZugPosition;
lImport : Boolean;
begin
Result := False;
oZugFerd := oOBJ;
oCW := CWOpen(20, 80, 'Importiere XML Zugferddaten');
try
if (GetXMLToken(cXMLData, 'ram:GuidelineSpecifiedDocumentContextParameter', cTemp1)) then begin
GetXMLToken(cTemp1,'ram:ID', oZugFerd.cZUG_Schema);
end;
if (GetXMLToken(cXMLData, 'rsm:ExchangedDocument', cTemp1)) then begin
nPos := 1;
GetXMLTokenValue(cTemp1,'udt:DateTimeString', nPos, cTemp2, cTemp3);
oZugFerd.dZUG_RDatum := SToD(cTemp2);
nPos := 1;
GetXMLToken(cTemp1,'ram:ID', oZugFerd.cZUG_Nr);
GetXMLToken(cTemp1,'ram:TypeCode', oZugFerd.cZUG_TypCode);
CWPrintn(oCW, 'Importiere Positionen Freitext');
while (GetXMLToken(cTemp1, 'ram:IncludedNote', nPos, cTemp2)) do begin
oPos := TZugPosition.Create(oZugFerd.cZUG_UID);
oPos.cZUP_PosTyp := ZUG_POSTYP_MEMO;
oPos.cZUP_Bez1 := 'Freitext';
GetXMLToken(cTemp2, 'ram:Content', oPos.cZUP_Text);
GetXMLToken(cTemp2, 'ram:SubjectCode', oPos.cZUP_Bez2);
oZugFerd.AddToPositionen(oPos);
end;
end;
if (GetXMLToken(cXMLData, 'rsm:SupplyChainTradeTransaction', cTemp1)) then begin
lImport := False;
if (GetXMLToken(cTemp1, 'ram:ApplicableHeaderTradeDelivery', cTemp2)) then begin
CWPrintn(oCW, 'Importiere Lieferung');
Lieferung_Import_XML(cTemp2);
lImport := True;
end;
if (GetXMLToken(cTemp1, 'ram:ApplicableHeaderTradeAgreement', cTemp2)) then begin
CWPrintn(oCW, 'Importiere Personen');
Personen_Import_XML(cTemp2);
lImport := True;
end;
if (not lImport) then begin
oZugFerd.AddProto('Kein Token ApplicableHeaderTradeDelivery vorhanden!');
oZugFerd.AddProto('Kein Token ApplicableHeaderTradeAgreement vorhanden!');
Result := False;
end;
nPos := 1;
while (GetXMLToken(cTemp1, 'ram:IncludedSupplyChainTradeLineItem', nPos, cTemp2)) do begin
oPos := TZugPosition.Create(oZugFerd.cZUG_UID);
Positionen_Import_XML(oPos, cTemp2);
oZugFerd.AddToPositionen(oPos);
end;
// Beträge nach den Positionen, damit Rabatte und Zusatzkosten als Positionen am Ende erfasst werden
if (GetXMLToken(cTemp1, 'ram:ApplicableHeaderTradeSettlement', cTemp2)) then begin
Finanzen_Import_XML(oZugFerd.oFinanzen, cTemp2);
end;
Result := True;
end;
finally
CWClose(oCW);
end;
end;
//------------------------------------------------------------------------------
Export
Wenn es einen aktiven Eintrag in der Script Libary mit dem Namen EXPORT_ZUGFERD gibt wird die Erstellung der XML-Datei über die Pax Funktion ausgeführt.
Beispiel Script Export
//------------------------------------------------------------------------------
// Unit Name: EXPORT_ZUGFERD
// Author: JB
// Date: 09-12-2021
//------------------------------------------------------------------------------
var oXML : TXMLWriter;
cRechnungsNr : String;
qRech : TxFQuery;
qKonst : TxFQuery;
qStamm : TxFQuery;
qPerson : TxFQuery;
dLiefDat : TDateTime;
nMWST : Double;
nMwstTotal : Double;
oFormat : TFormatSettings;
//------------------------------------------------------------------------------
// Procedure: _Format
// Author: JB
// Date: 09-12-2021
// Comment: Zahlenausgabe für XML
//------------------------------------------------------------------------------
function _Format(nVal : Double): String;
begin
Result := ZugFerd_FormatDouble(nVal);
end;
//------------------------------------------------------------------------------
// Procedure: OBSRechnungsart_To_ZUGInvoiceTypeCode(
// Author: JB
// Date: 09-12-2021
// Comment:
//------------------------------------------------------------------------------
function OBSRechnungsart_To_ZUGInvoiceTypeCode(const cOBSRechArt : String): String;
begin
Result := '';
if (cOBSRechArt = '1') then begin // Standardrechnung
Result := ZUG_RECHTYP_COMMERCIAL;
end else if (cOBSRechArt = '2') then begin // Abschlagsrechnung
Result := ZUG_RECHTYP_ABSCHLAG;
end else if (cOBSRechArt = '3') then begin // Schlussrechnung
Result := ZUG_RECHTYP_COMMERCIAL;
end else if (cOBSRechArt = '4') then begin // Proformarechnung
Result := ZUG_RECHTYP_PROFORMA;
end else if (cOBSRechArt = '5') then begin // Gutschrift
Result := ZUG_RECHTYP_GUTSCHRIFT;
end else if (cOBSRechArt = '6') then begin // Stornorechnung
Result := ZUG_RECHTYP_GUTSCHRIFT;
end else if (cOBSRechArt = '7') then begin // Anzahlungsrechnung
Result := ZUG_RECHTYP_PARTIAL;
end;
end;
//------------------------------------------------------------------------------
// Procedure: OBSMwstSchl_To_ZUGCategoryCode((
// Author: JB
// Date: 09-12-2021
// Comment:
//------------------------------------------------------------------------------
function OBSMwstSchl_To_ZUGCategoryCode(const cOBSMWST : String): String;
var nMwst : Integer;
begin
nMWST := iVal(cOBSMWST);
if (nMWST < 10) then begin
Result := ZUG_MWSTTYP_STANDARD;
end;
end;
//------------------------------------------------------------------------------
// Procedure: GetVersandTyp(
// Author: JB
// Date: 09-12-2021
// Comment:
//------------------------------------------------------------------------------
function GetVersandTyp(oMyDB: TxDB; cPerson: String): Integer;
begin
Result := iVal(DB_ReadSQLValue(oMyDB,'ZUGFERD_PERSONEN','zp_versand','zp_psnr = '+DB_SQLVal(cPerson)));
end;
//------------------------------------------------------------------------------
// Procedure: ZugFerd_Positionen
// Author: JB
// Date: 09-12-2021
// Comment:
//------------------------------------------------------------------------------
procedure ZugFerd_Positionen(var oXML : TXMLWriter);
var cSQL : String;
qPos : TxFQuery;
begin
cSQL := 'SELECT * FROM RECHPOS'+
' LEFT JOIN s_mwst ON az_mwstsch = mw_nr' +
' WHERE az_nr = ' + DB_SQLVal(cRechnungsNr) +
' AND az_typ = 0';
if (DB_SOpen(oDB, cSQL, qPos)) then begin
dLiefDat := CToD(DB_ReadSQLValue(oDB,'LIEFSTA LEFT JOIN LIEFPOS ON a_nr = az_nr','a_datum','az_aufnr = '+DB_SQLVal(qPos.A2C('az_aufnr'))));
if (empty(dLiefDat)) then begin
dLiefDat := qRech.A2D('a_facdatum');
if (empty(dLiefdat)) then begin
dLiefDat := qRech.A2D('a_datum');
end;
end;
while not qPos.eof do begin
with oXML do begin
OpenElement('ram:IncludedSupplyChainTradeLineItem');
OpenElement('ram:AssociatedDocumentLineDocument');
AddElement('ram:LineID', qPos.A2C('az_posnr')); // Positionsnummer // BR-21
CloseElement; // ram:AssociatedDocumentLineDocument
OpenElement('ram:SpecifiedTradeProduct');
AddElement('ram:SellerAssignedID', qPos.A2C('az_artnr')); //BT-155 Artikelnummer des Verkäufers
AddElement('ram:Name', qPos.A2C('az_bez1')); // Positionsname // BR-25
CloseElement; // ram:SpecifiedTradeProduct
OpenElement('ram:SpecifiedLineTradeAgreement');
OpenElement('ram:NetPriceProductTradePrice');
AddElement('ram:ChargeAmount', _Format(qPos.A2F('az_epreis'))); // Netto Einzelpreis // BR-26, BR-27
CloseElement; // ram:NetPriceProductTradePrice
CloseElement; // ram:SpecifiedLineTradeAgreement
OpenElement('ram:SpecifiedLineTradeDelivery');
AddAttrElement('ram:BilledQuantity', 'unitCode', 'H87', _Format(qPos.A2F('az_menge'))); // Einheit und Menge // BR-22, BR-23
CloseElement; // ram:SpecifiedLineTradeDelivery
OpenElement('ram:SpecifiedLineTradeSettlement');
OpenElement('ram:ApplicableTradeTax');
OpenElement('ram:TypeCode');
SetContent('VAT'); // Steuerart, im Standard immer VAT
CloseElement; // ram:TypeCode
OpenElement('ram:CategoryCode');
// Andere: (100 - 199)
// AE: $13b Reverse Charge (200 - 299)
// K: Innereuropäisch (400 - 499)
SetContent('S');
CloseElement; // ram:CategoryCode
OpenElement('ram:RateApplicablePercent');
SetContent(_Format(qPos.A2F('mw_satz')));
CloseElement; // ram:RateApplicablePercent
CloseElement; // ram:ApplicableTradeTax
if (qPos.A2F('az_rabatt') > 0) or (qPos.A2F('az_grabatt') > 0) then begin
OpenElement('ram:SpecifiedTradeAllowanceCharge');
OpenElement('ram:ChargeIndicator');
AddElement('udt:Indicator','false'); // false = Abschlag, true = Zuschlag
CloseElement; // ram:ChargeIndicator
if (qPos.A2F('az_rabatt') > 0) then begin
AddElement('ram:CalculationPercent', qPos.A2C('az_rabatt'));
end;
AddElement('ram:BasisAmount', _Format(qPos.A2F('az_menge')*qPos.A2F('az_epreis')));
if (qPos.A2F('az_rabatt') > 0) then begin // BR-41
AddElement('ram:ActualAmount', _Format(qPos.A2F('az_menge')*qPos.A2F('az_epreis')*(qPos.A2F('az_rabatt')/100)));
end else if (qPos.A2F('az_grabatt') > 0) then begin
AddElement('ram:ActualAmount', _Format(qPos.A2F('az_grabatt')));
end;
AddElement('ram:ReasonCode', '95');
AddElement('ram:Reason', 'Discount'); // BR-42
CloseElement; // ram:SpecifiedTradeAllowanceCharge
end;
OpenElement('ram:SpecifiedTradeSettlementLineMonetarySummation');
AddElement('ram:LineTotalAmount', _Format(qPos.A2F('az_gpreis'))); // Netto Gesampreis // BR-24
CloseElement; // ram:SpecifiedTradeSettlementLineMonetarySummation
CloseElement; // ram:SpecifiedLineTradeSettlement
CloseElement; // ram:IncludedSupplyChainTradeLineItem
end;
qPos.next();
end;
end;
DB_Close(qPos);
end;
//------------------------------------------------------------------------------
// Procedure: StartProc
// Author: JB
// Date: 09-12-2021
// Comment: Start Procwedure
//------------------------------------------------------------------------------
function StartProc(xoXML : TXMLWriter;
xcRechnungsNr : String;
xqRech : TxFQuery;
xqKonst : TxFQuery;
xqStamm : TxFQuery;
xqPerson : TxFQuery):Boolean;
begin
Result := True;
oXML := xoXML;
cRechnungsNr := xcRechnungsNr;
qRech := xqRech;
qKonst := xqKonst;
qStamm := xqStamm;
qPerson := xqPerson;
oFormat.DecimalSeparator := '.';
oFormat.CurrencyDecimals := 2;
oXML.OpenElement('rsm:CrossIndustryInvoice');
oXML.SetAttribute('xmlns:a', 'urn:un:unece:uncefact:data:standard:QualifiedDataType:100');
oXML.SetAttribute('xmlns:rsm', 'urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100');
oXML.SetAttribute('xmlns:qdt', 'urn:un:unece:uncefact:data:standard:QualifiedDataType:10');
oXML.SetAttribute('xmlns:ram', 'urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100');
oXML.SetAttribute('xmlns:xs', 'http://www.w3.org/2001/XMLSchema');
oXML.SetAttribute('xmlns:udt', 'urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100');
oXML.OpenElement('rsm:ExchangedDocumentContext');
oXML.OpenElement('ram:GuidelineSpecifiedDocumentContextParameter');
oXML.AddElement('ram:ID', ZUG_COMPLIANCE_XRECHNUNG_2_0); // BR-1
oXML.CloseElement; // ram:GuidelineSpecifiedDocumentContextParameter
oXML.CloseElement; // rsm:ExchangedDocumentContext
oXML.OpenElement('rsm:ExchangedDocument');
oXML.AddElement('ram:ID', qRech.A2C('a_nr')); // Rechnungsnummer // BR-2
oXML.AddElement('ram:TypeCode', OBSRechnungsart_To_ZUGInvoiceTypeCode(qRech.A2C('a_art'))); // Rechnungstyp // BR-4
oXML.OpenElement('ram:IssueDateTime');
oXML.AddAttrElement('udt:DateTimeString','format', '102', DToS(qRech.A2D('a_datum'))); // Datum // BR-3
oXML.CloseElement; // ram:IssueDateTime
//Wenn Postgut
//oXML.OpenElement('ram:IncludedNote');
// oXML.AddElement('ram:Content',qRech.A2C('a_aufnrku'));
// oXML.AddElement('ram:SubjectCode','INV');
//oXML.CloseElement; //ram:IncludedNote
oXML.CloseElement; // rsm:ExchangedDocument
oXML.OpenElement('rsm:SupplyChainTradeTransaction');
ZugFerd_positionen(oXML); // ram:IncludedSupplyChainTradeLineItem
oXML.OpenElement('ram:ApplicableHeaderTradeAgreement');
oXML.AddElement('ram:BuyerReference',qPerson.A2C('zp_leitwegid')); // Leitweg-ID für XRechnung
oXML.OpenElement('ram:SellerTradeParty');
oXML.AddElement('ram:ID', qPerson.A2C('zp_kreditorennr')); // BT-29: Kreditorennummer beim Kunden
oXML.AddElement('ram:Name', qKonst.A2C('k_name')); // BR-6
oXML.OpenElement('ram:DefinedTradeContact'); // BG-6, BR-DE-5, BR-DE-6, BR-DE-7
oXML.AddElement('ram:PersonName', qPerson.A2C('zp_apname')); // BT-41 Name
oXML.OpenElement('ram:TelephoneUniversalCommunication'); // BT-42 Telefon
oXML.AddElement('ram:CompleteNumber', qPerson.A2C('zp_aptel'));
oXML.CloseElement(); // ram:TelephoneUniversalCommunication
oXML.OpenElement('ram:EmailURIUniversalCommunication'); // BT-43 E-Mail
oXML.AddElement('ram:URIID', qPerson.A2C('zp_apmail'));
oXML.CloseElement(); // ram:EmailURIUniversalCommunication
oXML.CloseElement(); // ram:DefinedTradeContact
oXML.OpenElement('ram:PostalTradeAddress'); // BR-8
oXML.AddElement('ram:PostcodeCode', qKonst.A2C('k_plz'));
oXML.AddElement('ram:LineOne', qKonst.A2C('k_strasse'));
oXML.AddElement('ram:CityName', qKonst.A2C('k_ort'));
oXML.AddElement('ram:CountryID', 'DE'); // BR-9
oXML.CloseElement; // ram:PostalTradeAddress
oXML.OpenElement('ram:SpecifiedTaxRegistration');
oXML.AddAttrElement('ram:ID', 'schemeID', 'VA', qKonst.A2C('k_ustid')); //
oXML.CloseElement; // ram:SpecifiedTaxRegistration
oXML.CloseElement; // ram:SellerTradeParty
oXML.OpenElement('ram:BuyerTradeParty');
oXML.AddElement('ram:Name',qRech.A2C('a_name')); // BR-7
oXML.OpenElement('ram:PostalTradeAddress'); // BR-10
oXML.AddElement('ram:PostcodeCode', qRech.A2C('a_plz'));
oXML.AddElement('ram:LineOne', qRech.A2C('a_strasse'));
oXML.AddElement('ram:CityName', qRech.A2C('a_ort'));
oXML.AddElement('ram:CountryID', 'DE'); // BR-11
oXML.CloseElement; // ram:PostalTradeAddress
oXML.CloseElement; // ram:BuyerTradeParty
oXML.OpenElement('ram:BuyerOrderReferencedDocument');
oXML.AddElement('ram:IssuerAssignedID',qRech.A2C('a_aufnrku'));
oXML.CloseElement(); //ram:BuyerOrderReferencedDocument
oXML.CloseElement; // ram:ApplicableHeaderTradeAgreement
oXML.OpenElement('ram:ApplicableHeaderTradeDelivery'); // Tag muss vorhanden sein
if (not empty(qRech.A2C('a_vstrasse'))) then begin
oXML.OpenElement('ram:ShipToTradeParty'); // Abweichender Warenempfänger
oXML.OpenElement('ram:PostalTradeAddress'); // BR-57
oXML.AddElement('ram:PostcodeCode', qRech.A2C('a_vplz'));
oXML.AddElement('ram:LineOne', qRech.A2C('a_vstrasse'));
oXML.AddElement('ram:CityName', qRech.A2C('a_vort'));
oXML.AddElement('ram:CountryID', 'DE'); // BR-11
oXML.CloseElement; // ram:PostalTradeAddress
oXML.CloseElement;
end;
oXML.OpenElement('ram:ActualDeliverySupplyChainEvent');
oXML.OpenElement('ram:OccurrenceDateTime');
oXML.AddAttrElement('udt:DateTimeString','format', '102', DToS(dLiefDat)); // Datum // BT-72
oXML.CloseElement;
oXML.CloseElement;
oXML.CloseElement;
oXML.OpenElement('ram:ApplicableHeaderTradeSettlement');
oXML.AddElement('ram:InvoiceCurrencyCode', 'EUR'); // Währungscode nach ISO 4217 // BR-5
// BR-49, BR-50, BR-51
if (not empty(qStamm.A2C('zus_iban1'))) then begin
oXML.OpenElement('ram:SpecifiedTradeSettlementPaymentMeans');
oXML.AddElement('ram:TypeCode', '30'); // 30 = Überweisung // BR-49
oXML.AddElement('ram:Information', qStamm.A2C('zus_bank1'));
oXML.OpenElement('ram:PayeePartyCreditorFinancialAccount');
oXML.AddElement('ram:IBANID', qStamm.A2C('zus_iban1'));
oXML.CloseElement; // ram:PayeePartyCreditorFinancialAccount
oXML.CloseElement; // ram:SpecifiedTradeSettlementPaymentMeans
end;
if (not empty(qStamm.A2C('zus_iban2'))) then begin
oXML.OpenElement('ram:SpecifiedTradeSettlementPaymentMeans');
oXML.AddElement('ram:TypeCode', '30'); // 30 = Überweisung // BR-49
oXML.AddElement('ram:Information', qStamm.A2C('zus_bank2'));
oXML.OpenElement('ram:PayeePartyCreditorFinancialAccount');
oXML.AddElement('ram:IBANID', qStamm.A2C('zus_iban2'));
oXML.CloseElement; // ram:PayeePartyCreditorFinancialAccount
oXML.CloseElement; // ram:SpecifiedTradeSettlementPaymentMeans
end;
if (not empty(qStamm.A2C('zus_iban3'))) then begin
oXML.OpenElement('ram:SpecifiedTradeSettlementPaymentMeans');
oXML.AddElement('ram:TypeCode', '30'); // 30 = Überweisung // BR-49
oXML.AddElement('ram:Information', qStamm.A2C('zus_bank3'));
oXML.OpenElement('ram:PayeePartyCreditorFinancialAccount');
oXML.AddElement('ram:IBANID', qStamm.A2C('zus_iban3'));
oXML.CloseElement; // ram:PayeePartyCreditorFinancialAccount
oXML.CloseElement; // ram:SpecifiedTradeSettlementPaymentMeans
end;
if (not empty(qStamm.A2C('zus_iban4'))) then begin
oXML.OpenElement('ram:SpecifiedTradeSettlementPaymentMeans');
oXML.AddElement('ram:TypeCode', '30'); // 30 = Überweisung // BR-49
oXML.AddElement('ram:Information', qStamm.A2C('zus_bank4'));
oXML.OpenElement('ram:PayeePartyCreditorFinancialAccount');
oXML.AddElement('ram:IBANID', qStamm.A2C('zus_iban4'));
oXML.CloseElement; // ram:PayeePartyCreditorFinancialAccount
oXML.CloseElement; // ram:SpecifiedTradeSettlementPaymentMeans
end;
if (not empty(qStamm.A2C('zus_iban5'))) then begin
oXML.OpenElement('ram:SpecifiedTradeSettlementPaymentMeans');
oXML.AddElement('ram:TypeCode', '30'); // 30 = Überweisung // BR-49
oXML.AddElement('ram:Information', qStamm.A2C('zus_bank5'));
oXML.OpenElement('ram:PayeePartyCreditorFinancialAccount');
oXML.AddElement('ram:IBANID', qStamm.A2C('zus_iban5'));
oXML.CloseElement; // ram:PayeePartyCreditorFinancialAccount
oXML.CloseElement; // ram:SpecifiedTradeSettlementPaymentMeans
end;
nMWSTTotal := 0;
if (not empty(qRech.A2C('a_mwstschl1'))) then begin
oXML.OpenElement('ram:ApplicableTradeTax');
nMWST := qRech.A2F('a_net1') * (qRech.A2F('a_mwst1') / 100);
nMWSTTotal := nMWSTTotal + nMWST;
oXML.AddElement('ram:CalculatedAmount',_Format(nMWST)); // BR-46
oXML.AddElement('ram:TypeCode', 'VAT');
oXML.AddElement('ram:BasisAmount', _Format(qRech.A2F('a_net1'))); // BR-45
oXML.AddElement('ram:CategoryCode', OBSMwstSchl_To_ZUGCategoryCode(qRech.A2C('a_art'))); // BR-47
oXML.AddElement('ram:RateApplicablePercent', _Format(qRech.A2F('a_mwst1'))); // BR-48
oXML.CloseElement; // ram:ApplicableTradeTax
end;
if (not empty(qRech.A2C('a_mwstschl2'))) then begin
oXML.OpenElement('ram:ApplicableTradeTax');
nMWST := qRech.A2F('a_net2') * (qRech.A2F('a_mwst2') / 100);
nMWSTTotal := nMWSTTotal + nMWST;
oXML.AddElement('ram:CalculatedAmount',_Format(nMWST)); // BR-46
oXML.AddElement('ram:TypeCode', 'VAT');
oXML.AddElement('ram:BasisAmount', _Format(qRech.A2F('a_net2'))); // BR-45
oXML.AddElement('ram:CategoryCode', OBSMwstSchl_To_ZUGCategoryCode(qRech.A2C('a_art'))); // BR-47
oXML.AddElement('ram:RateApplicablePercent', _Format(qRech.A2F('a_mwst2'))); // BR-48
oXML.CloseElement; // ram:ApplicableTradeTax
end;
if (not empty(qRech.A2C('a_mwstschl3'))) then begin
oXML.OpenElement('ram:ApplicableTradeTax');
nMWST := qRech.A2F('a_net3') * (qRech.A2F('a_mwst3') / 100);
nMWSTTotal := nMWSTTotal + nMWST;
oXML.AddElement('ram:CalculatedAmount',_Format(nMWST)); // BR-46
oXML.AddElement('ram:TypeCode', 'VAT');
oXML.AddElement('ram:BasisAmount', _Format(qRech.A2F('a_net3'))); // BR-45
oXML.AddElement('ram:CategoryCode', OBSMwstSchl_To_ZUGCategoryCode(qRech.A2C('a_art'))); // BR-47
oXML.AddElement('ram:RateApplicablePercent', _Format(qRech.A2F('a_mwst3'))); // BR-48
oXML.CloseElement; // ram:ApplicableTradeTax
end;
oXML.OpenElement('ram:SpecifiedTradePaymentTerms');
// Fälligkeitsdatum
oXML.OpenElement('ram:DueDateDateTime');
oXML.AddAttrElement('udt:DateTimeString','format', '102', DToS(qRech.A2D('a_faellig'))); // Datum // BT-9, BR-CO-25
oXML.CloseElement; // ram:DueDateDateTime
oXML.CloseElement; // ram:SpecifiedTradePaymentTerms
oXML.OpenElement('ram:SpecifiedTradeSettlementHeaderMonetarySummation');
oXML.AddElement('ram:LineTotalAmount', _Format(qRech.A2F('a_nbetrag'))); // BR-12
oXML.AddElement('ram:TaxBasisTotalAmount', _Format(qRech.A2F('a_nbetrag'))); // BR-13
oXML.AddAttrElement('ram:TaxTotalAmount','currencyID','EUR',_Format(nMWSTTotal)); // BR-53
oXML.AddElement('ram:GrandTotalAmount', _Format(qRech.A2F('a_bbetrag'))); // BR-14
oXML.AddElement('ram:DuePayableAmount', _Format(qRech.A2F('a_bbetrag'))); // BR-15
oXML.CloseElement(); // ram:SpecifiedTradeSettlementHeaderMonetarySummation
oXML.CloseElement; // ram:ApplicableHeaderTradeSettlement
oXML.CloseElement; // rsm:SupplyChainTradeTransaction
oXML.CloseElement; // rsm:CrossIndustryInvoice
end;