إنفويسي

تصميم واجهة فوترة إلكترونية متعددة الأقاليم: دروس من الميدان

إن كنت تبني بنية تحتية تخدم دول الإصدار المسبق ودول التدقيق اللاحق معاً، فأمامك فرصة واحدة لضبط التجريدات. إليك ما تعلمناه بالطريقة الصعبة.

Invocie Team · ٤ ديسمبر ٢٠٢٥ · 6 دقائق قراءة


بنينا محرك الامتثال في إنفويسي ليعالج الإصدار المسبق في الشرق الأوسط، وبيبول في الاتحاد الأوروبي، والتدقيق اللاحق العالمي من قاعدة كود واحدة. واحتاجت المعمارية إلى ثلاث جولات حتى استقرت. هذه القرارات التصميمية هي التي بقيت.

1. نمط الاستراتيجية على مستوى الدولة لا الإقليم

الإقليم تعريف فضفاض. السعودية (إصدار مسبق، زاتكا، 15%) والإمارات (تشغيلي بيني، الهيئة الاتحادية، 5%) تنتميان إلى "الشرق الأوسط" لكنهما مختلفتان معمارياً. نحن نوجّه بناءً على رمز الدولة ISO أولاً، ثم الإقليم، مع استراتيجية افتراضية في النهاية.

function pickStrategy(t: { country_code: string; tax_region: string }) {
  if (MENA.includes(t.country_code)) return new MENAStrategy();
  if (EU.includes(t.country_code))   return new EUStrategy();
  if (t.tax_region === "MENA") return new MENAStrategy();
  if (t.tax_region === "EU")   return new EUStrategy();
  return new DefaultStrategy();
}

2. أرقام Decimal دائماً، لا floats أبداً

نستخدم BigInt مع تحجيم نقطة ثابتة (10000x لدقة 4 منازل عشرية) في المسارات الحساسة للأداء، وdecimal.js حيث تكون SDK أكثر ودّاً. النوع الوحيد الممنوع للقيم النقدية هو number في JavaScript — اصطدنا ثلاثة أخطاء تقريب قبل الإنتاج تتبّعناها إلى استدعاء Number() شارد.

3. غير متزامن افتراضياً، متزامن استثناءً

مسار HTTP الذي ينشئ فاتورة لا يتوقّف أبداً عند الواجهة الحكومية. يكتب إلى قاعدة البيانات، يضع مهمة في الطابور، ويعيد 201. ويعالج العامل (worker) الإرسال للحكومة مع إعادة محاولة (تباطؤ أُسّي، 6 محاولات بحدّ أقصى، مع تشويش). هذا يعزل واجهة المستخدم عن زمن الاستجابة الحكومي، ويُبقي إعادة المحاولة آمنة حتى حين تواجه زاتكا يوماً سيئاً.

4. افصل النموذج القانوني عن صيغة الإرسال

نوع Invoice الداخلي لدينا واحد بصرف النظر عن الدولة. كل buildArtifacts() في الاستراتيجية يحوّله إلى صيغة الإرسال الخاصة بالدولة (TLV QR، أو UBL 2.1 XML، أو JSON افتراضي). النموذج القانوني لا يعرف XML أبداً، وXML لا يخرج من الاستراتيجية. هذا يجعل إضافة IRP الهندي لاحقاً تغييراً في ملف واحد.

5. التسجيل جزء من العقد

كل تعامل حكومي يكتب صفاً في ComplianceLog بسلسلة prev_hash → hash. حين يأتي المدققون — وسيأتون — لا تريد إعادة بناء ما حدث من سجلات التطبيق. صفّ قاعدة البيانات هو الإيصال.


قراءات ذات صلة

أصدر فواتير متوافقة في كل سوق

زاتكا، الهيئة الاتحادية، بيبول، والنموذج اللاحق عالمياً — بواجهة واحدة.

تواصل مع فريقنا