Skip to content

4. تمرين تطبيقي - IMPOTS

4.1. المشكلة

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

  • يتم حساب عدد حصص الموظف nbParts=nbEnfants/2 +1 إذا كان غير متزوج، nbEnfants/2+2 إذا كان متزوجًا، حيث nbEnfants هو عدد أطفاله.
  • يُحسب دخله الخاضع للضريبة R=0.72*S حيث S هو راتبه السنوي
  • يتم حساب معامل الأسرة Q=R/N

نحسب ضريبته I بناءً على البيانات التالية

12620.0
0
0
13190
0.05
631
15640
0.1
1290.5
24740
0.15
2072.5
31810
0.2
3309.5
39970
0.25
4900
48360
0.3
6898.5
55790
0.35
9316.5
92970
0.4
12106
127860
0.45
16754.5
151250
0.50
23147.5
172040
0.55
30710
195000
0.60
39312
0
0.65
49062

يحتوي كل سطر على 3 حقول. لحساب الضريبة I، نبحث عن السطر الأول الذي يكون فيه QF<=الحقل 1. على سبيل المثال، إذا كان QF=30000، فسنجد السطر

    24740        0.15        2072.5

يكون الضريبة I عندئذٍ مساوية لـ 0.15*R - 2072.5*nbParts. إذا كان QF بحيث لا تتحقق العلاقة QF<=champ1 أبدًا، فسيتم استخدام معاملات السطر الأخير. وهنا:

    0                0.65        49062

مما يعطي الضريبة I=0.65*R – 49062*nbParts.

4.2. النسخة التي تحتوي على جداول (impots_01)

نقدم برنامجًا أوليًّا حيث:

  • توجد البيانات اللازمة لحساب الضريبة في ثلاثة جداول (الحدود، coeffR، coeffN)
  • توجد بيانات دافعي الضرائب (الحالة الاجتماعية، عدد الأبناء، الراتب) في ملف نصي أول
  • يتم تخزين نتائج حساب الضريبة (متزوج، أطفال، راتب، ضريبة) في ملف نصي ثانٍ

<?php

// تعريف الثوابت
$DATA = "data.txt";
$RESULTATS = "resultats.txt";
$limites = array(12620, 13190, 15640, 24740, 31810, 39970, 48360, 55790, 92970, 127860, 151250, 172040, 195000);
$coeffR = array(0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65);
$coeffN = array(0, 631, 1290.5, 2072.5, 3309.5, 4900, 6898.5, 9316.5, 12106, 16754.5, 23147.5, 30710, 39312, 49062);

// قراءة البيانات
$data = fopen($DATA, "r");
if (!$data) {
  print "Impossible d'ouvrir en lecture le fichier des données [$DATA]\n";
  exit;
}

// فتح ملف النتائج
$résultats = fopen($RESULTATS, "w");
if (!$résultats) {
  print "Impossible de créer le fichier des résultats [$RESULTATS]\n";
  exit;
}

// استخدام السطر الحالي من ملف البيانات
while ($ligne = fgets($data, 100)) {
  // إزالة علامة نهاية السطر إن وجدت
  $ligne = cutNewLineChar($ligne);
  // استرجاع الحقول الثلاثة «متزوج» و«أطفال» و«الراتب» التي تشكل $ligne
  list($marié, $enfants, $salaire) = explode(",", $ligne);
  // يتم حساب الضريبة
  $impôt = calculImpots($marié, $enfants, $salaire, $limites, $coeffR, $coeffN);
  // يتم تسجيل النتيجة في ملف النتائج
  fputs($résultats, "$marié:$enfants:$salaire:$impôt\n");
  // المكلف التالي
}
// يتم إغلاق الملفات
fclose($data);
fclose($résultats);

// النهاية
exit;

// --------------------------------------------------------------------------
function cutNewLinechar($ligne) {
  // يتم حذف علامة نهاية السطر من $ligne إن وجدت
  $L = strlen($ligne);  // طول السطر
  while (substr($ligne, $L - 1, 1) == "\n" or substr($ligne, $L - 1, 1) == "\r") {
    $ligne = substr($ligne, 0, $L - 1);
    $L--;
  }
  // النهاية
  return($ligne);
}

// --------------------------------------------------------------------------
function calculImpots($marié, $enfants, $salaire, $limites, $coeffR, $coeffN) {
  // $marié: نعم، لا
  // $enfants: عدد الأطفال
  // $salaire: الراتب السنوي
  // $limites, $coeffR, $coeffN: جداول البيانات التي تسمح بحساب الضريبة
  
  // عدد الحصص
  $marié = strtolower($marié);
  if ($marié == "oui")
    $nbParts = $enfants / 2 + 2;
  else
    $nbParts=$enfants / 2 + 1;
  // حصة إضافية بمقدار النصف في حالة وجود 3 أطفال على الأقل
  if ($enfants >= 3)
    $nbParts+=0.5;
  // الدخل الخاضع للضريبة
  $revenuImposable = 0.72 * $salaire;
  // معدل الأسرة
  $quotient = $revenuImposable / $nbParts;
  // يتم وضعه في نهاية جدول الحدود لإنهاء الحلقة التالية
  array_push($limites, $quotient);
  // حساب الضريبة
  $i = 0;
  while ($quotient > $limites[$i])
    $i++;
  // نظرًا لوضع $quotient في نهاية الجدول $limites، فإن الحلقة السابقة
  // لا يمكن أن تتجاوز الجدول $limites
  // الآن يمكننا حساب الضريبة
  return floor($revenuImposable * $coeffR[$i] - $nbParts * $coeffN[$i]);
}
?>

ملف البيانات data.txt (متزوج، أطفال، راتب):

oui,2,200000
non,2,200000
oui,3,200000
non,3,200000
oui,5,50000
non,0,3000000

الملفات résultats.txt (المتزوجون، والأطفال، والراتب، والضرائب) من النتائج التي تم الحصول عليها:

oui:2:200000:22504
non:2:200000:33388
oui:3:200000:16400
non:3:200000:22504
oui:5:50000:0
non:0:3000000:1354938

تعليقات

  • السطر 4: اسم الملف النصي الذي يحتوي على بيانات دافعي الضرائب (الحالة الاجتماعية، عدد الأبناء، الراتب)
  • السطر 5: اسم الملف النصي الذي يحتوي على نتائج (الحالة الاجتماعية، عدد الأبناء، الراتب، الضريبة) حساب الضريبة
  • السطور 6-8: الجداول الثلاثة للبيانات التي تسمح بحساب الضريبة
  • الأسطر 11-15: فتح ملف بيانات دافعي الضرائب للقراءة
  • الأسطر 18-22: فتح ملف النتائج للكتابة
  • السطر 25: حلقة قراءة الأسطر (متزوج، أطفال، راتب) من ملف دافعي الضرائب
  • السطر 27: إزالة علامة نهاية السطر
  • السطر 29: يتم استرداد مكونات السطر (المتزوج، الأبناء، الراتب)
  • السطر 31: يتم حساب الضريبة
  • السطر 33: يتم تخزين الضريبة في ملف النتائج
  • السطران 37-38: بمجرد الانتهاء من معالجة ملف دافعي الضرائب بالكامل، يتم إغلاق الملفات
  • السطر 44: الدالة التي تحذف علامة نهاية السطر من سطر $ligne. علامة نهاية السطر هي السلسلة "\r\n" في أنظمة ويندوز، و"\n" في أنظمة يونكس. والنتيجة هي سلسلة الإدخال بدون علامة نهاية السطر.
  • السطران 47-48: substr($chaîne,$début,$taille) هي السلسلة الفرعية من $chaîne التي تبدأ من الحرف $début وتحتوي على $taille حرفًا كحد أقصى.
  • السطر 63: تعيد الدالة strtolower($chaîne) القيمة $chaîne بأحرف صغيرة
  • السطر 76: array_push($tableau,$élément) تضيف $élément إلى نهاية المصفوفة $tableau. تجدر الإشارة إلى أن المصفوفة $limites تم تمريرها بالقيمة إلى الدالة calculerImpot (السطر 56). وبالتالي، يتم إضافة هذا العنصر إلى نسخة المعلمة الفعلية، بينما تظل هذه الأخيرة دون تغيير.
  • السطر 84: تُرجع الدالة floor($x) القيمة الصحيحة الأقرب إلى الأسفل من $x.

4.3. الإصدار الذي يحتوي على ملفات نصية (impots_02)

لا تختلف هذه النسخة الجديدة عن النسخة السابقة إلا في أن البيانات ($limites، $coeffR، $coeffN) اللازمة لحساب الضريبة موجودة الآن في ملف نصي بالصيغة التالية:

ملف impots.txt:

12620:13190:15640:24740:31810:39970:48360:55790:92970:127860:151250:172040:195000:0
0:0.05:0.1:0.15:0.2:0.25:0.3:0.35:0.4:0.45:0.5:0.55:0.6:0.65
0:631:1290.5:2072.5:3309.5:4900:6898.5:9316.5:12106:16754.5:23147.5:30710:39312:49062

تكتفي النسخة الجديدة بقراءة البيانات من الملف [impots.txt] لوضعها في ثلاثة جداول ($limites، $coeffR، $coeffN). وبذلك نعود إلى الحالة السابقة. ونكتفي هنا بعرض التغييرات فقط:


<?php

// تعريف الثوابت
$DATA = "data.txt";
$RESULTATS = "resultats.txt";
$IMPOTS = "impots.txt";

// تم وضع البيانات اللازمة لحساب الضريبة في الملف $IMPOTS
// بمعدل سطر واحد لكل جدول بالصيغة
// val1:val2:val3,...
list($erreur, $limites, $coeffR, $coeffN) = getTables($IMPOTS);

// هل حدث خطأ؟
if ($erreur) {
  print "$erreur\n";
  exit;
}//if
// قراءة بيانات المستخدم
...

// نهاية
exit;

// --------------------------------------------------------------------------
function cutNewLinechar($ligne) {
  // يتم حذف علامة نهاية السطر من $ligne إن وجدت
...
}

// --------------------------------------------------------------------------
function calculImpots($marié, $enfants, $salaire, $limites, $coeffR, $coeffN) {
  // $marié: نعم، لا
  // $enfants: عدد الأطفال
  // $salaire: الراتب السنوي
  // $limites، $coeffR، $coeffN: جداول البيانات التي تسمح بحساب الضريبة
  ...
}

// --------------------------------------------------------------------------
function getTables($IMPOTS) {
  // $IMPOTS: اسم الملف الذي يحتوي على بيانات الجداول $limites، $coeffR، $coeffN
  // هل الملف $IMPOTS موجود؟
  if (!file_exists($IMPOTS))
    return array("Le fichier $IMPOTS n'existe pas","","","");
  // قراءة الملف دفعة واحدة
  $tables = file($IMPOTS);
  if (!$tables)
    return array("Erreur lors de l'exploitation du fichier $IMPOTS","","","");
  // إنشاء الجداول الثلاثة - نفترض أن الأسطر صحيحة من الناحية النحوية
  $limites = explode(":", cutNewLineChar($tables[0]));
  $coeffR = explode(":", cutNewLineChar($tables[1]));
  $coeffN = explode(":", cutNewLineChar($tables[2]));
  // النهاية
  return array("", $limites, $coeffR, $coeffN);
}
?>

تعليقات

  • السطر 11: تستخدم الدالة getTables($IMPOTS) الملف النصي $IMPOTS لاستخراج الجداول الثلاثة منه ($limites، $coeffR، $coeffN). والنتيجة النهائية هي ($erreur، $limites، $coeffR، $coeffN) حيث $erreur هي رسالة خطأ، وتكون فارغة في حالة عدم وجود خطأ.
  • السطر 40: الدالة getTables($IMPOTS).
  • السطر 43: تُرجع الدالة files_exists(nom_fichier) القيمة المنطقية true إذا كان الملف nom_fichier موجودًا، وإلا تُرجع القيمة المنطقية false.
  • السطر 46: تقوم الدالة file(nom_fichier) بقراءة ملف النص nom_fichier بالكامل. وتُرجع مصفوفةً يكون كل عنصر فيها سطرًا من ملف النص. وبما أن ملف impots.txt يحتوي، كما هو الحال هنا، على ثلاثة أسطر نصية، فإن الدالة ستُرجع مصفوفةً مكونةً من ثلاثة عناصر.
  • السطور 50-52: استخدام الأسطر الثلاثة المسترجعة لإنشاء المصفوفات الثلاثة ($limites، $coeffR، $coeffN)

النتائج التي تم الحصول عليها هي نفسها التي تم الحصول عليها في الإصدار السابق.