التقنية المالية والمدفوعات الأدلة التقنية

التمويل الإسلامي Islamic Finance: المرابحة Murabaha وقيودها

كيف تعيش المرابحة داخل النظام المصرفي الأساسي من الوعد بالشراء إلى السداد المبكر، بقيودها في الدفتر العام ومختبر يعيد مثال البنك المركزي.

التمويل الإسلامي Islamic Finance: المرابحة Murabaha وقيودها

لنفرض أن أحد الأندية الرياضية التي تعمل مع الشركة الناشئة، والتي تتبعنا أموالها في مقالات هذا القسم، قرر أن يجدد صالة الأجهزة بمعدات ثمنها 50,000 ريال، وأن صاحب النادي طلب من البنك الشريك تمويلها على اثني عشر شهراً. وكانت الشركة الناشئة تعمل مع البنك على إضافة «طلب تمويل المعدات» إلى لوحة التحكم التي يستخدمها أصحاب الأندية، فجلس مهندسوها مع فريق البنك ليفهموا الحالات التي سيعرضونها للنادي. وتوقع الفريق شاشة بسيطة: طلب، ثم موافقة، ثم تحويل 50,000 ريال إلى حساب النادي، ثم أقساط. ولكن مهندس البنك رسم شيئاً مختلفاً: البنك لا يحول المال إلى النادي أصلاً، وإنما يشتري الأجهزة من المورد باسمه، ويتملكها ويقبضها، ثم يبيعها لصاحب النادي بثمن معلوم هو 50,928 ريالاً يدفعه على اثني عشر قسطاً، كل قسط 4,244 ريالاً. وأضاف جملة جعلت المطور يرفع رأسه: «إذا سجل النظام البيع قبل أن يسجل القبض، فالعقد نفسه فيه خلل، والنظام يجب أن يرفض هذا الترتيب كما يرفض قيداً غير متوازن».

هذا هو عقد المرابحة Murabaha، وهو من أكثر صيغ التمويل استخداماً في البنوك التي تعمل بأحكام الشريعة، وفي المملكة يعمل كثير من المنتجات المصرفية بهذه الصيغ. وفي مقال النظام المصرفي الأساسي ذكرنا أن المنتجات المتوافقة مع الشريعة تختلف في هيكلتها وقيودها المحاسبية عن المنتجات التقليدية، وتركنا التفاصيل لهذا المقال. وما يهمنا هنا هو ما يحتاجه المهندس: كيف تعيش المرابحة داخل النظام المصرفي الأساسي، وما الأحداث التي يسجلها النظام وبأي ترتيب، وما القيود التي تتولد في الدفتر العام، وكيف يوزع الربح على الأشهر، وكيف يحسب مبلغ السداد المبكر. ولن ندخل في الأحكام الفقهية، فهذه تقررها لجان الشريعة في البنوك والمعايير الشرعية، وإنما نأخذ تعريف العقد كما ينشره البنك المركزي، ونبني عليه النظام.

وسوف نناقش في هذا المقال ما يلي:

  • ما المرابحة كما يعرفها البنك المركزي، وكيف تختلف عن القرض، وأين تقف بين صيغ التمويل الأخرى.
  • دورة حياة العقد في النظام: الوعد، والشراء، والقبض، والبيع، والأقساط، ولماذا الترتيب والتواريخ جزء من صحة العقد.
  • القيود في الدفتر العام: المخزون، والذمة، والربح المؤجل، وإثبات الربح شهراً بشهر.
  • توزيع الربح بالرصيد المتناقص أم بالتساوي، وما يقوله دليل البنك المركزي لحساب السداد المبكر.
  • ما هو متاح للعامة من معيار هيئة المحاسبة والمراجعة للمؤسسات المالية الإسلامية AAOIFI للمرابحة.
  • مختبر في Python: دفتر قيد مزدوج بنفس طريقة المحفظة الرقمية، يعيد مثال البنك المركزي الرسمي هللة بهللة، ويرفض البيع قبل القبض.
  • التورق، والحوكمة الشرعية داخل البنك، والنوافذ الإسلامية، وما يعنيه كل ذلك لشركة تبني مع بنك.

المرابحة Murabaha: بيع وليس قرضاً

يعرف إطار إدارة مخاطر العمل المصرفي المتوافق مع أحكام الشريعة، الذي أصدره البنك المركزي بالتعميم رقم 45029601 بتاريخ 14 نوفمبر 2023، المرابحة بأنها عقد بيع يبيع فيه البنك للعميل أصلاً محدداً بثمن هو مجموع تكلفة الشراء وهامش ربح متفق عليه، ويذكر أن عقد المرابحة يمكن أن يسبقه وعد بالشراء من العميل. وفي هذا التعريف ثلاث كلمات يبنى عليها كل ما يحتاجه النظام: «بيع»، فالعلاقة بين البنك والعميل علاقة بائع ومشتر، لا مقرض ومقترض، و«أصل محدد»، فهناك سلعة معينة يملكها البنك قبل أن يبيعها، و«تكلفة وهامش ربح متفق عليه»، فالعميل يعرف ثمن الشراء الأصلي والربح، والثمن يثبت عند العقد ولا يتغير بعد ذلك.

وقد يتساءل البعض: إذا كان العميل في النهاية يدفع 50,928 ريالاً على سنة مقابل أجهزة ثمنها 50,000، فما الفرق التقني بين هذا والقرض بعائد؟ والإجابة أن الفرق يظهر في النظام قبل أن يظهر في الأرقام. ففي القرض يقيد البنك أصلاً واحداً هو مبلغ القرض، ويحسب عليه عائداً بحسب المدة والرصيد، وإذا تأخر العميل استمر العائد على الرصيد في التمويل التقليدي. أما في المرابحة فهناك سلعة تدخل دفتر البنك كأصل يملكه، ثم تخرج منه ببيع، ويحل محلها دين على العميل بثمن ثابت، والربح جزء من هذا الثمن معلوم من اليوم الأول، فلا يزيد الدين بالتأخر. وبالتالي يحتاج النظام أحداثاً لا يعرفها نظام القروض: شراء من مورد، وقبض للسلعة، وبيع، ويحتاج حسابات لا يحتاجها القرض: مخزون سلع المرابحة، وربح مؤجل لم يكتسب بعد.

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

المرابحة بين صيغ التمويل الأخرى

المرابحة ليست الصيغة الوحيدة، ونفس الإطار يعرف صيغاً أخرى تحتاج كل منها نموذجاً مختلفاً في النظام، والجدول التالي يلخص أشهرها كما يعرفها الإطار:

الصيغةتعريفها في الإطارما يعنيه للنظام
المرابحة Murabahaبيع أصل محدد بالتكلفة وهامش ربح متفق عليه، وقد يسبقه وعد بالشراءمخزون ثم ذمة بثمن ثابت وربح مؤجل
التورق Tawarruqشراء سلعة من بائع أو وسيط وبيعها للعميل مرابحة مؤجلة، ثم يبيعها العميل نقداً لطرف ثالث للحصول على السيولة، دون ربط بين العقديننفس قيود المرابحة، ومعها أحداث بيع العميل للسلعة
الإجارة Ijarahعقد إيجار منفعة أصل محدد لمدة متفق عليها مقابل أجرة محددةأصل مؤجر يبقى في دفتر البنك وأجرة دورية
الإجارة المنتهية بالتمليكإجارة مع وعد منفصل من المؤجر بتمليك الأصل للمستأجر في نهاية المدةأجرة دورية ثم حدث نقل الملكية
المشاركة Musharakahشراكة يساهم فيها الشركاء برأس المال، والأرباح بحسب الاتفاق والخسائر بنسبة رأس المالحصص تتغير وأرباح غير ثابتة

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

دورة حياة المرابحة في النظام

لنعد إلى طلب صاحب النادي، ولنتبع العقد في النظام من أول حدث إلى آخره، والصورة التالية تبين الأحداث بترتيبها:

خمس محطات من اليمين إلى اليسار: الوعد Promise to purchase العميل يطلب السلعة ويعد بشرائها، ثم شراء البنك Bank buys the asset من المورد بثمن 50,000، ثم القبض Possession البنك يملك ويقبض بتاريخ ومستند، ثم عقد المرابحة Murabaha sale البيع للعميل بثمن 50,928 مؤجلاً، ثم الأقساط 12 قسطاً بـ 4,244 أو سداد مبكر، وتحتها أن الترتيب جزء من صحة العقد والبيع قبل التملك والقبض يجعل المعاملة غير صحيحة فالنظام يرفضه
خمسة أحداث بترتيب ثابت، ولكل حدث تاريخ ومستند
  1. الطلب والوعد بالشراء Promise: يحدد صاحب النادي الأجهزة والمورد وعرض السعر، ويمر بالدراسة الائتمانية كأي تمويل، ثم يوقع وعداً بشراء الأجهزة من البنك إذا اشتراها البنك. والوعد هنا ليس بيعاً، فالبنك لم يملك شيئاً بعد، والنظام يسجله كحدث بتاريخه ومستنده، ولا يولد أي قيد في الدفتر العام، لأنه لا يوجد أصل ولا دين.
  2. شراء البنك Purchase: يشتري البنك الأجهزة من المورد بثمن 50,000 ريال، فتدخل دفتر البنك كمخزون سلع مرابحة، ويظهر التزام للمورد أو دفع له.
  3. القبض Possession: يتملك البنك الأجهزة ويقبضها، حقيقة أو حكماً بحسب ما تجيزه لجنة الشريعة في البنك، وفي النظام هذا حدث مستقل بتاريخ ومستند، مثل إشعار التسليم أو مستند نقل الملكية، ومن هذه اللحظة يتحمل البنك خطر السلعة.
  4. البيع Murabaha Sale: يوقع البنك وصاحب النادي عقد المرابحة بثمن 50,928 ريالاً، منها 50,000 تكلفة و928 ربح، فيخرج المخزون من دفتر البنك، ويظهر دين على العميل بالثمن كاملاً، ويظهر الربح كربح مؤجل لم يكتسب بعد.
  5. الأقساط Instalments: يدفع العميل 12 قسطاً بـ 4,244 ريالاً، وفي كل شهر يكتسب البنك جزءاً من الربح المؤجل، حتى يصبح الدين صفراً والربح المؤجل صفراً، أو يسدد العميل الباقي مبكراً.

لماذا الترتيب والتواريخ جزء من صحة العقد؟

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

وهذا يحول مسألة شرعية إلى متطلب تقني واضح: ترتيب الأحداث ليس تفضيلاً في واجهة المستخدم، وإنما قيد يجب أن يفرضه النظام. فلا يقبل النظام تسجيل البيع إذا لم يسجل الشراء والقبض قبله، ولا يقبل بيعاً بتاريخ يسبق تاريخ القبض، ولا يسمح بتعديل تاريخ حدث بعد تسجيله دون أثر في سجل التدقيق. والخطأ الذي يحدث في الأنظمة التي لم تصمم لهذا أن يدخل الموظف المستندات بأي ترتيب تصل به، أو أن يسمح النظام بإنشاء عقد البيع مباشرة لأن «القبض سيسجل لاحقاً»، فيكتشف التدقيق الشرعي بعد أشهر عقوداً ترتيبها خطأ. ولهذا بنينا في المختبر حالة العقد كآلة حالات State Machine ترفض الحدث الذي يأتي قبل أوانه، تماماً كما يرفض الدفتر القيد غير المتوازن.

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

الفترة التي يملك فيها البنك السلعة

بين الشراء والبيع يملك البنك الأجهزة، وفي هذه الفترة يتحمل خطرها: إذا تلفت قبل البيع فهي خسارته، وإذا تراجع العميل عن الشراء بقيت عنده سلعة لا يحتاجها. ويذكر الإطار هذا النوع من المخاطر في باب مخاطر السوق، ففي البند 8.7.1 من أمثلته القيمة السوقية لأصول مرابحة اشتريت لتسلم خلال فترة محددة. وللنظام في ذلك درسان: الأول أن مخزون سلع المرابحة حساب يجب أن يكون صفراً في الغالب، فكل سلعة تدخله تخرج منه ببيع في أيام قليلة، والرصيد الذي يبقى فيه أسابيع إشارة على عقود متعثرة في منتصفها تحتاج متابعة. والثاني أن الفترة بين الشراء والبيع يجب أن تكون قصيرة ومراقبة، ولذلك يقيس النظام عمر كل سلعة في المخزون ويعرض للموظفين العقود التي اشتريت سلعتها ولم تبع بعد.

القيود في الدفتر العام GL

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

أربع بطاقات من اليمين إلى اليسار: شراء السلعة Purchase مدين 1400 inventory بـ 50,000 ودائن 2100 supplier بـ 50,000 أصل في دفتر البنك، ثم البيع مرابحة Sale مدين 1500 receivable بـ 50,928 ودائن 1400 inventory بـ 50,000 ودائن 1590 deferred بـ 928، ثم القسط الشهري Instalment مدين 1100 cash بـ 4,244 ودائن 1500 receivable بـ 4,244 حركة نقد لا دخل، ثم إثبات الربح Profit recognition مدين 1590 deferred بـ 142.03 ودائن 4100 income بـ 142.03 بالرصيد المتناقص، وتحتها أن الذمة بإجمالي الثمن والربح المؤجل حساب مقابل لها وصافيهما هو الأصل المتبقي في كل لحظة
أربعة قيود تكفي لتتبع العقد من الشراء إلى آخر قسط
  • الشراء: مدين مخزون سلع المرابحة 50,000، ودائن المورد 50,000، ثم عند الدفع للمورد مدين المورد ودائن النقد. والسلعة هنا أصل في دفتر البنك بتكلفتها.
  • البيع: مدين ذمة المرابحة 50,928، ودائن المخزون 50,000، ودائن الربح المؤجل 928. لاحظ أن الذمة تسجل بالثمن الإجمالي الذي سيدفعه العميل، لا بالتكلفة، لأن العميل مدين فعلاً بـ 50,928 ريالاً بمجرد البيع، والربح المؤجل حساب مقابل Contra Account يطرح من الذمة في الميزانية، فصافيهما في يوم البيع 50,000، أي ما زال البنك «يملك» قيمة التكلفة في صورة دين.
  • القسط: مدين النقد أو حساب العميل الجاري 4,244، ودائن ذمة المرابحة 4,244. وهذا القيد لا يولد دخلاً، لأن القسط تحصيل لدين موجود، والخطأ الشائع أن يقيد النظام جزءاً من القسط كدخل مباشرة كما يفعل نظام القروض.
  • إثبات الربح: مدين الربح المؤجل، ودائن دخل المرابحة، بمبلغ ربح الشهر. وهذا القيد هو الذي يحول الربح المؤجل إلى دخل على مدى العقد، وطريقة حساب مبلغه هي موضوع القسم التالي.

وقد يتساءل البعض: لماذا لا نسجل الذمة بالتكلفة ونضيف الربح شهراً بشهر كما في القرض؟ والإجابة أن هذا يخفي حقيقة العقد، فالعميل مدين بالثمن كاملاً من يوم البيع، وكشف حسابه يجب أن يظهر 50,928 ريالاً، والسداد المبكر يحسب من هذا الثمن مطروحاً منه ما يتنازل عنه البنك من الربح كما سنرى. وتسجيل الذمة بالإجمالي مع ربح مؤجل مقابل لها يعطي الرقمين معاً في كل لحظة: ما يدين به العميل بحسب العقد، وما اكتسبه البنك فعلاً حتى الآن. ولاحظ أيضاً أن المطابقة اليومية التي شرحناها في النظام الأساسي بين الدفتر الفرعي والدفتر العام تنطبق هنا على حسابين: مجموع ذمم عقود المرابحة يساوي رصيد حساب الذمة، ومجموع الربح المؤجل في العقود يساوي رصيد حساب الربح المؤجل.

كيف يوزع الربح على الأشهر؟

الربح 928 ريالاً معلوم من يوم البيع، والسؤال كم منه يكتسب في كل شهر. والطريقتان المعروفتان: التوزيع بالتساوي Flat، فيكتسب البنك 928 على 12، أي 77.33 ريالاً كل شهر، والتوزيع بالرصيد المتناقص Declining Balance، فيكتسب في كل شهر ربحاً يتناسب مع الرصيد المتبقي من التكلفة في بداية الشهر، فيكون ربح الشهر الأول أكبر لأن الرصيد أكبر، ويصغر شهراً بعد شهر. والصورة التالية تقارن الطريقتين بأرقام عقدنا:

أعمدة أفقية لربح الشهر في خمسة أشهر: الشهر 1 بالرصيد المتناقص 142.03 وبالتساوي 77.33، والشهر 3 متناقص 118.69 وثابت 77.33، والشهر 6 متناقص 83.44 وثابت 77.33، والشهر 9 متناقص 47.88 وثابت 77.33، والشهر 12 متناقص 12.03 وثابت 77.33، وتحتها أن الربح الكلي واحد في الطريقتين والفرق في توزيعه على الأشهر وهو ما يحدد مبلغ السداد المبكر
نفس الربح الكلي، وتوزيع مختلف جداً على الأشهر

والطريقة التي يعتمدها البنك المركزي في حساب السداد المبكر واضحة في صفحة أبرز شروط حساب مبلغ السداد المبكر بتاريخ 1 أغسطس 2015: استخدام طريقة الرصيد المتناقص لتوزيع تكلفة الأجل على مدة التمويل، بحيث توزع تكلفة الأجل على الأقساط بنسبة الرصيد المتبقي من مبلغ التمويل في بداية الفترة التي يستحق عنها القسط. وتطلب الصفحة نفسها أن يحدد جدول السداد عدد الدفعات، وتاريخ كل دفعة، ومبلغها، ومقدار تكلفة الأجل (الربح) والأصل في كل دفعة، والرصيد المتبقي من مبلغ التمويل بعد كل دفعة. وهذه الأعمدة هي بالضبط ما يطبعه المختبر، لأن الجدول ليس ورقة للعميل فقط، وإنما المرجع الذي يحسب منه مبلغ السداد المبكر.

ولماذا يهم الفرق بين الطريقتين ما دام الربح الكلي واحداً؟ لثلاثة أسباب. الأول أن العميل الذي يسدد مبكراً يدفع الأصل المتبقي، والأصل المتبقي يختلف بين الطريقتين: بالرصيد المتناقص يكون الجزء الأكبر من الأقساط الأولى ربحاً فيبقى أصل أكبر، وبالتساوي يكون الأصل المتبقي أقل، وسوف نرى في المختبر أن الفرق بعد ستة أشهر يقارب 160 ريالاً في عقد بخمسين ألفاً. والثاني أن الدخل الذي يعرضه البنك في قوائمه كل شهر يختلف، والمدقق يسأل عن الطريقة. والثالث أن العميل والجهة المنظمة يحسبان بالطريقة المعتمدة، فالنظام الذي يحسب بغيرها يعطي أرقاماً لا يستطيع أحد تفسيرها.

ماذا يقول معيار AAOIFI؟

هيئة المحاسبة والمراجعة للمؤسسات المالية الإسلامية AAOIFI تصدر معايير محاسبية وشرعية تطبقها مؤسسات مالية إسلامية في دول عدة، ومعيارها المحاسبي للمرابحة هو المعيار رقم 28 «المرابحة والبيوع الآجلة الأخرى» Murabaha and Other Deferred Payment Sales. ويذكر إعلان الهيئة أن مجلس المحاسبة فيها اعتمد إصدار المعيار في اجتماعه بين 22 و24 سبتمبر 2017 بعد جلسات استماع عامة بين أبريل ويونيو 2017. ويذكر إعلان إصدار النسخة العربية أن المعيار يحل محل المعيار 2 «المرابحة والمرابحة للآمر بالشراء» والمعيار 20 «البيوع الآجلة»، وأنه يضع قواعد القياس والإثبات والإفصاح لمعاملات المرابحة والبيوع الآجلة التي تقوم بها المؤسسة المالية الإسلامية، وأنه لا ينطبق على المرابحة في السلع Commodity Murabaha والتورق، لأن لهما معياراً منفصلاً كان في مرحلة التطوير وقت الإعلان، وأن الهيئة سعت فيه إلى تقريب المحاسبة من أفضل الممارسات الدولية دون الإخلال بأحكام الشريعة.

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

السداد المبكر: ماذا يدفع العميل؟

بعد ستة أشهر تحسنت أعمال النادي، وأراد صاحبه أن يسدد باقي ثمن الأجهزة دفعة واحدة. والسؤال الذي يجب أن يجيب عنه النظام فوراً: كم يدفع؟ ونص البنك المركزي في صفحة السداد المبكر أن أنظمة التمويل ولوائحها وضوابط التمويل الاستهلاكي تضمن للمستفيد أن يعجل سداد المبلغ المتبقي في أي وقت، عدا فترة منع السداد المبكر في التمويل العقاري إذا نص عليها العقد على ألا تتجاوز سنتين من تاريخ العقد، وأن هذا السداد يتم دون تكلفة الأجل عن الفترة المتبقية، مع حق جهة التمويل في تعويض عن أمرين: تكلفة إعادة الاستثمار، بما لا يتجاوز تكلفة الأجل للأشهر الثلاثة التالية للسداد محسوبة بالرصيد المتناقص، ومدفوعات لطرف ثالث بسبب عقد التمويل بشروط، منها أن تكون مدفوعة فعلاً وموثقة في ملف التمويل وغير قابلة للاسترداد من الطرف الثالث. والصورة التالية تبين الحساب بأرقام عقدنا:

أربع بطاقات: المتبقي من الأصل Remaining principal 25,212.74 بعد 6 أقساط، وربح 3 أشهر تالية Next 3 months profit يساوي 71.62 و59.77 و47.88 بمجموع 179.27، ومبلغ السداد المبكر Early settlement 25,392.01 يدفعه العميل، والربح المتنازل عنه Waived deferred profit يساوي 251.27 ناقص 179.27 أي 72.00 لا يدفعه العميل، وتحتها أن طريقة الحساب من دليل البنك المركزي لحساب مبلغ السداد المبكر والأرقام من مثاله الأول
الأصل المتبقي وربح ثلاثة أشهر فقط، وباقي الربح المؤجل لا يدفعه العميل

والأرقام ليست من اختيارنا، فصفحة أمثلة حساب مبلغ السداد المبكر فيها مثال أول لتمويل شخصي بمبلغ 50,000 ريال يسدد بأقساط شهرية قدرها 4,244 ريالاً على 12 شهراً، وتقول إن العميل إذا أراد السداد المبكر وبقيت عليه 6 أقساط فالرصيد المتبقي من مبلغ التمويل 25,212.74 ريالاً، وتكلفة الأجل للأشهر الثلاثة التالية 179.27 ريالاً، ومبلغ السداد المبكر مجموعهما، وتعرض جدول السداد كاملاً. وقد استخدمنا نفس المبلغ والقسط والمدة لعقد المرابحة في قصتنا، لأن الدليل يطبق على عقود التمويل بأقساط شهرية بغض النظر عن اسم المنتج، ولأن إعادة مثال رسمي منشور هللة بهللة أفضل اختبار لأي محرك جداول، فإذا لم يطابق المثال فالخطأ في المحرك.

وفي الدفتر، السداد المبكر قيد واحد: مدين النقد بمبلغ السداد، ومدين الربح المؤجل بكل ما بقي فيه، ودائن الذمة بكل ما بقي فيها، ودائن دخل المرابحة بربح الأشهر الثلاثة. والفرق بين الربح المؤجل الباقي وربح الأشهر الثلاثة هو ما لا يدفعه العميل، أي ما يتنازل عنه البنك من الثمن، وتسمي البنوك هذا التنازل في الغالب إبراءً Ibra. وسوف نرى في المختبر أن هذا القيد بالذات هو الذي كشف لنا فرق هللة بين الجدول والدفتر.

المختبر: مرابحة كاملة على دفتر قيد مزدوج

المختبر برنامج Python واحد بالمكتبة القياسية، شغلناه داخل Container من الـ Docker Image الرسمية python:3.13.17-slim. وفيه ثلاثة أجزاء: دفتر قيد مزدوج على SQLite بنفس قواعد دفتر المحفظة الرقمية (القيد متوازن، والقيود لا تعدل ولا تحذف، ولكل قيد مفتاح منع تكرار Idempotency Key مع بصمة للطلب)، ومحرك جدول بالرصيد المتناقص يستخرج معدل الربح الشهري من القسط والمدة، وآلة حالات للعقد ترفض الحدث الذي يأتي قبل أوانه. ثم يمر العقد بالشراء والقبض والبيع وستة أقساط والسداد المبكر، ويطبع ميزان المراجعة. والمبالغ في الكود بالنوع Decimal وتقيد في الدفتر بالهللة كأعداد صحيحة:

# murabaha.py: a murabaha contract lifecycle on a small double-entry ledger (SQLite, append-only, idempotent)
# Numbers reproduce SAMA's published early-repayment example (50,000 over 12 monthly payments of 4,244).
import sqlite3, hashlib, json, sys
from datetime import date
from decimal import Decimal, ROUND_HALF_UP

C = Decimal("0.01")
def q(x): return x.quantize(C, rounding=ROUND_HALF_UP)

# ---------- the ledger: same rules as the wallet ledger (balanced entries, append-only, idempotency key) ----------
db = sqlite3.connect(":memory:")
db.executescript("""
CREATE TABLE accounts (code TEXT PRIMARY KEY, type TEXT NOT NULL CHECK (type IN ('asset','liability','income','contra')));
CREATE TABLE journal  (id INTEGER PRIMARY KEY, idempotency_key TEXT NOT NULL UNIQUE, request_hash TEXT NOT NULL,
                       kind TEXT NOT NULL, ref TEXT, business_date TEXT NOT NULL);
CREATE TABLE postings (journal_id INTEGER NOT NULL REFERENCES journal(id), account TEXT NOT NULL REFERENCES accounts(code),
                       amount INTEGER NOT NULL CHECK (amount <> 0));          -- halalas; debit > 0, credit < 0
CREATE TRIGGER postings_no_update BEFORE UPDATE ON postings BEGIN SELECT RAISE(ABORT, 'postings are append-only'); END;
CREATE TRIGGER postings_no_delete BEFORE DELETE ON postings BEGIN SELECT RAISE(ABORT, 'postings are append-only'); END;
""")
for code, t in [("1100 cash", "asset"), ("1400 murabaha inventory", "asset"), ("1500 murabaha receivable", "asset"),
                ("1590 deferred murabaha profit", "contra"), ("2100 supplier payable", "liability"),
                ("4100 murabaha income", "income")]:
    db.execute("INSERT INTO accounts VALUES (?,?)", (code, t))

def post(key, kind, ref, day, lines):
    """lines: {account: Decimal SAR, + debit / - credit}. Returns the journal id; a replay returns the first id."""
    cents = {a: int(v * 100) for a, v in lines.items()}
    h = hashlib.sha256(json.dumps([kind, ref, sorted(cents.items())]).encode()).hexdigest()[:16]
    old = db.execute("SELECT id, request_hash FROM journal WHERE idempotency_key=?", (key,)).fetchone()
    if old:
        if old[1] != h:
            raise ValueError(f"idempotency key {key} was used for a different request")
        return old[0]
    if sum(cents.values()) != 0:
        raise ValueError(f"{kind} {ref} not balanced: {sum(cents.values())} halalas off")
    with db:
        jid = db.execute("INSERT INTO journal (idempotency_key, request_hash, kind, ref, business_date) VALUES (?,?,?,?,?)",
                         (key, h, kind, ref, day.isoformat())).lastrowid
        db.executemany("INSERT INTO postings VALUES (?,?,?)", [(jid, a, v) for a, v in cents.items() if v])
    return jid

def bal(acc):
    return Decimal(db.execute("SELECT COALESCE(SUM(amount),0) FROM postings WHERE account=?", (acc,)).fetchone()[0]) / 100

# ---------- the schedule: SAMA's declining-balance method ----------
def monthly_rate(principal, payment, n):
    lo, hi = Decimal(0), Decimal("0.05")
    for _ in range(200):                       # bisection: the rate whose annuity payment equals `payment`
        mid = (lo + hi) / 2
        pay = principal * mid / (1 - (1 + mid) ** -n)
        lo, hi = (mid, hi) if pay < payment else (lo, mid)
    return (lo + hi) / 2

def declining(principal, payment, n, carry_rounded=False):
    """rows of (k, opening, profit, principal, closing), rounded to halalas for posting and display.
    The balance is carried unrounded (as in SAMA's example); carry_rounded=True was our first version."""
    r, b, rows, total = monthly_rate(principal, payment, n), principal, [], payment * n - principal
    for k in range(1, n + 1):
        profit = b * r
        if carry_rounded:
            profit = q(profit)
        princ = payment - profit
        rows.append([k, q(b), q(profit), q(princ), q(b - princ)])
        b -= princ
    if not carry_rounded:                      # the last row absorbs the rounding so the profits add up to the contract
        rows[-1][2] = total - sum(x[2] for x in rows[:-1])
        rows[-1][3] = rows[-1][1]; rows[-1][4] = Decimal("0.00")
    else:
        rows[-1][3] = rows[-1][1]; rows[-1][4] = Decimal("0.00")
    return r, [tuple(x) for x in rows]

# ---------- the contract: a state machine; the order of events is part of validity ----------
ORDER = ["promise", "purchase", "possession", "sale"]
class Murabaha:
    def __init__(self, ref): self.ref, self.events = ref, {}
    def record(self, event, day):
        need = ORDER[:ORDER.index(event)]
        missing = [e for e in need if e not in self.events]
        if missing:
            raise ValueError(f"{self.ref}: cannot record '{event}' before {missing}")
        if need and day < self.events[need[-1]]:
            raise ValueError(f"{self.ref}: '{event}' dated {day} is before '{need[-1]}' on {self.events[need[-1]]}")
        self.events[event] = day

if __name__ == "__main__":
    cost, payment, n = Decimal("50000"), Decimal("4244"), 12
    price = payment * n
    r, rows = declining(cost, payment, n, carry_rounded="--carry-rounded" in sys.argv)
    print(f"cost {cost:,}  selling price {price:,}  profit {price - cost:,}  monthly rate {r*100:.5f}%  yearly x12 {r*1200:.3f}%")
    print(" k   opening      profit   principal     closing")
    for k, b, p, pr, e in rows:
        print(f"{k:>2} {b:>10,.2f} {p:>10,.2f} {pr:>10,.2f} {e:>11,.2f}")
    print("sum of profit:", sum(p for _, _, p, _, _ in rows))

    m = Murabaha("MRB-0001")
    if "--sell-early" in sys.argv:                          # what if the sale is booked before possession?
        m.record("promise", date(2026, 1, 4))
        m.record("purchase", date(2026, 1, 5))
        try:
            m.record("sale", date(2026, 1, 5))
        except ValueError as e:
            print("REJECTED:", e)
        sys.exit()

    m.record("promise", date(2026, 1, 4))
    m.record("purchase", date(2026, 1, 5))
    post("MRB-0001:purchase", "purchase", m.ref, date(2026, 1, 5),
         {"1400 murabaha inventory": cost, "2100 supplier payable": -cost})
    post("MRB-0001:pay-supplier", "pay supplier", m.ref, date(2026, 1, 5),
         {"2100 supplier payable": cost, "1100 cash": -cost})
    m.record("possession", date(2026, 1, 6))
    m.record("sale", date(2026, 1, 6))
    post("MRB-0001:sale", "sale", m.ref, date(2026, 1, 6),
         {"1500 murabaha receivable": price, "1400 murabaha inventory": -cost,
          "1590 deferred murabaha profit": -(price - cost)})

    for k, _, profit, _, _ in rows[:6]:                     # six monthly instalments and their profit
        d = date(2026, 1 + k, 6)
        post(f"MRB-0001:inst:{k}", "instalment", m.ref, d, {"1100 cash": payment, "1500 murabaha receivable": -payment})
        post(f"MRB-0001:profit:{k}", "profit", m.ref, d, {"1590 deferred murabaha profit": profit, "4100 murabaha income": -profit})

    replay = post("MRB-0001:profit:3", "profit", m.ref, date(2026, 4, 6),
                  {"1590 deferred murabaha profit": rows[2][2], "4100 murabaha income": -rows[2][2]})
    print("replay of month-3 profit returns journal", replay, "and posts nothing new")
    try:
        post("MRB-0001:profit:3", "profit", m.ref, date(2026, 4, 6),
             {"1590 deferred murabaha profit": Decimal("77.33"), "4100 murabaha income": Decimal("-77.33")})
    except ValueError as e:
        print("REJECTED:", e)

    # early settlement after 6 instalments: remaining principal + profit of the next three months (SAMA guide)
    remaining = rows[5][4]
    next3 = sum(p for _, _, p, _, _ in rows[6:9])
    payoff = remaining + next3
    receivable, deferred = bal("1500 murabaha receivable"), -bal("1590 deferred murabaha profit")
    print(f"after 6: receivable {receivable:,.2f}  deferred profit {deferred:,.2f}  principal {receivable - deferred:,.2f}")
    print(f"early settlement = {remaining:,.2f} + next three months profit {next3:,.2f} = {payoff:,.2f}"
          f"  (waived profit {deferred - next3:,.2f})")
    lines = {"1100 cash": payoff, "1590 deferred murabaha profit": deferred,
             "1500 murabaha receivable": -receivable, "4100 murabaha income": -next3}
    if "--strict" not in sys.argv:             # the ledger's principal comes from rounded postings; book the gap visibly
        gap = sum(lines.values())
        lines["4100 murabaha income"] -= gap
        print(f"rounding gap between schedule and ledger: {gap} SAR, booked to income")
    post("MRB-0001:settle", "early settlement", m.ref, date(2026, 7, 20), lines)

    tb = db.execute("SELECT account, SUM(amount) FROM postings GROUP BY account ORDER BY account").fetchall()
    print("trial balance:")
    for a, v in tb:
        print(f"  {a:<32}{Decimal(v)/100:>12,.2f}")
    print("  sum (must be 0):", sum(v for _, v in tb))
    print("income recognised:", -bal("4100 murabaha income"), " journals:", db.execute("SELECT COUNT(*) FROM journal").fetchone()[0])
    try:
        db.execute("UPDATE postings SET amount = amount + 100 WHERE journal_id = 1")
    except sqlite3.DatabaseError as e:
        print("REJECTED:", e)

    # the same contract if the system had spread the profit evenly (flat) instead of declining balance
    flat = q((price - cost) / n)
    flat_principal_left = cost - 6 * (payment - flat)
    print(f"flat method: profit per month {flat}, income by month 6 {6*flat:,.2f} vs declining {sum(p for _,_,p,_,_ in rows[:6]):,.2f}")
    print(f"flat method payoff after 6: {flat_principal_left:,.2f} + {3*flat:,.2f} = {flat_principal_left + 3*flat:,.2f}"
          f"  vs guide {payoff:,.2f}")

وشغلناه من مجلد المختبر في Git Bash على Windows بالأمر التالي:

export MSYS_NO_PATHCONV=1
docker run --rm --name sfc-murabaha -v "$(pwd -W)":/lab -w /lab python:3.13.17-slim python murabaha.py

والمخرج سوف يكون كما يلي:

cost 50,000  selling price 50,928  profit 928  monthly rate 0.28406%  yearly x12 3.409%
 k   opening      profit   principal     closing
 1  50,000.00     142.03   4,101.97   45,898.03
 2  45,898.03     130.38   4,113.62   41,784.41
 3  41,784.41     118.69   4,125.31   37,659.10
 4  37,659.10     106.97   4,137.03   33,522.08
 5  33,522.08      95.22   4,148.78   29,373.30
 6  29,373.30      83.44   4,160.56   25,212.74
 7  25,212.74      71.62   4,172.38   21,040.36
 8  21,040.36      59.77   4,184.23   16,856.13
 9  16,856.13      47.88   4,196.12   12,660.01
10  12,660.01      35.96   4,208.04    8,451.97
11   8,451.97      24.01   4,219.99    4,231.98
12   4,231.98      12.03   4,231.98        0.00
sum of profit: 928.00
replay of month-3 profit returns journal 9 and posts nothing new
REJECTED: idempotency key MRB-0001:profit:3 was used for a different request
after 6: receivable 25,464.00  deferred profit 251.27  principal 25,212.73
early settlement = 25,212.74 + next three months profit 179.27 = 25,392.01  (waived profit 72.00)
rounding gap between schedule and ledger: 0.01 SAR, booked to income
trial balance:
  1100 cash                             856.01
  1400 murabaha inventory                 0.00
  1500 murabaha receivable                0.00
  1590 deferred murabaha profit           0.00
  2100 supplier payable                   0.00
  4100 murabaha income                 -856.01
  sum (must be 0): 0
income recognised: 856.01  journals: 16
REJECTED: postings are append-only
flat method: profit per month 77.33, income by month 6 463.98 vs declining 676.73
flat method payoff after 6: 24,999.98 + 231.99 = 25,231.97  vs guide 25,392.01

الجدول: هل يطابق مثال البنك المركزي؟

السطر الأول يقول إن المعدل الشهري الذي يجعل 12 قسطاً بـ 4,244 تسدد 50,000 ريال هو 0.28406%، أي 3.409% إذا ضرب في 12. ولاحظ أن البرنامج لا يعرف المعدل مسبقاً، وإنما يستخرجه بالتنصيف Bisection من القسط والمدة، لأن المثال الرسمي يعطي القسط لا المعدل. ثم الجدول: قارن الأعمدة بجدول البنك المركزي في صفحة الأمثلة، فربح الشهر الأول 142.03، والثاني 130.38، والسادس 83.44، والرصيد بعد ستة أقساط 25,212.74، والرصيد بعد الحادي عشر 4,231.98، كلها تطابق المثال هللة بهللة.

ولكن الوصول إلى هذه المطابقة لم يكن من أول تشغيل، وهذه أول مشكلة ظهرت لنا فعلاً. ففي النسخة الأولى من الدالة كنا نقرب ربح كل شهر إلى الهللة، ثم نطرح الأصل المقرب من الرصيد، فنحمل الرصيد مقرباً إلى الشهر التالي. والنسخة الأولى ما زالت في الكود خلف الخيار --carry-rounded، وعند تشغيلها يكون أول الجدول كما يلي:

cost 50,000  selling price 50,928  profit 928  monthly rate 0.28406%  yearly x12 3.409%
 k   opening      profit   principal     closing
 1  50,000.00     142.03   4,101.97   45,898.03
 2  45,898.03     130.38   4,113.62   41,784.41
 3  41,784.41     118.69   4,125.31   37,659.10
 4  37,659.10     106.97   4,137.03   33,522.07
 5  33,522.07      95.22   4,148.78   29,373.29
 6  29,373.29      83.44   4,160.56   25,212.73
 7  25,212.73      71.62   4,172.38   21,040.35
 8  21,040.35      59.77   4,184.23   16,856.12
 9  16,856.12      47.88   4,196.12   12,660.00
10  12,660.00      35.96   4,208.04    8,451.96
11   8,451.96      24.01   4,219.99    4,231.97
12   4,231.97      12.02   4,231.97        0.00
sum of profit: 927.99
replay of month-3 profit returns journal 9 and posts nothing new

لاحظ أن الأشهر الثلاثة الأولى تطابق المثال، ثم في الشهر الرابع يصبح الرصيد 33,522.07 بينما في جدول البنك المركزي 33,522.08، ويبقى الفرق هللة واحدة حتى آخر الجدول، فالرصيد بعد ستة أقساط 25,212.73 بدلاً من 25,212.74، ومجموع الربح 927.99. والسبب أن جدول البنك المركزي يحمل الرصيد بدقته الكاملة من شهر إلى شهر، ويقرب الأرقام عند العرض فقط، أما نسختنا الأولى فكانت تقرب في كل خطوة فتتراكم الكسور. والإصلاح في النسخة الحالية أن الرصيد يحمل بدقة Decimal الكاملة، وتقرب الأعمدة عند كتابة الصف فقط. وهذه الهللة تبدو تافهة، ولكنها في مبلغ السداد المبكر الذي يدفعه العميل، والعميل الذي يحسب بالطريقة الرسمية ويجد هللة مختلفة له أن يسأل، والمطابقة مع ملفات البنك المركزي أو المدقق تفشل.

والمثال الرسمي نفسه: 927.99 أم 928؟

المشكلة الثانية أدق: إذا جمعت عمود الربح في جدول البنك المركزي كما هو منشور ستجد 927.99، بينما الثمن 12 قسطاً بـ 4,244 يساوي 50,928، أي ربح 928 بالضبط. والسبب أن كل صف مقرب وحده، ومجموع المقربات لا يساوي تقريب المجموع، فضاعت هللة في العرض. وهذا مقبول في جدول للشرح، وغير مقبول في الدفتر، لأن الدفتر سيقيد عند البيع ربحاً مؤجلاً 928 ريالاً، فإذا أثبت منه 927.99 فقط على مدى العقد بقيت هللة في حساب الربح المؤجل إلى الأبد، وظهرت في تقرير الحسابات التي لم تصف. لذلك يجعل البرنامج الصف الأخير يمتص الفرق، فيكون ربحه 12.03 بدلاً من 12.02، ومجموع الربح 928.00 كما في سطر sum of profit. وهذا قرار يجب أن يكتب في تعريف المنتج: أين يذهب فرق التقريب، في القسط الأول أو الأخير، بنفس المنطق الذي رأيناه في تقسيم الأقساط في مقالات سابقة من القسم.

الدفتر: التكرار والسداد المبكر وميزان المراجعة

وبعد الجدول يمر العقد في الدفتر، وفي المخرج لاحظ التالي:

  • replay of month-3 profit: أعاد البرنامج إرسال قيد إثبات ربح الشهر الثالث بنفس المفتاح MRB-0001:profit:3 ونفس المبلغ، فرجع الدفتر برقم القيد الأول 9 دون أن يكتب شيئاً، وهذا ما يحمي من الدورة الليلية التي تعاد بعد عطل، كما شرحنا في مختبر النظام الأساسي.
  • REJECTED: idempotency key … was used for a different request: ثم أرسلنا نفس المفتاح بمبلغ 77.33، أي ربح الشهر بطريقة التساوي، كأن نسخة أخرى من البرنامج تعمل بإعداد مختلف، فرفض الدفتر لأن بصمة الطلب تختلف عن الأولى. وهذا أهم من الإعادة نفسها: المفتاح المكرر بطلب مختلف خطأ يجب أن يتوقف عنده النظام، لا أن يتجاهله.
  • after 6: بعد ستة أقساط الذمة 25,464.00، أي ستة أقساط باقية بـ 4,244، والربح المؤجل 251.27، والأصل المتبقي بحسب الدفتر هو الفرق 25,212.73.
  • early settlement: مبلغ السداد المبكر بحسب الجدول 25,212.74 وربح ثلاثة أشهر 179.27، فالمجموع 25,392.01، وهو نفس مثال البنك المركزي، والربح المتنازل عنه 72.00.
  • rounding gap … 0.01: وهنا المشكلة الثالثة: الأصل المتبقي في الجدول 25,212.74، وفي الدفتر 25,212.73، لأن الدفتر قيد ربح كل شهر مقرباً إلى الهللة، والجدول يحمل الرصيد بدقته الكاملة. فقيد السداد المبكر بمبالغ الجدول لا يتوازن بهللة.
  • trial balance: كل الحسابات أصبحت صفراً بعد السداد عدا النقد والدخل، فالنقد 856.01 والدخل 856.01، وهذا ربح البنك الفعلي من العقد: 676.73 أثبت في الأشهر الستة، و179.28 مع السداد المبكر. وميزان المراجعة صفر، و16 قيداً في الدفتر لهذا العقد.
  • REJECTED: postings are append-only: حاولنا تعديل قيد قديم مباشرة بأمر UPDATE، فرفضه الـ Trigger في SQLite، والتصحيح في دفتر حقيقي يكون بقيد عكسي، لا بتعديل.

وكيف عالجنا فرق الهللة؟ شغلنا البرنامج أولاً بالخيار --strict الذي يقيد مبالغ الجدول كما هي، فرفض الدفتر القيد:

ValueError: early settlement MRB-0001 not balanced: 1 halalas off

وهذا هو الرفض الصحيح، فالدفتر لا يقبل قيداً غير متوازن ولو بهللة. وكان أمامنا ثلاثة خيارات: أن نحسب مبلغ السداد من الدفتر لا من الجدول، فيدفع العميل 25,392.00 لا 25,392.01، وهذا يخالف الجدول الذي أعطيناه للعميل والطريقة الرسمية، أو أن نغير طريقة إثبات الربح الشهري لتطابق الجدول بدقة كاملة، وهذا مستحيل بالهللة، أو أن نقيد مبلغ الجدول كما هو ونحمل الفرق صراحة على حساب، وهذا ما فعلناه في النسخة الافتراضية: الهللة ذهبت إلى دخل المرابحة، وطبع البرنامج سطراً يقول ذلك. وفي بنك حقيقي يذهب هذا الفرق غالباً إلى حساب فروق تقريب مخصص تراجعه المالية، والأهم أن الفرق يقيد ويظهر، لا أن يختفي داخل رقم آخر. والدرس: الجدول والدفتر يجب أن يكونا من نفس المصدر، أو أن تكون بينهما قاعدة مكتوبة لمعالجة الفرق.

ماذا لو سجل البيع قبل القبض؟

الآن نجرب ما حذر منه مهندس البنك في بداية القصة، بالخيار --sell-early الذي يسجل الوعد والشراء ثم يحاول تسجيل البيع مباشرة:

docker run --rm --name sfc-murabaha -v "$(pwd -W)":/lab -w /lab python:3.13.17-slim python murabaha.py --sell-early

والمخرج سوف يكون كما يلي:

REJECTED: MRB-0001: cannot record 'sale' before ['possession']

رفضت آلة الحالات البيع لأن حدث القبض لم يسجل، وتذكر الرسالة الحدث الناقص بالاسم. ولاحظ أن الرفض يحدث قبل أي قيد في الدفتر، لأن البرنامج يسجل الحدث في العقد أولاً ثم يقيد، فالقيد لا يكتب لعقد ترتيبه خطأ. والدالة record تفحص أيضاً أن تاريخ الحدث لا يسبق تاريخ الحدث الذي قبله، فالبيع بتاريخ 5 يناير والقبض بتاريخ 6 يناير مرفوض حتى لو سجل القبض أولاً في النظام.

وماذا لو كان النظام يوزع الربح بالتساوي؟

آخر سطرين في المخرج يحسبان نفس العقد لو كان النظام يوزع الربح بالتساوي: ربح الشهر 77.33، والدخل المثبت حتى الشهر السادس 463.98 مقابل 676.73 بالرصيد المتناقص. والأهم مبلغ السداد المبكر: الأصل المتبقي بطريقة التساوي 24,999.98، ومعه ربح ثلاثة أشهر 231.99، فالمجموع 25,231.97، مقابل 25,392.01 بالطريقة الرسمية. أي أن النظام الذي يوزع بالتساوي ويحسب السداد المبكر من دفتره يطلب من العميل 160.04 ريالاً أقل مما يحسبه الدليل، وفي الاتجاه المعاكس في عقود أخرى قد يطلب أكثر. وفي الحالتين يعطي النظام رقماً لا يطابق الطريقة التي يحسب بها العميل والمدقق، وهذا يكفي ليكون خطأ يجب إصلاحه، مهما كان اتجاهه.

التأخر في السداد

ثمن المرابحة ثابت، فلا يزيد الدين على العميل المتأخر كما يزيد العائد على القرض التقليدي، وهذا أحد الفروق التي يجب أن يعرفها النظام: لا يوجد استحقاق يومي على الرصيد المتأخر يضاف إلى الدين. وأما ما يفرض على المتأخر من غرامة، وكيف تعامل في دفتر البنك، فقرار تحدده لجنة الشريعة في البنك وسياساته، والنظام يحتاج أن يدعمه بحساب مستقل في الدفتر لا يختلط بدخل المرابحة، حتى يظهر في كل لحظة كم حصل من غرامات وأين ذهب. وتنطبق على التحصيل نفسه ضوابط وإجراءات التحصيل التي تسري على البنوك وشركات التمويل، ومنها أن غرامات التأخير ورسوم التحصيل لا تتجاوز المبلغ المستحق وبحد أقصى قيمة قسط واحد طوال فترة التمويل، وأن الخصم لا يتم قبل موعد القسط، وأن العميل يعد متعثراً في الأقساط الشهرية إذا لم يسدد ثلاثة أشهر متتالية أو تأخر في خمسة أقساط منفصلة سبعة أيام عمل أو أكثر لكل منها. وفي الدفتر يبقى القسط المتأخر في الذمة كما هو، ويستمر إثبات الربح بحسب السياسة المحاسبية، ويحتاج النظام تصنيف التأخر وأيامه لكل عقد، لأن متابعة الائتمان والمخصصات تبنى عليه، كما يطلب الإطار في باب مخاطر الائتمان من متابعة قدرة الطرف المقابل ورغبته في السداد وتصنيف أداء التمويلات.

التورق Tawarruq: مرابحة غرضها السيولة

صاحب النادي احتاج أجهزة، فالمرابحة مناسبة لأن هناك سلعة يريدها فعلاً. ولكن لو احتاج نقداً لدفع رواتب موظفيه، فلا توجد سلعة يريدها، وهنا تأتي صيغة يعرفها الإطار باسم المرابحة في السلع Commodity Murabaha أو التورق، والصورة التالية تبين خطواتها:

أربع محطات من اليمين إلى اليسار: البنك يشتري سلعة Commodity purchase من بائع أو وسيط ويملكها، ثم يبيعها للعميل Deferred Murabaha بثمن مؤجل كالمرابحة، ثم العميل يبيعها Spot sale to third party نقداً لطرف ثالث دون ربط بين العقدين، ثم السيولة Cash to customer العميل يحصل على النقد ويبقى مديناً بالأقساط، وتحتها أن التورق كما يعرفه إطار البنك المركزي لإدارة مخاطر العمل المصرفي المتوافق مع الشريعة
نفس قيود المرابحة، ومعها أحداث بيع العميل للسلعة لطرف ثالث

ويعرف الإطار التورق بأنه معاملة مرابحة تقوم على شراء سلعة من بائع أو وسيط وبيعها للعميل بمرابحة مؤجلة، ثم يبيع العميل السلعة نقداً لطرف ثالث للحصول على السيولة، بشرط ألا يوجد ربط بين العقدين. ومن ناحية النظام، الجزء الأول نفس المرابحة بقيودها، والجزء الثاني أحداث جديدة: بيع العميل للسلعة، ووصول ثمنها إلى حسابه، وكلها بتواريخ ومستندات يراجعها التدقيق الشرعي، لأن شرط عدم الربط بين العقدين يجب أن يظهر في الوثائق والأحداث. وتذكر أن معيار AAOIFI رقم 28 للمرابحة يستثني التورق كما ذكر إعلان الهيئة، فالمعالجة المحاسبية للتورق قد تختلف عن المرابحة في تفاصيلها، والنظام الذي يدعم الصيغتين يعاملهما كمنتجين مختلفين في محرك المنتجات لا كمنتج واحد بخيار.

الحوكمة الشرعية: من يراقب المنتج داخل البنك؟

المهندس الذي يعمل على منتجات متوافقة مع الشريعة يتعامل مع جهة لا يجدها في منتجات أخرى: لجنة الشريعة، ومعها وظائف رقابة خاصة. وينظم ذلك إطار الحوكمة الشرعية للبنوك المحلية العاملة في المملكة، الصادر بالتعميم رقم 41042498 بتاريخ 12 فبراير 2020، والصورة التالية تبين الأطراف التي يذكرها:

خمس بطاقات: مجلس الإدارة Board يعين لجنة الشريعة بعدم ممانعة البنك المركزي، ولجنة الشريعة Shariah Committee تجيز المنتج وهيكله ووثائقه، والالتزام الشرعي Shariah Compliance يتحقق من التطبيق اليومي والترتيب، والمخاطر Non-compliance risk مخاطر عدم الالتزام ضمن إدارة المخاطر، والتدقيق الشرعي Shariah Internal Audit يراجع العينات والقيود والمستندات، وتحتها إطار الحوكمة الشرعية للبنوك المحلية تعميم 12 فبراير 2020 ومنه فصل أصول النوافذ الإسلامية
ثلاث وظائف رقابة داخلية بجانب لجنة الشريعة، وكلها تحتاج بيانات من النظام
  • لجنة الشريعة: يشكلها مجلس الإدارة ويعين أعضاءها بعد الحصول على عدم ممانعة مكتوبة من البنك المركزي، ومدة العضوية ثلاث سنوات، وتعتمد كل منتج مصرفي إسلامي قبل طرحه وأي تعديل عليه، وتراجع العقود والمستندات بالتفصيل.
  • ثلاث وظائف رقابة داخلية: يقوم الإطار على وظائف الالتزام الشرعي، وإدارة مخاطر عدم الالتزام الشرعي كجزء من إدارة المخاطر المتكاملة، والتدقيق الشرعي الداخلي الذي يجري على المجالات المهمة مرة في السنة على الأقل بحسب مستوى المخاطر.
  • عند اكتشاف عدم الالتزام: إذا علمت الإدارة أن معاملات تبدو غير متوافقة، فعليها أن تبلغ المجلس واللجنة فوراً، وأن توقف فوراً تقديم الخدمات أو المنتجات في خط العمل المرتبط، وأن تقدم خلال 30 يوم عمل خطة لتصحيح الوضع يعتمدها المجلس وتؤيدها اللجنة.
  • تطوير المنتج: يمر المنتج بموافقة قبل الطرح تشمل المفهوم والهيكل والشروط والوثائق والسياسات والإجراءات والمواد التسويقية، ومتابعة بعد الطرح عبر الالتزام والتدقيق.

ولكل بند من هذه أثر على النظام. فالموافقة على المنتج تعني أن إعدادات المنتج في محرك المنتجات، مثل طريقة توزيع الربح ومعالجة الغرامة وترتيب الأحداث، جزء مما اعتمدته اللجنة، فتغييرها يحتاج نفس المسار، لا تذكرة تطوير عادية. والتدقيق الشرعي يعني أن النظام يجب أن يعطي المدقق لكل عقد أحداثه بتواريخها ومستنداتها وقيودها في مكان واحد، فإذا احتاج المدقق ثلاثة أنظمة وجدول Excel ليعرف هل سبق القبض البيع، فالتدقيق سيكون عينات صغيرة وأخطاء كبيرة. والإيقاف الفوري لخط العمل يعني أن النظام يحتاج مفتاحاً يوقف إنشاء عقود جديدة لمنتج معين دون أن يتوقف تحصيل العقود القائمة، وهذا قرار تصميم لا يأتي من تلقاء نفسه.

النوافذ الإسلامية Islamic Window

بعض البنوك التقليدية تقدم منتجات متوافقة مع الشريعة عبر ما يسميه الإطار النافذة الإسلامية: جزء من بنك تقليدي، فرع أو وحدة مخصصة، يقدم خدمات تمويل واستثمار متوافقة مع الشريعة. وتطلب المادة السابعة عشرة من الإطار أن يضمن البنك أنظمة رقابة داخلية تفصل الأصول ومصادر التمويل المتوافقة عن غير المتوافقة، وأن يحتفظ بسجلات محاسبية منفصلة للعمليات الإسلامية، وأن يعد لها قوائم مالية منفصلة شهرياً على الأقل، مع تدقيق داخلي مرة في السنة على الأقل لهذه المتطلبات. وتقنياً يعني هذا أن الدفتر العام يحتاج تقسيماً واضحاً، كدفتر منفصل أو بعد محاسبي Segment في كل قيد، وأن مصدر التمويل جزء من بيانات العقد، فلا يمول عقد مرابحة من وديعة تقليدية، وأن القوائم الشهرية المنفصلة تستخرج من القيود مباشرة لا من تقسيم يدوي في آخر الشهر.

ماذا يعني ذلك للشركة الناشئة؟

عاد فريق الشركة الناشئة من الاجتماع وقد تغيرت شاشة «طلب تمويل المعدات» في لوحة الأندية، فلم تعد طلباً وموافقة وتحويلاً، وإنما حالات تتبع العقد في البنك:

  • الحالات من البنك: طلب مقدم، ثم موافقة ائتمانية، ثم وعد موقع، ثم شراء البنك للأجهزة، ثم تسليمها، ثم توقيع عقد المرابحة، ثم أقساط. والشاشة تعرض الحالة التي يرسلها البنك، ولا تستنتج حالة من حالة، لأن الترتيب يحكمه البنك.
  • المورد طرف في القصة: البنك يشتري من المورد ويدفع له، فالنادي لا يستلم 50,000 ريال في حسابه، والمورد يحتاج أن يعرف أن المشتري هو البنك، وأن الفاتورة باسمه، وهذا يغير طريقة عرض السعر الذي يرفعه النادي.
  • الأرقام التي تعرض: ثمن البيع وتكلفته والربح، وجدول الأقساط بأعمدته، ومبلغ السداد المبكر الذي يعطيه البنك في أي لحظة، لا رقماً تحسبه الشركة بنفسها.
  • التواريخ: كل حالة بتاريخ الحدث كما يعطيه البنك، لأن تاريخ القبض وتاريخ البيع جزء من العقد، والعرض الذي يخلط تاريخ الإشعار بتاريخ الحدث يربك صاحب النادي والبنك معاً.
  • التعديل بعد الموافقة: إذا أراد صاحب النادي تغيير جهاز بعد شراء البنك، فهذا ليس تعديلاً على طلب، وإنما مسألة يقررها البنك وفق سياسته، والشاشة لا تعرض زر «تعديل» على طلب في هذه المرحلة.

وفي وثيقة التكامل التي شرحناها في مقال النظام الأساسي يضيف الفريق أسئلة جديدة: ما الحالات التي يرسلها البنك وبأي ترتيب، وكيف يصل جدول الأقساط، وهل يمكن طلب مبلغ السداد المبكر عبر الواجهة، وكيف تعرف الأحداث المرتبطة بالمورد، وما المستندات التي يرفعها النادي ومتى.

أخطاء شائعة

الخطألماذا يضرالبديل
نمذجة المرابحة كقرض بعائدلا يوجد مخزون ولا ربح مؤجل، والدين يتصرف كقرضأحداث شراء وقبض وبيع وحسابات مخزون وربح مؤجل
السماح بتسجيل الأحداث بأي ترتيبعقود ترتيبها خطأ يكتشفها التدقيق الشرعي بعد أشهرآلة حالات ترفض الحدث قبل أوانه وتفحص التواريخ
قيد جزء من القسط كدخل مباشرةدخل لا يطابق الربح المؤجلالقسط تحصيل للذمة، والربح بقيد إثبات منفصل
توزيع الربح بالتساوي وحساب السداد المبكر منهمبلغ سداد لا يطابق الطريقة المعتمدةالرصيد المتناقص، وجدول بالأعمدة المطلوبة
تقريب الرصيد في كل شهرانحراف هللة عن المثال الرسمي من الشهر الرابعحمل الرصيد بدقة كاملة والتقريب عند العرض والقيد
ترك فرق التقريب دون قاعدةربح مؤجل لا يصفى، أو قيد لا يتوازنصف محدد يمتص الفرق، وحساب فروق تقريب ظاهر
خلط الغرامات بدخل المرابحةلا يعرف أحد كم حصل وأين ذهبحساب مستقل بحسب قرار لجنة الشريعة
معاملة التورق كخيار في منتج المرابحةأحداث ومعالجة مختلفة في منتج واحدمنتجان مستقلان في محرك المنتجات
دفتر واحد للنافذة الإسلامية والتقليدي دون تقسيملا يمكن إعداد القوائم المنفصلة من القيوددفتر منفصل أو بعد محاسبي، ومصدر التمويل في العقد

قائمة تحقق لنظام يدعم المرابحة

  • العقد آلة حالات: وعد، شراء، قبض، بيع، أقساط، إغلاق، ولا يقبل حدثاً قبل أوانه ولا تاريخاً يسبق الحدث الذي قبله.
  • كل حدث يحمل تاريخ الحدث من المستند وتاريخ الإدخال، ومرجع المستند نفسه.
  • القيود الأربعة (الشراء، والبيع، والقسط، وإثبات الربح) مكتوبة في تعريف المنتج، والذمة بالثمن الإجمالي مع ربح مؤجل مقابل لها.
  • جدول الأقساط بالرصيد المتناقص يطابق مثال البنك المركزي الرسمي هللة بهللة في الاختبارات الآلية.
  • مبلغ السداد المبكر يحسب كما في الدليل: الأصل المتبقي وتكلفة الأجل للأشهر الثلاثة التالية بالرصيد المتناقص، ومدفوعات الطرف الثالث بشروطها.
  • فرق التقريب له قاعدة مكتوبة وحساب ظاهر، ولا يبقى ربح مؤجل بعد إغلاق أي عقد.
  • كل قيد بمفتاح منع تكرار وبصمة طلب، والقيود لا تعدل، والتصحيح بقيد عكسي.
  • مخزون سلع المرابحة يراقب بعمر كل سلعة، والرصيد الذي يبقى أياماً يظهر في تقرير.
  • الغرامات في حساب مستقل بحسب قرار لجنة الشريعة، والتحصيل يحترم ضوابط التحصيل.
  • إعدادات المنتج التي اعتمدتها لجنة الشريعة لا تتغير إلا بنفس مسار الاعتماد، ويوجد مفتاح يوقف العقود الجديدة لمنتج دون إيقاف التحصيل.
  • في النافذة الإسلامية: سجلات محاسبية منفصلة، ومصدر التمويل في بيانات العقد، وقوائم شهرية منفصلة من القيود مباشرة.

الخلاصة

وصلنا لنهاية الموضوع، وأهم ما فيه:

  • المرابحة كما يعرفها البنك المركزي بيع أصل محدد بالتكلفة وهامش ربح متفق عليه، وقد يسبقها وعد بالشراء، فهي في النظام سلعة تدخل الدفتر ثم تخرج ببيع، ودين بثمن ثابت وربح مؤجل.
  • الإطار ينص على أن التواريخ مهمة جداً في المرابحة وأن تغيير ترتيب المستندات قد يجعل المعاملة غير صحيحة، فالترتيب قيد يفرضه النظام بآلة حالات.
  • أربعة قيود تحمل العقد: الشراء، والبيع بالذمة الإجمالية والربح المؤجل، والقسط كتحصيل، وإثبات الربح شهراً بشهر.
  • دليل البنك المركزي يعتمد الرصيد المتناقص لتوزيع تكلفة الأجل في حساب السداد المبكر، والسداد المبكر هو الأصل المتبقي وتكلفة الأجل للأشهر الثلاثة التالية.
  • في المختبر طابق الجدول مثال البنك المركزي هللة بهللة بعد أن صححنا تقريب الرصيد، ورأينا أن الجدول المنشور يجمع 927.99 ربحاً فجعلنا الصف الأخير يمتص الهللة، وكشف الدفتر فرق هللة في السداد المبكر فقيدناه صراحة، ورفضت آلة الحالات البيع قبل القبض.
  • التورق مرابحة غرضها السيولة، ومعيار AAOIFI رقم 28 للمرابحة يستثنيه، فهما منتجان مختلفان في النظام.
  • الحوكمة الشرعية بلجنتها ووظائفها الثلاث تحتاج من النظام أحداثاً وقيوداً ومستندات في مكان واحد، والنافذة الإسلامية تحتاج سجلات منفصلة.

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

وبقية مقالات قسم التقنية المالية والمدفوعات:

دليلالنظام المصرفي الأساسي Core Banking: البنك من الداخلما الذي يحفظه النظام المصرفي الأساسي وكيف تمر فيه الحركة، ولماذا يعمل بتاريخ عمل ودورة ليلية، مع مختبر لاستحقاق العائد على ألف حساب.دليلالمحفظة الرقمية من الداخل: دفتر القيد المزدوج Ledgerكيف تبني محفظة رقمية لا يضيع فيها ريال ولا يخصم مرتين، بالقيد المزدوج والمعاملات والمطابقة مع مزود الدفع.دليلدفتر الأستاذ للأموال Ledger: TigerBeetle وFormance وBlnkشغلنا TigerBeetle وFormance Ledger وBlnk بنفس سيناريو الحجز والتقسيم، ورأينا كيف تحمي كل أداة الرصيد ومتى يعرف تطبيقك النتيجة.دليلالمطابقة Reconciliation: كشف البنك مقابل نظامككيف تقابل كل حركة في كشف البنك بقيد في دفترك على مراحل، ولماذا قد يتساوى الرصيدان وتحتهما دفع مكرر لا يكشفه إلا المرجع.دليلاشتر الآن وادفع لاحقاً BNPL: كيف يعمل من الداخلكيف يعمل التقسيط دون تكلفة على العميل، وما تطلبه قواعد البنك المركزي، ومن أين تربح الشركة ومتى تخسر، مع نموذج Python لمحفظة أقساط.دليلالمحافظ الرقمية Digital Wallets: الأنواع والترخيص والبناءأنواع المحافظ الرقمية وتراخيص النقود الإلكترونية في المملكة وحدودها، وحماية أموال العملاء، مع مختبر للحدود والمطابقة اليومية.

سجل التحديثات

  • أكتوبر 2026: كتابة المقال، وتشغيل مختبر المرابحة على Python 3.13.17 داخل Docker بأرقام المثال الرسمي للسداد المبكر، والتحقق من إطار إدارة مخاطر العمل المصرفي المتوافق مع الشريعة وإطار الحوكمة الشرعية وصفحات السداد المبكر وضوابط التحصيل في دليل قواعد البنك المركزي وإعلانات AAOIFI عن المعيار 28 بتاريخ 27 أكتوبر 2026.
Could not load content
نشرة عرب رووت | ArabRoot

معرفة تستحق مكاناً في بريدك.

مقالات مختارة وأدوات مفيدة وأفكار لمشروعك القادم، في رسالة واحدة كل أسبوع.

يمكنك إلغاء الاشتراك متى شئت. الخصوصية

تم استلام طلبك. افتح بريدك واضغط رابط التأكيد لإتمام الاشتراك.