الفوترة الإلكترونية في بنما من SAP Business One: ربط حقول NUC-JSON ورفض DGI
بقلم زين عباس, كودينوفا · آخر تحديث
لإصدار فاتورة إلكترونية بنمية (Factura Electrónica، FE) من SAP Business One عبر مزوّد الاعتماد Digifact (PAC)، ترسل مستند NUC-JSON واحدًا لكل فاتورة أو إشعار دائن. معظم البيانات موجودة أصلًا في OINV و INV1 و OCRD و OITM. أما ما لا يوفره SAP B1 جاهزًا فهو نوع المستلم، ورقم التحقق من RUC (DV)، ورمز الموقع (CodUbi)، ورمز الصنف CPBS، لذلك تصبح هذه حقول مستخدم. يرد مزوّد الاعتماد برمز CUFE وبروتوكول اعتماد ورابط QR، وتكتبها أنت مرة أخرى على المستند.
هذا الدليل هو الربط الذي أستخدمه في إضافتي لـ SAP Business One في بنما. اختُبر في 27 أكتوبر 2026 على شركة SAP B1 10 تعمل على SQL Server مقابل بيئة Digifact التجريبية: 34 سيناريو، من فاتورة مستهلك بنسبة 7 % إلى فاتورة من 105 أسطر، والتصدير، والمنطقة الحرة، والإشعارات الدائنة، والإلغاءات. للنظرة التجارية العامة، راجع الفوترة الإلكترونية في بنما لـ SAP Business One.
كيف يسير التدفق من SAP Business One إلى DGI؟
- يضيف المستخدم فاتورة مبيعات (الكائن 13) أو إشعارًا دائنًا للمبيعات (الكائن 14) في SAP B1 كالمعتاد.
- تقرأ الإضافة المستند، وتتحقق من قواعد DGI التي يمكن التحقق منها محليًا، وتبني ملف NUC-JSON.
- ترسل ملف JSON إلى Digifact (
/api/v2/transform/nuc_json، مع معاملات الاستعلامTAXIDوFORMATوUSERNAME). يحوّله Digifact إلى XML بصيغة DGI، ويوقّعه، ويحصل على الاعتماد. - يحمل الرد CUFE والبروتوكول وتاريخ الاعتماد ورابط QR. تكتبها الإضافة في حقول مستخدم على
OINV/ORINوترفق ملفي XML و PDF بالمستند.
قراران في التصميم وفّرا عليّ معظم المتاعب:
- صف سجل واحد لكل مستند (جدول مستخدم،
@FE_PA_DOC، مفتاحه13-<DocEntry>أو14-<DocEntry>). لا يمكن لجهازين يضيفان مستندات في الوقت نفسه أن يرسلا الفاتورة نفسها مرتين. - الاستعلام قبل إعادة الإرسال. إذا انتهت مهلة الإرسال، تسأل الإضافة Digifact أولًا ما إذا كان رقم NumeroDF هذا موجودًا بالفعل، ثم ترسل مجددًا فقط بعد ذلك. في الاختبار، الضغط على «Reintentar» (إعادة المحاولة) لفاتورة معتمدة بالفعل أعاد CUFE نفسه ولم يرسل شيئًا.
أي حقول SAP B1 تُربط بأي حقول NUC-JSON؟
صيغة NUC-JSON حساسة لحالة الأحرف: Buyer.TaxID يعمل، و buyer.taxid لا يعمل. كثير من القيم توضع في قوائم من كائنات { "Name": ..., "Value": ... } بدل خصائص عادية، وهذا أول ما يربك القادمين من FEL في غواتيمالا أو DTE في السلفادور.
| حقل NUC-JSON | ما هو | مصدره في SAP B1 |
|---|---|---|
Header.DocType | 01 فاتورة، 03 تصدير، 04/06 إشعار دائن، 05/07 إشعار مدين، 08، 09، 10 | نوع الكائن (13/14)، و DocSubType = 'DN' للإشعارات المدينة، إضافة إلى حقل مستخدم على المستند للأنواع 02/08/09/10 |
Header.IssuedDateTime | تاريخ ووقت الإصدار، 2026-10-27T14:23:00-05:00 | يؤخذ وقت الإرسال ويُخزَّن في حقل مستخدم (U_FE_FechaEmi). تحتاجه الإشعارات الدائنة لاحقًا |
AdditionalIssueDocInfo ← NumeroDF | الرقم الضريبي من 10 خانات، مكمَّل بالأصفار، ولا يُعاد ضبطه أبدًا | عدّاد خاص لكل نقطة فوترة. لا تعِد استخدام DocNum دون تفكير إذا كانت لديك عدة سلاسل ترقيم |
PtoFactDF | نقطة الفوترة، 3 خانات، وليست 000 | إعداد في الإضافة |
CodigoSeguridad | 9 أرقام عشوائية، جزء من CUFE، ولا تساوي NumeroDF | يُولَّد لكل مستند |
Seller.TaxID و TaxIDType و DigitoVerificador | RUC المُصدِر، 1 شخص طبيعي / 2 شخص اعتباري، و DV | إعدادات في الإضافة (شركة واحدة، RUC واحد) |
Seller.BranchInfo.Code | 0000 المقر الرئيسي، و0001 فما فوق للفروع | إعداد في الإضافة |
Buyer.TaxID | رقم RUC، أو CF للمستهلك النهائي (consumidor final)، أو EXTRANJERO | OCRD.LicTradNum |
TipoReceptor | 01 مكلَّف (contribuyente)، 02 مستهلك نهائي، 03 جهة حكومية، 04 أجنبي | حقل مستخدم لشريك الأعمال U_FE_TipoRec |
Buyer.TaxIDType / DigitoVerificador | شخص طبيعي أو اعتباري، و DV لرقم RUC | حقلا مستخدم لشريك الأعمال U_FE_TipoRuc و U_FE_DV |
CodUbi | رمز المقاطعة-المنطقة-البلدية (corregimiento) | حقل مستخدم لشريك الأعمال U_FE_CodUbi |
Buyer.Name والبريد والهاتف | اسم المستلم وبيانات الاتصال | OCRD.CardName و E_Mail و Phone1 |
Items[].Description و Qty | نص السطر والكمية | INV1.Dscription و Quantity |
Items[].Price | سعر الوحدة قبل الخصم | INV1.PriceBefDi |
Discounts.Discount[].Amount | الخصم لكل وحدة بالبالبوا، وليس نسبة مئوية | PriceBefDi - Price |
Codes ← CodCPBSabr / CodCPBScmp | رمز السلع والخدمات CPBS (خانتان و4 خانات) | حقل مستخدم للصنف U_FE_CPBS على OITM |
Taxes.Tax[].Code | ITBMS 00 = 0 %، 01 = 7 %، 02 = 10 %، 03 = 15 % | من INV1.VatPrcnt |
Taxes.Tax[].Amount | مبلغ ضريبة السطر | INV1.VatSum (أو VatSumFrgn) |
Totals.TotalItem | إجمالي السطر شاملًا الضريبة | LineTotal + VatSum |
Payments | النوع 02 دون شروط ائتمان؛ ومع شروط ائتمان النوع 01 إضافة إلى سطر PLAZO بتاريخ الاستحقاق | أيام OCTG لقيمة GroupNum، و DocDueDate |
تفصيلتان من الاختبار لا توضحهما المواصفات:
- مبالغ الأسطر، لا مبالغ الرأس. ابنِ كل إجمالي من الأسطر واجعل الرأس مجموعها. لم يظهر لدي أي عدم تطابق في الفواتير متعددة النسب (0 و7 و10 % في مستند واحد) ولا في فاتورة من 105 أسطر، بتقريب كل سطر إلى خانتين عشريتين أولًا ثم الجمع.
- الشركات بعملة أجنبية. إذا لم تكن العملة المحلية للشركة هي الدولار الأمريكي، فإن
DocTotalوLineTotalوVatSumتكون بالعملة المحلية. يجب أن تحمل الفاتورة الإلكترونية عملة المستند، فاقرأDocTotalFCوTotalFrgnوVatSumFrgnبدلًا منها. كانت العملة المحلية لشركة الاختبار لدي الجنيه الإسترليني، وهكذا ظهرت المشكلة.
ما حقول المستخدم التي تحتاجها في SAP Business One؟
المدخلات (يعبّئها المستخدم أو البيانات الرئيسية لشريك الأعمال): U_FE_TipoRec و U_FE_TipoRuc و U_FE_DV و U_FE_CodUbi على OCRD؛ و U_FE_CPBS على OITM؛ و U_FE_Incoterm و U_FE_PuertoEmb و U_FE_TipoDoc على المستند.
المخرجات (تكتبها الإضافة على OINV و ORIN): الحالة، و CUFE، والبروتوكول، وتاريخ الاعتماد، ورابط QR، و NumeroDF، وتاريخ/وقت الإصدار المرسل، ونص الخطأ، وعدد المحاولات، وسبب الإلغاء. يبلغ رابط QR نحو 560 حرفًا، لذلك يحتاج حقلًا من نوع memo، لا حقلًا أبجديًا رقميًا من 254 حرفًا.
كثير من العملاء لديهم بالفعل حقول خاصة لنوع RUC أو DV من حزمة توطين سابقة. تتيح شاشة الإعدادات لدي توجيه كل مفتاح إلى حقل موجود بدل إنشاء حقل مكرر. ومهما فعلت، أنشئ الحقول عبر DI API أو الواجهة، ولا تستخدم ALTER TABLE أبدًا.
قبل الإطلاق أشغّل هذا الفحص. يسرد البيانات الرئيسية التي سترفض قبل أن يصل أي شيء إلى مزوّد الاعتماد. نسخة SQL Server أولًا:
-- 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, '') = '';
(الاستعلام الأول: العملاء الذين سيُرفضون، أي المكلَّفون أو الجهات الحكومية دون RUC أو DV أو رمز موقع. الثاني: الأصناف المباعة خلال آخر 90 يومًا دون رمز CPBS.)
نسخة SAP HANA (معرّفات مقتبسة، و 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", '') = '';
إذا كانت لديك استعلامات SQL Server فقط حاليًا، فإن محوّل SQL إلى HANA يتولى معظم تغييرات الصياغة.
كيف تشير الإشعارات الدائنة إلى الفاتورة الأصلية؟
الإشعار الدائن في SAP B1 المبني على فاتورة (RIN1.BaseType = 13 و BaseEntry = <DocEntry للفاتورة>) يصبح من نوع DGI 04. ويجب أن يحمل ثلاث قيم في AdditionalInfo: اسم المُصدِر (NombEmRef)، وتاريخ/وقت إصدار الفاتورة الإلكترونية الأصلية (FechaDFRef)، ورمز CUFE الخاص بها (CUFERef). لهذا يجب تخزين وقت الإصدار عند إرسال الفاتورة؛ فلا يمكنك إعادة بنائه لاحقًا من DocDate.
أما الإشعار الدائن دون مستند أساس، أو المبني على فاتورة سابقة لتاريخ إطلاقك، فهو إشعار عام من النوع 06 دون مرجع. يمكن معرفة الإشعارات الدائنة التي لها فاتورة أساس في جدول ORIN (الإشعار الدائن للمبيعات) وأسطره في RIN1.
قواعد DGI الأشد إيلامًا، وكلها أتحقق منها الآن في SAP قبل الإرسال:
| قاعدة DGI | ماذا تعني | الفحص في SAP B1 |
|---|---|---|
| 1710 | يجب أن يكون للإشعار المستلم نفسه الذي للفاتورة | خذ المشتري من ملف JSON الذي أُرسل للفاتورة، لا من البيانات الرئيسية لشريك الأعمال اليوم |
| 1711 | الإشعار الدائن أكبر من الفاتورة | قارن مع إجمالي فاتورة الأساس |
| 1714 | إشعار صادر بعد أكثر من 180 يومًا من الفاتورة | DocDate للإشعار مقابل الفاتورة |
| 1717 | مجموع الإشعارات الدائنة يتجاوز الفاتورة + الإشعارات المدينة | اجمع الإشعارات المعتمدة المرتبطة بالفعل عبر أسطر الأساس في RIN1/INV1 |
| 1718 | إشعار على فاتورة ملغاة (anulada) | حالة فاتورة الأساس |
| 1720 | الفاتورة المرجعية لا تحمل تاريخ/وقت إصدار مخزنًا | الحقل FechaEmi للفاتورة |
الإشعار الدائن على فاتورة أساس لم تُعتمد بعد ليس خطأً. تحتفظ به إضافتي حتى تحصل الفاتورة على CUFE ثم ترسله.
ما أسباب حالات الرفض الأكثر شيوعًا في فوترة بنما الإلكترونية؟
من اختبارات البيئة التجريبية، بالترتيب الذي واجهتها به:
- مستلم حكومي (03) برقم RUC عادي. القاعدة 1604: يجب أن يكون رقم RUC في جدول DGI للجهات الحكومية (Tabla 30). إذا لم يكن العميل في تلك القائمة، فاستخدم نوع المستلم 01. بعد تصحيح RUC، اعتُمدت الفاتورة نفسها بمجرد إعادة محاولة بسيطة.
- مستهلك نهائي برقم RUC لشخص اعتباري. القاعدة 1621: لا يمكن أن يكون RUC لشخص اعتباري (
TaxIDType2) من نوع المستلم 02. - تصدير أو عملية أجنبية دون INCOTERM. للنوعين 03 و10 ردّت البيئة التجريبية بأن شروط التسليم (
CondEntr) مفقودة. ضع INCOTERM في حقل مستخدم على المستند وأرسله فيAdditionalInfo. - الحرف
<في وصف الصنف. عادت إحدى فواتير الاختبار برسالة «XSLT failed» بسبب<في نص السطر. حوّله إلى رمز هروب أو استبدله قبل الإرسال. أماñوáو&و"و>فقُبلت كلها، بما في ذلك عميل باسم «Compañía Ñandú & Hijos». - الخصم على مستوى المستند. لا مكان واضحًا لقيمة
OINV.DiscSumفي بنية الأصناف. تمنع إضافتي المستند الذي ما زال يحمل خصم رأس وتطلب خصومات على الأسطر بدلًا منه. ومشكلة خصم الرأس نفسها تشوّه تقارير المبيعات أيضًا، راجع لماذا لا تتطابق إجماليات المبيعات في SAP B1.
كيف تلغي (anular) فاتورة إلكترونية من SAP Business One؟
يُرسل الإلغاء إلى نقطة CancelFePA لدى Digifact مع RUC المُصدِر، و CUFE، وسبب (Motivo)، والمستخدم. أمران قِستهما في بيئة الاختبار:
- مباشرة بعد الاعتماد يفشل الإلغاء بالرد
{"Codigo":9019,"Anulado":false,"Mensaje":"Anulacion incorrecta. Verifique si el CUFE pertenece a una FE existente"}. وبعد ثلاث إلى ثماني دقائق قُبل الطلب نفسه. تعيد إضافتي المحاولة مرة كل دقيقة بدل عرض خطأ للمستخدم. - الأسباب القصيرة تفشل بالرمز 9019 نفسه. عشرون حرفًا أو أقل رُفضت دائمًا، و25 حرفًا أو أكثر قُبلت دائمًا، رغم أن الورقة التقنية لـ DGI تسمح من 15 إلى 1000. أفرض حدًا أدنى من 25 حرفًا في النموذج.
في SAP B1، يجب أن يُلغي الأمر Data > Cancel (البيانات > إلغاء) على فاتورة معتمدة لدى DGI أولًا. إذا رفضت DGI، فامنع الإلغاء في SAP، وإلا سيعرض SAP الفاتورة ملغاة بينما تعتبرها DGI صالحة. أما الفاتورة التي لم تصل إلى DGI أبدًا فيمكن إلغاؤها في SAP مباشرة.
إذا كنت تبني هذا كإضافة بنفسك، فأنماط معالجة الأحداث والتغليف والترحيل عبر DI موجودة في دليل تطوير إضافات SAP Business One، وحقول الجداول المذكورة أعلاه موجودة في مرجع جداول SAP B1.
ما الذي لم يكتمل بعد؟
وضع الطوارئ (TipoEmision 02/04) والعملات غير الدولار الأمريكي ليسا في إضافتي بعد. اعتُمدت الإشعارات المدينة (05 و07) في البيئة التجريبية، لكن الشركة ذات التوطين البريطاني لا تستطيع ترحيلها من DI API (إذ يُرفض DocumentSubType = DN)، لذا اختبرها في شركة بتوطين بنما أو أمريكا اللاتينية.
إذا كنت تشغّل SAP Business One في بنما وتحتاج الفوترة الإلكترونية عبر Digifact، أخبرني عن إعداداتك. نفّذت النوع نفسه من التكامل لـ FEL في غواتيمالا، و DTE في السلفادور، و SRI في الإكوادور، و ZATCA في السعودية.
المصادر
خدمات ذات صلة
أسئلة شائعة
هل أحتاج إلى مزوّد اعتماد (PAC) لإصدار الفواتير الإلكترونية من SAP Business One في بنما؟
لتكامل مع نظام ERP، نعم من الناحية العملية. لا يتصل SAP Business One بـ DGI مباشرة. يذهب المستند إلى PAC (Proveedor de Autorización Calificado)، الذي يتحقق منه ويعتمده ويمرّره إلى DGI. تستخدم إضافتي مزوّد Digifact وواجهة NUC-JSON البرمجية الخاصة به.
أي مستندات SAP Business One تصبح أي أنواع مستندات لدى DGI؟
فاتورة المبيعات من النوع 01 (أو 03 للتصدير، و08 للمنطقة الحرة zona franca، و09 للاسترداد reembolso، و10 للعملية الأجنبية operación extranjera عندما تحدده). والإشعار الدائن للمبيعات المبني على فاتورة إلكترونية من النوع 04؛ ودون فاتورة مرجعية يكون 06. والإشعارات المدينة 05 و07.
لماذا ترفض DGI إلغاء فاتورة أصدرتها للتو؟
في بيئة الاختبار لدى Digifact، أعاد CancelFePA الرمز 9019 لبضع دقائق بعد الاعتماد، وكذلك كلما كان السبب (Motivo) 20 حرفًا أو أقل. الانتظار نحو 3 دقائق وكتابة سبب من 25 حرفًا أو أكثر نجح في كل مرة.
جاهز للبدء؟
أخبرنا بما تحتاجه. ستحصل على إجابة تقنية واضحة ونطاق عمل محدد وسعر ثابت، عادةً خلال 24 ساعة.
