E-Rechnung in Panama aus SAP Business One: NUC-JSON-Feldzuordnung und DGI-Ablehnungen

Von Zain Abbas, Kodenova · Aktualisiert am

Kurz gesagtUm eine elektronische Rechnung in Panama aus SAP Business One über den PAC Digifact auszustellen, senden Sie pro Beleg ein NUC-JSON: Header (DocType, IssuedDateTime, NumeroDF, CodigoSeguridad), Seller, Buyer (TipoReceptor, RUC, DV, CodUbi), Items mit ITBMS-Code 00/01/02/03 für 0/7/10/15 % sowie Payments. Das meiste davon liegt in SAP B1 bereits in OINV, INV1, OCRD und OITM. Sie ergänzen einige benutzerdefinierte Felder (Empfängertyp, DV, Ortscode, CPBS) und speichern CUFE, Protokoll und QR-URL, die zurückkommen.

Um eine elektronische Rechnung in Panama (Factura Electrónica, FE) aus SAP Business One über den PAC Digifact auszustellen, senden Sie pro Rechnung oder Gutschrift ein NUC-JSON-Dokument. Die meisten Daten liegen bereits in OINV, INV1, OCRD und OITM. Was SAP B1 standardmäßig nicht hat, sind Empfängertyp, Prüfziffer des RUC (DV), Ortscode (CodUbi) und der CPBS-Artikelcode; diese werden zu benutzerdefinierten Feldern. Der PAC antwortet mit einem CUFE, einem Autorisierungsprotokoll und einer QR-URL, die Sie in den Beleg zurückschreiben.

Dieser Leitfaden beschreibt die Zuordnung, die ich in meinem SAP-Business-One-Add-on für Panama verwende. Getestet wurde sie am 27. Oktober 2026 in einem SAP-B1-10-Mandanten auf SQL Server gegen die Sandbox von Digifact: 34 Szenarien, von einer Endkundenrechnung mit 7 % bis zu einer Rechnung mit 105 Positionen, Exporte, zona franca, Gutschriften und Stornierungen. Den kaufmännischen Überblick finden Sie unter E-Rechnung in Panama für SAP Business One.

Wie läuft der Weg von SAP Business One zur DGI?

  1. Der Benutzer legt in SAP B1 wie gewohnt eine Ausgangsrechnung (Objekt 13) oder Ausgangsgutschrift (Objekt 14) an.
  2. Das Add-on liest den Beleg, prüft die DGI-Regeln, die sich lokal prüfen lassen, und erzeugt das NUC-JSON.
  3. Es sendet das JSON per POST an Digifact (/api/v2/transform/nuc_json, Query-Parameter TAXID, FORMAT, USERNAME). Digifact wandelt es in das DGI-XML um, signiert es und holt die Autorisierung ein.
  4. Die Antwort enthält CUFE, Protokoll, Autorisierungsdatum und QR-URL. Das Add-on schreibt sie in benutzerdefinierte Felder an OINV/ORIN und hängt XML und PDF an den Beleg an.

Zwei Designentscheidungen haben mir den meisten Ärger erspart:

  • Eine Registerzeile pro Beleg (eine benutzerdefinierte Tabelle, @FE_PA_DOC, mit dem Schlüssel 13-<DocEntry> oder 14-<DocEntry>). Zwei Arbeitsplätze, die gleichzeitig Belege anlegen, können so nie dieselbe Rechnung zweimal senden.
  • Erst abfragen, dann erneut senden. Ist beim Senden ein Timeout aufgetreten, fragt das Add-on zuerst bei Digifact nach, ob diese NumeroDF bereits existiert, und sendet erst dann erneut. Im Test lieferte ein Klick auf „Reintentar“ bei einer bereits autorisierten Rechnung denselben CUFE und sendete nichts.

Welche SAP-B1-Felder entsprechen welchen NUC-JSON-Feldern?

Das NUC-JSON unterscheidet Groß- und Kleinschreibung. Buyer.TaxID funktioniert, buyer.taxid nicht. Viele Werte stehen in Listen aus { "Name": ..., "Value": ... }-Objekten statt in einfachen Eigenschaften – das ist der erste Stolperstein für alle, die von FEL Guatemala oder DTE El Salvador kommen.

NUC-JSON-FeldBedeutungHerkunft in SAP B1
Header.DocType01 Rechnung, 03 Export, 04/06 Gutschrift, 05/07 Belastungsanzeige, 08, 09, 10Objekttyp (13/14), DocSubType = 'DN' für Belastungsanzeigen, plus ein Beleg-UDF für 02/08/09/10
Header.IssuedDateTimeAusstellungsdatum und -uhrzeit, 2026-10-27T14:23:00-05:00Beim Senden ermittelt und in einem UDF gespeichert (U_FE_FechaEmi). Gutschriften brauchen den Wert später
AdditionalIssueDocInfo → NumeroDF10-stellige Fiskalnummer, mit Nullen aufgefüllt, beginnt nie neuEigener Zähler pro Fakturierungspunkt. Verwenden Sie DocNum nicht ungeprüft, wenn Sie mehrere Nummernkreise haben
PtoFactDFFakturierungspunkt, 3 Ziffern, nicht 000Einstellung im Add-on
CodigoSeguridadZufällige 9 Ziffern, Teil des CUFE, ungleich NumeroDFPro Beleg erzeugt
Seller.TaxID, TaxIDType, DigitoVerificadorRUC des Ausstellers, 1 natürliche / 2 juristische Person, DVEinstellungen im Add-on (ein Mandant, ein RUC)
Seller.BranchInfo.Code0000 Hauptsitz, ab 0001 FilialenEinstellung im Add-on
Buyer.TaxIDRUC, oder CF für consumidor final, oder EXTRANJEROOCRD.LicTradNum
TipoReceptor01 contribuyente, 02 consumidor final, 03 gobierno, 04 extranjeroGP-UDF U_FE_TipoRec
Buyer.TaxIDType / DigitoVerificadorNatürliche oder juristische Person, DV des RUCGP-UDFs U_FE_TipoRuc, U_FE_DV
CodUbiCode für Provinz-Distrikt-CorregimientoGP-UDF U_FE_CodUbi
Buyer.Name, E-Mail, TelefonName und Kontakt des EmpfängersOCRD.CardName, E_Mail, Phone1
Items[].Description, QtyPositionstext und MengeINV1.Dscription, Quantity
Items[].PriceStückpreis vor RabattINV1.PriceBefDi
Discounts.Discount[].AmountRabatt pro Einheit in Balboas, kein ProzentsatzPriceBefDi - Price
Codes → CodCPBSabr / CodCPBScmpCPBS-Code für Waren und Dienstleistungen (2 und 4 Stellen)Artikel-UDF U_FE_CPBS an OITM
Taxes.Tax[].CodeITBMS 00 = 0 %, 01 = 7 %, 02 = 10 %, 03 = 15 %Aus INV1.VatPrcnt
Taxes.Tax[].AmountSteuerbetrag der PositionINV1.VatSum (oder VatSumFrgn)
Totals.TotalItemPositionssumme inklusive SteuerLineTotal + VatSum
PaymentsTyp 02 ohne Zahlungsziel; mit Zahlungsziel Typ 01 plus eine PLAZO-Zeile mit FälligkeitsdatumTage aus OCTG zum GroupNum, DocDueDate

Zwei Details aus den Tests, die die Spezifikation nicht deutlich macht:

  • Positionsbeträge, nicht Kopfbeträge. Bilden Sie jede Summe aus den Positionen und lassen Sie den Kopf deren Summe sein. Bei Rechnungen mit mehreren Steuersätzen (0, 7 und 10 % in einem Beleg) und bei einer Rechnung mit 105 Positionen hatte ich null Abweichungen, weil ich jede Position zuerst auf zwei Nachkommastellen gerundet und dann addiert habe.
  • Mandanten mit Fremdwährung. Ist die Hauswährung des Mandanten nicht USD, stehen DocTotal, LineTotal und VatSum in Hauswährung. Die E-Rechnung muss die Belegwährung enthalten, lesen Sie also stattdessen DocTotalFC, TotalFrgn und VatSumFrgn. Mein Testmandant hatte GBP als Hauswährung – so ist das aufgefallen.

Welche benutzerdefinierten Felder brauchen Sie in SAP Business One?

Eingaben (vom Benutzer oder im GP-Stamm gepflegt): U_FE_TipoRec, U_FE_TipoRuc, U_FE_DV, U_FE_CodUbi an OCRD; U_FE_CPBS an OITM; U_FE_Incoterm, U_FE_PuertoEmb und U_FE_TipoDoc am Beleg.

Ausgaben (vom Add-on an OINV und ORIN geschrieben): Status, CUFE, Protokoll, Autorisierungsdatum, QR-URL, NumeroDF, gesendetes Ausstellungsdatum und -uhrzeit, Fehlertext, Anzahl der Versuche und Stornogrund. Die QR-URL hat etwa 560 Zeichen; sie braucht also ein Memofeld, kein alphanumerisches Feld mit 254 Zeichen.

Viele Kunden haben aus einer früheren Lokalisierung bereits eigene Felder für RUC-Typ oder DV. In meiner Einstellungsmaske können Sie jeden Schlüssel auf ein vorhandenes Feld verweisen lassen, statt ein Duplikat anzulegen. Was Sie auch tun: Legen Sie die Felder über die DI API oder die Oberfläche an, nie mit ALTER TABLE.

Vor dem Produktivstart führe ich diese Prüfung aus. Sie listet die Stammdaten auf, die abgelehnt würden, bevor überhaupt etwas beim PAC ankommt. Zuerst die SQL-Server-Version:

-- Customers that will fail: contribuyente/gobierno without RUC, DV or location code
SELECT C.CardCode, C.CardName, C.LicTradNum, C.U_FE_TipoRec, C.U_FE_DV, C.U_FE_CodUbi
FROM OCRD C
WHERE C.CardType = 'C'
  AND ISNULL(C.U_FE_TipoRec, '01') IN ('01', '03')
  AND (ISNULL(C.LicTradNum, '') = '' OR ISNULL(C.U_FE_DV, '') = '' OR ISNULL(C.U_FE_CodUbi, '') = '');

-- Items sold in the last 90 days without a CPBS code
SELECT DISTINCT L.ItemCode, I.ItemName
FROM INV1 L
INNER JOIN OINV H ON H.DocEntry = L.DocEntry
INNER JOIN OITM I ON I.ItemCode = L.ItemCode
WHERE H.DocDate >= DATEADD(DAY, -90, GETDATE())
  AND ISNULL(I.U_FE_CPBS, '') = '';

Die SAP-HANA-Version (Bezeichner in Anführungszeichen, IFNULL, ADD_DAYS):

SELECT C."CardCode", C."CardName", C."LicTradNum", C."U_FE_TipoRec", C."U_FE_DV", C."U_FE_CodUbi"
FROM "OCRD" C
WHERE C."CardType" = 'C'
  AND IFNULL(C."U_FE_TipoRec", '01') IN ('01', '03')
  AND (IFNULL(C."LicTradNum", '') = '' OR IFNULL(C."U_FE_DV", '') = '' OR IFNULL(C."U_FE_CodUbi", '') = '');

SELECT DISTINCT L."ItemCode", I."ItemName"
FROM "INV1" L
INNER JOIN "OINV" H ON H."DocEntry" = L."DocEntry"
INNER JOIN "OITM" I ON I."ItemCode" = L."ItemCode"
WHERE H."DocDate" >= ADD_DAYS(CURRENT_DATE, -90)
  AND IFNULL(I."U_FE_CPBS", '') = '';

Wenn Sie heute nur SQL-Server-Abfragen haben, übernimmt der SQL-zu-HANA-Konverter die meisten Dialektänderungen.

Wie verweisen Gutschriften auf die ursprüngliche Rechnung?

Eine Ausgangsgutschrift in SAP B1, die auf einer Rechnung basiert (RIN1.BaseType = 13, BaseEntry = <DocEntry der Rechnung>), wird zum DGI-Typ 04. Sie muss in AdditionalInfo drei Werte enthalten: den Namen des Ausstellers (NombEmRef), Ausstellungsdatum und -uhrzeit der ursprünglichen E-Rechnung (FechaDFRef) und deren CUFE (CUFERef). Deshalb muss die Ausstellungszeit beim Senden der Rechnung gespeichert werden. Aus dem DocDate lässt sie sich später nicht rekonstruieren.

Eine Gutschrift ohne Basisbeleg oder mit Bezug auf eine Rechnung von vor Ihrem Produktivstart ist eine generische Gutschrift, Typ 06, ohne Referenz. Welche Gutschriften eine Basisrechnung haben, sehen Sie in der Tabelle ORIN (Ausgangsgutschrift) und ihren RIN1-Positionen.

Die DGI-Regeln, die mich am härtesten getroffen haben und die ich heute alle vor dem Senden in SAP prüfe:

DGI-RegelBedeutungPrüfung in SAP B1
1710Die Gutschrift muss denselben Empfänger haben wie die RechnungDen Käufer aus dem JSON übernehmen, das für die Rechnung gesendet wurde, nicht aus dem heutigen GP-Stamm
1711Gutschrift höher als die RechnungMit der Summe der Basisrechnung vergleichen
1714Gutschrift mehr als 180 Tage nach der Rechnung ausgestelltDocDate der Gutschrift gegenüber der Rechnung
1717Alle Gutschriften zusammen übersteigen Rechnung plus BelastungsanzeigenDie bereits autorisierten Gutschriften summieren, die über Basispositionen in RIN1/INV1 verknüpft sind
1718Gutschrift zu einer stornierten (anulada) RechnungStatus der Basisrechnung
1720Für die referenzierte Rechnung ist kein Ausstellungsdatum/-uhrzeit gespeichertDas Feld FechaEmi der Rechnung

Eine Gutschrift zu einer Basisrechnung, die noch nicht autorisiert ist, ist kein Fehler. Mein Add-on hält sie zurück, bis die Rechnung ihren CUFE hat, und sendet sie dann.

Was verursacht die häufigsten Ablehnungen bei Panama FE?

Aus den Sandbox-Tests, in der Reihenfolge, in der sie mir begegnet sind:

  • Behörde als Empfänger (03) mit normalem RUC. Regel 1604: Der RUC muss in der DGI-Tabelle der Behörden (Tabla 30) stehen. Ist der Kunde nicht auf dieser Liste, verwenden Sie Empfängertyp 01. Nach Korrektur des RUC hat ein einfacher erneuter Versuch dieselbe Rechnung autorisiert.
  • Consumidor final mit dem RUC einer juristischen Person. Regel 1621: Ein juristischer RUC (TaxIDType 2) kann nicht Empfängertyp 02 sein.
  • Export oder Auslandsgeschäft ohne INCOTERM. Bei den Typen 03 und 10 meldete die Sandbox, dass die Lieferbedingungen (CondEntr) fehlten. Erfassen Sie den INCOTERM in einem Beleg-UDF und senden Sie ihn in AdditionalInfo.
  • Das Zeichen < in einer Artikelbeschreibung. Eine Testrechnung kam mit „XSLT failed“ zurück, weil der Positionstext ein < enthielt. Maskieren oder ersetzen Sie es vor dem Senden. ñ, á, &, " und > wurden alle akzeptiert, auch ein Kunde namens „Compañía Ñandú & Hijos“.
  • Rabatt auf Belegebene. OINV.DiscSum hat in der Positionsstruktur keinen sauberen Platz. Mein Add-on sperrt einen Beleg, der noch einen Belegrabatt hat, und verlangt stattdessen Positionsrabatte. Dasselbe Belegrabatt-Problem verzerrt auch Umsatzberichte, siehe warum Umsatzsummen in SAP B1 nicht übereinstimmen.

Wie stornieren (anular) Sie eine E-Rechnung aus SAP Business One?

Die Stornierung geht an den Endpunkt CancelFePA von Digifact, mit RUC des Ausstellers, CUFE, einem Grund (Motivo) und dem Benutzer. Zwei Dinge habe ich in der Testumgebung gemessen:

  1. Direkt nach der Autorisierung scheitert die Stornierung mit {"Codigo":9019,"Anulado":false,"Mensaje":"Anulacion incorrecta. Verifique si el CUFE pertenece a una FE existente"}. Drei bis acht Minuten später wurde derselbe Aufruf angenommen. Mein Add-on versucht es einmal pro Minute erneut, statt dem Benutzer einen Fehler anzuzeigen.
  2. Kurze Gründe scheitern mit demselben Fehler 9019. Zwanzig Zeichen oder weniger wurden immer abgelehnt, 25 oder mehr immer angenommen, obwohl das technische Merkblatt der DGI 15 bis 1000 Zeichen zulässt. Ich erzwinge im Formular mindestens 25 Zeichen.

In SAP B1 sollte Daten > Stornieren bei einer autorisierten Rechnung zuerst bei der DGI stornieren. Lehnt die DGI ab, sperren Sie die Stornierung in SAP – sonst zeigt SAP die Rechnung als storniert, während die DGI sie weiterhin als gültig führt. Eine Rechnung, die die DGI nie erreicht hat, kann direkt in SAP storniert werden.

Wenn Sie das selbst als Add-on entwickeln: Die Muster für Ereignisbehandlung, Paketierung und Buchen über die DI API stehen in meinem Leitfaden zur Add-on-Entwicklung für SAP Business One, die Felder der oben genannten Tabellen in der SAP-B1-Tabellenreferenz.

Was ist noch offen?

Notfallbetrieb (TipoEmision 02/04) und andere Währungen als USD sind noch nicht in meinem Add-on. Belastungsanzeigen (05 und 07) wurden in der Sandbox autorisiert, aber ein Mandant mit britischer Lokalisierung kann sie nicht über die DI API buchen (DocumentSubType = DN wird abgelehnt). Testen Sie sie deshalb in einem Mandanten mit Lokalisierung für Panama oder Lateinamerika.

Wenn Sie SAP Business One in Panama betreiben und FE über Digifact benötigen, schildern Sie mir Ihre Umgebung. Dieselbe Art von Integration habe ich für FEL Guatemala, DTE El Salvador, SRI Ecuador und ZATCA Saudi-Arabien umgesetzt.

Quellen

Passende Leistungen

FAQ

Häufige Fragen

Brauche ich in Panama einen PAC, um aus SAP Business One elektronische Rechnungen auszustellen?

Für eine ERP-Integration praktisch ja. SAP Business One kommuniziert nicht direkt mit der DGI. Der Beleg geht an einen PAC (Proveedor de Autorización Calificado), der ihn prüft, autorisiert und an die DGI weiterleitet. Mein Add-on nutzt den PAC Digifact und dessen NUC-JSON-API.

Welche SAP-Business-One-Belege werden zu welchen DGI-Dokumenttypen?

Eine Ausgangsrechnung ist Typ 01 (oder 03 Export, 08 zona franca, 09 reembolso, 10 operación extranjera, wenn Sie das festlegen). Eine Ausgangsgutschrift, die auf einer elektronisch ausgestellten Rechnung basiert, ist Typ 04; ohne referenzierte Rechnung ist sie Typ 06. Belastungsanzeigen sind 05 und 07.

Warum verweigert die DGI die Stornierung einer Rechnung, die ich gerade ausgestellt habe?

In der Testumgebung von Digifact antwortete CancelFePA in den ersten Minuten nach der Autorisierung mit Code 9019, ebenso immer dann, wenn der Grund (Motivo) 20 Zeichen oder kürzer war. Etwa 3 Minuten zu warten und einen Grund mit 25 oder mehr Zeichen anzugeben, hat jedes Mal funktioniert.

Bereit für den Start?

Sagen Sie uns, was Sie brauchen. Sie erhalten eine klare technische Antwort, einen festen Leistungsumfang und einen Preis, in der Regel innerhalb von 24 Stunden.