Skip to content

4. تمرین عملی – نسخه‌های ۱ و ۲

4.1. مسئله

Image

جدول بالا برای محاسبه مالیات در حالت ساده‌شده‌ی مودی‌ای که تنها حقوق خود را برای اظهار دارد، استفاده می‌شود. همان‌طور که در یادداشت (۱) اشاره شده است، مالیات محاسبه‌شده به این روش، مالیات قبل از اعمال سه مکانیزم است:

  • محدود کردن ضریب خانوادگی، که برای افراد با درآمد بالا اعمال می‌شود؛
  • معافیت مالیاتی و کاهش مالیات که برای درآمدهای پایین اعمال می‌شوند؛

بنابراین محاسبه مالیات شامل مراحل زیر است [http://impotsurlerevenu.org/comprendre-le-calcul-de-l-impot/1217-calcul-de-l-impot-2019.php]:

Image

ما پیشنهاد می‌کنیم برنامه‌ای برای محاسبه بدهی مالیاتی مودی در حالت ساده‌شده‌ای که تنها حقوق خود را برای اظهار دارد، بنویسیم:

4.1.1. محاسبه مالیات ناخالص

مالیات ناخالص را می‌توان به شرح زیر محاسبه کرد:

ابتدا تعداد سهام متعلق به مؤدی را محاسبه کنید:

    • هر والد یک سهم مشارکت می‌کند؛
    • دو فرزند اول هر کدام نیم سهم می‌پردازند؛
    • فرزندان بعدی هر کدام یک سهم مشارکت می‌کنند:

بنابراین تعداد سهام به این صورت است:

  • nbParts = 1 + nbEnfants * 0.5 + (تعداد فرزندان – 2) * 0.5 اگر کارمند مجرد باشد؛
  • nbParts = 2 + nbChildren * 0.5 + (nbChildren - 2) * 0.5 اگر متأهل باشند؛

که در آن nbEnfants تعداد فرزندان است؛

  • درآمد مشمول مالیات R به صورت R = 0.9 * S محاسبه می‌شود، که در آن S حقوق سالانه است؛
  • ضریب خانوادگی به صورت QF = R / nbParts محاسبه می‌شود؛
  • مالیات ناخالص I بر اساس داده‌های زیر (۲۰۱۹) محاسبه می‌شود:
۹۹۶۴
0
0
27519
0.14
۱٬۳۹۴٫۹۶
۷۳٬۷۷۹
0.3
۵٬۷۹۸
۱۵۶٬۲۴۴
0.41
۱۳٬۹۱۳٫۶۹
0
0.45
20163.45

هر سطر دارای ۳ فیلد است: champ1، champ2، champ3. برای محاسبه مالیات I، اولین ردیفی را که در آن QFfield1 باشد پیدا کرده و مقادیر آن ردیف را برمی‌داریم. برای مثال، برای کارمندی که متأهل با دو فرزند است و حقوق سالانه‌اش S برابر با ۵۰٬۰۰۰ یورو است:

درآمد مشمول مالیات: R = 0.9 × S = 45,000

تعداد پله های مالیاتی: nbParts = 2 + 2 * 0.5 = 3

ضریب خانوادگی: QF = ۴۵٬۰۰۰ / ۳ = ۱۵٬۰۰۰

اولین سطر که QF <= field1 است به شرح زیر است:

    27519        0.14    1394.96

بنابراین مالیات I برابر است با 0.14*R – 1394.96*nbParts=[0,14*45000-1394,96*3]=2115. مالیات به نزدیک‌ترین یورو به سمت پایین گرد می‌شود.

اگر شرط QFfield1 از خط اول به بعد برقرار باشد، مالیات صفر است.

اگر QF به گونه‌ای باشد که شرط QF <= field1 هرگز برقرار نشود، آنگاه ضرایب مربوط به آخرین خط استفاده می‌شوند. در این صورت:

    0            0.45        20163.45

که مالیات ناخالص I = 0.45*R – 20163.45*nbParts را می‌دهد.

4.1.2. سقف نسبت خانوادگی

Image

برای تعیین اینکه آیا سقف ضریب خانوادگی QF اعمال می‌شود، مالیات ناخالص بدون در نظر گرفتن فرزندان مجدداً محاسبه می‌شود. مجدداً، برای کارمند متأهل با دو فرزند و حقوق سالانه S برابر با ۵۰٬۰۰۰ یورو:

درآمد مشمول مالیات: R = 0.9 × S = 45,000

تعداد پله های مالیاتی: nbParts=2 (فرزندان دیگر در محاسبه لحاظ نمی‌شوند)

ضریب خانواده: QF = ۴۵٬۰۰۰ / ۲ = ۲۲٬۵۰۰

اولین خطی که QF <= field1 است به شرح زیر است:

    27519        0.14    1394.96

بنابراین مالیات I برابر است با 0.14*R – 1394.96*nbParts = [0,14*45000-1394,96*2] = 3510.

حداکثر معافیت مربوط به فرزند: ۱۵۵۱ * ۲ = ۳۱۰۲ یورو

حداقل مالیات: ۳۵۱۰ – ۳۱۰۲ = ۴۰۸ یورو

مالیات ناخالص، که قبلاً به مبلغ ۲٬۱۱۵ یورو (بر اساس ۳ رده مالیاتی) محاسبه شده است، از حداقل مالیات ۴۰۸ یورو بیشتر است، بنابراین سقف خانوادگی در اینجا اعمال نمی‌شود.

به‌طور کلی، مالیات ناخالص از (مالیات۱، مالیات۲) بیشتر است، که در آن:

  • [impôt1]: مالیات ناخالص محاسبه شده با احتساب فرزندان است؛
  • [impôt2]: مالیات ناخالص محاسبه شده بدون احتساب فرزندان و کاهش یافته با حداکثر معافیت (در اینجا ۱٬۵۵۱ یورو به ازای هر نیم‌سهم) مربوط به فرزندان است؛

4.1.3. محاسبه کاهش مالیات

Image

بار دیگر، برای کارمند متأهل با دو فرزند و حقوق سالانه S برابر با ۵۰,۰۰۰ یورو:

مالیات ناخالص (۲۱۱۵) از مرحله قبل کمتر از ۲۶۲۷ یورو برای یک زوج متأهل (۱۵۹۵ یورو برای یک فرد مجرد) است: بنابراین معافیت مالیاتی اعمال می‌شود. این معافیت به شرح زیر محاسبه می‌شود:

کاهش = آستانه (زوج = ۱۹۷۰ / فرد مجرد = ۱۱۹۶) – ۰.۷۵ × مالیات ناخالص

تخفیف = ۱۹۷۰ – ۰.۷۵ × ۲۱۱۵ = ۳۸۳.۷۵، که به ۳۸۴ یورو گرد شده است.

مالیات ناخالص جدید = ۲۱۱۵ – ۳۸۴ = ۱۷۳۱ یورو

4.1.4. محاسبه کاهش مالیات

Image

زیر یک آستانه مشخص، کاهشی ۲۰ درصدی بر مالیات ناخالص حاصل از محاسبات قبلی اعمال می‌شود. آستانه‌ها در سال ۲۰۱۹ به شرح زیر است:

  • فرد مجرد: ۲۱٬۰۳۷ یورو؛
  • زوج: ۴۲٬۰۷۴ یورو؛ (عدد ۳۷٬۹۶۸ که در مثال بالا استفاده شده به نظر نادرست است)؛

این آستانه با مقدار زیر افزایش می‌یابد: ۳٬۷۹۷ * (تعداد نیم‌سهام اهدایی توسط فرزندان).

بار دیگر، برای کارمند متأهل با دو فرزند و حقوق سالانه S برابر با ۵۰,۰۰۰ یورو:

  • درآمد مشمول مالیات او (۴۵٬۰۰۰ یورو) کمتر از آستانه (۴۲٬۰۷۴ + ۲ × ۳٬۷۹۷) = ۴۹٬۶۶۸ یورو است؛
  • بنابراین او مستحق ۲۰ درصد کاهش در مالیات خود است: ۱۷۳۱ × ۰.۲ = ۳۴۶.۲ یورو، که به ۳۴۷ یورو گرد شده است؛
  • مالیات ناخالص مودی به این صورت درمی‌آید: ۱,۷۳۱ – ۳۴۷ = ۱,۳۸۴ یورو؛

4.1.5. محاسبه مالیات خالص

محاسبه ما در اینجا به پایان می‌رسد: مالیات خالص قابل پرداخت ۱٬۳۸۴ یورو خواهد بود. در واقع، مؤدی ممکن است واجد شرایط دریافت کاهش‌های دیگری باشد، به‌ویژه برای اهدای کمک‌های مالی به سازمان‌های دارای منافع عمومی یا عمومی.

4.1.6. افراد با درآمد بالا

مثال قبلی ما برای اکثریت کارکنان صدق می‌کند. با این حال، محاسبه مالیات برای افراد با درآمد بالا متفاوت است.

4.1.6.1. سقف کاهش ۱۰ درصدی بر درآمد سالانه

در اکثر موارد، درآمد مشمول مالیات با استفاده از فرمول زیر محاسبه می‌شود: R = 0.9 × S، که در آن S حقوق سالانه است. این به عنوان کاهش ۱۰ درصدی شناخته می‌شود. این کاهش مشمول یک سقف است. در سال ۲۰۱۹:

  • نمی‌تواند از ۱۲٬۵۰۲ یورو تجاوز کند؛
  • نمی‌تواند کمتر از ۴۳۷ یورو باشد؛

بیایید مورد یک کارمند مجرد بدون فرزند با حقوق سالانه ۲۰۰,۰۰۰ یورو را در نظر بگیریم:

  • کاهش ۱۰ درصدی معادل ۲۰۰,۰۰۰ یورو > ۱۲,۵۰۲ یورو است. بنابراین، این مبلغ به ۱۲,۵۰۲ یورو محدود می‌شود؛

4.1.6.2. سقف ضریب خانوادگی

بیایید موردی را در نظر بگیریم که سقف کمک‌هزینه خانوادگی ذکرشده در پاراگراف مرتبط اعمال می‌شود. فرض کنیم یک زوج با سه فرزند و درآمد سالانه ۱۰۰,۰۰۰ یورو را در نظر بگیریم. بیایید مراحل محاسبه را دوباره بررسی کنیم:

  • معافیت ۱۰ درصدی برابر با ۱۰٬۰۰۰ یورو < ۱۲٬۵۰۲ یورو است. بنابراین درآمد مشمول مالیات R برابر است با ۱۰۰٬۰۰۰ – ۱۰٬۰۰۰ = ۹۰٬۰۰۰ یورو؛
  • این زوج دارای nbParts = 2 + 0.5 × 2 + 1 = 4 سهم هستند؛
  • بنابراین ضریب خانوادگی آنها QF = R / nbParts = 90,000 / 4 = 22,500 یورو است؛
  • مالیات ناخالص آنها I1 با فرزندان برابر است با I1 = 0.14 × 90,000 – 1,394.96 × 4 = 7,020 یورو؛
  • مالیات ناخالص او I2 بدون فرزندان:
    • QF = ۹۰٬۰۰۰ / ۲ = ۴۵٬۰۰۰ یورو؛
    • I2 = 0.3 × 90,000 – 5,798 × 2 = 15,404 یورو؛
    • قانونی که ضریب خانوادگی را محدود می‌کند، بیان می‌دارد که مزایایی که از بابت فرزندان به دست می‌آید نمی‌تواند از (۱۵۵۱ × ۴ سهم نیم‌برادر) = ۶۲۰۴ یورو تجاوز کند. با این حال، در این مورد، مقدار آن I2-I1 = ۱۵۴۰۴ – ۷۰۲۰ = ۸۳۸۴ یورو است، که بنابراین از ۶۲۰۴ یورو بیشتر است؛
    • بنابراین مالیات ناخالص مجدداً به صورت I3 = I2-6204 = 15,404 – 6,204 = 9,200 یورو محاسبه می‌شود؛

این زوج نه معافیت مالیاتی و نه کاهش مالیاتی دریافت نخواهند کرد و صورتحساب مالیاتی نهایی آنها ۹۲۰۰ یورو خواهد بود.

4.1.7. اعداد رسمی

محاسبه مالیات پیچیده است. در سراسر این سند، محاسبات بر اساس مثال‌های زیر انجام خواهد شد. نتایج از شبیه‌ساز سازمان مالیاتی [https://www3.impots.gouv.fr/simulateur/calcul_impot/2019/simplifie/index.htm] گرفته شده‌اند:

مودی
نتایج رسمی
نتایج حاصل از الگوریتم سند
یک زوج با دو فرزند و درآمد سالانه ۵۵٬۵۵۵ یورو
مالیات = ۲٬۸۱۵ یورو
نرخ مالیات = ۱۴٪
مالیات = ۲۸۱۴ یورو
نرخ مالیات = ۱۴٪
زوجی با دو فرزند و درآمد سالانه ۵۰,۰۰۰ یورو
مالیات = ۱۳۸۵ یورو
معافیت مالیاتی = ۷۲۰ یورو
کاهش = ۰ یورو
نرخ مالیات = ۱۴٪
مالیات = ۱۳۸۴ یورو
تخفیف = ۳۸۴ یورو
کاهش = ۳۴۷ یورو
نرخ مالیات = 14%
زوجی با ۳ فرزند و درآمد سالانه ۵۰,۰۰۰ یورو
مالیات = ۰ یورو
معافیت مالیاتی = ۳۸۴ یورو
کاهش = ۳۴۶ یورو
نرخ مالیات = ۱۴٪
مالیات = ۰ یورو
تخفیف = ۷۲۰ یورو
کاهش = ۰ یورو
نرخ مالیات = ۱۴٪
متأهل با دو فرزند و درآمد سالانه ۱۰۰,۰۰۰ یورو
مالیات = ۱۹٬۸۸۴ یورو
تخفیف = ۰ یورو
معافیت مالیاتی = ۰ یورو
نرخ مالیات = ۴۱٪
مالیات = ۱۹٬۸۸۴ یورو
سربار = ۴٬۴۸۰ یورو
تخفیف = ۰ یورو
کاهش = ۰ یورو
نرخ مالیات = ۴۱٪
متأهل مجرد با ۳ فرزند و درآمد سالانه ۱۰۰,۰۰۰ یورو
مالیات = ۱۶٬۷۸۲ یورو
تخفیف = ۰ یورو
معافیت مالیاتی = ۰ یورو
نرخ مالیات = ۴۱٪
مالیات = ۱۶٬۷۸۲ یورو
سربار = ۷٬۱۷۶ یورو
تخفیف = ۰ یورو
کاهش = ۰ یورو
نرخ مالیات = ۴۱٪
یک زوج با سه فرزند و درآمد سالانه ۱۰۰٬۰۰۰ یورو
مالیات = ۹٬۲۰۰ یورو
معافیت مالیاتی = ۰ یورو
معافیت = ۰ یورو
نرخ مالیات = ۳۰ درصد
مالیات = ۹۲۰۰ یورو
سربار = ۲٬۱۸۰ یورو
تخفیف = ۰ یورو
کاهش = ۰ یورو
نرخ مالیات = ۳۰٪
زوجی با ۵ فرزند و درآمد سالانه ۱۰۰,۰۰۰ یورو
مالیات = ۴٬۲۳۰ یورو
تخفیف = ۰ یورو
معافیت مالیاتی = ۰ یورو
نرخ مالیات = ۱۴٪
مالیات = ۴۲۳۰ یورو
تخفیف = ۰ یورو
معافیت = ۰ یورو
نرخ مالیات = 14%
مجرد، بدون فرزند و با درآمد سالانه ۱۰۰,۰۰۰ یورو
مالیات = ۲۲٬۹۸۶ یورو
تخفیف = ۰ یورو
معافیت مالیاتی = ۰ یورو
نرخ مالیات = ۴۱٪
مالیات = ۲۲٬۹۸۶ یورو
سربار = ۰ یورو
تخفیف = ۰ یورو
کاهش = ۰ یورو
نرخ مالیات = ۴۱٪
زوجی با دو فرزند و درآمد سالانه ۳۰,۰۰۰ یورو
مالیات = ۰ یورو
تخفیف = ۰ یورو
معافیت مالیاتی = ۰ یورو
نرخ مالیات = ۰٪
مالیات = ۰ یورو
تخفیف = ۰ یورو
کاهش = ۰ یورو
نرخ مالیات = ۰٪
مجرد، بدون فرزند و با درآمد سالانه ۲۰۰,۰۰۰ یورو
مالیات = ۶۴٬۲۱۱ یورو
تخفیف = ۰ یورو
معافیت مالیاتی = ۰ یورو
نرخ مالیات = ۴۵٪
مالیات = ۶۴٬۲۱۰ یورو
سربار = ۷٬۴۹۸ یورو
تخفیف = ۰ یورو
کاهش = ۰ یورو
نرخ مالیات = ۴۵٪
زوجی با سه فرزند و درآمد سالانه ۲۰۰,۰۰۰ یورو
مالیات = ۴۲٬۸۴۳ یورو
تخفیف = ۰ یورو
معافیت مالیاتی = ۰ یورو
نرخ مالیات = ۴۱٪
مالیات = ۴۲٬۸۴۲ یورو
سربار = ۱۷٬۲۸۳ یورو
تخفیف = ۰ یورو
کاهش = ۰ یورو
نرخ مالیات = ۴۱٪

در بالا، «سربار» به مبلغ اضافی پرداختی توسط افراد با درآمد بالا به دلیل دو عامل اشاره دارد:

  • سقف ۱۰ درصدی معافیت درآمد سالانه؛
  • سقف کمک‌هزینه خانوادگی؛

این شاخص قابل تأیید نیست زیرا شبیه‌ساز سازمان مالیاتی آن را ارائه نمی‌دهد.

می‌توانیم ببینیم که الگوریتم موجود در سند، هر بار مبلغ مالیات صحیح را محاسبه می‌کند، هرچند با یک حاشیه خطای ۱ یورو. این حاشیه خطا ناشی از گرد کردن اعداد است. در برخی موارد، تمام مبالغ پولی به بالا و در موارد دیگر به پایین، تا نزدیک‌ترین یورو گرد می‌شوند. از آنجایی که با قوانین رسمی آشنا نبودم، مقادیر پولی در الگوریتم سند گرد شده است:

  • برای تخفیف‌ها و کاهش‌ها تا نزدیک‌ترین یورو گرد شده است؛
  • برای عوارض اضافی و مالیات نهایی به نزدیک‌ترین یورو گرد شده است؛

در ادامه، آزمایش‌هایی برای تأیید اعتبار نتایج انجام خواهد شد. این آزمایش‌ها بر اساس مثال‌های جدول بالا و با یک حاشیه خطای قابل قبول ۱ یورو انجام می‌شوند.

4.2. ساختار دایرکتوری اسکریپت

Image

4.3. نسخه ۱

4.3.1. الگوریتم

ما یک برنامهٔ اولیه ارائه می‌دهیم که در آن:

  • داده‌های مورد نیاز برای محاسبه مالیات به‌صورت آرایه‌ها و ثابت‌ها به‌صورت سخت‌کد در برنامه درج شده‌اند؛
  • اطلاعات مالیات‌دهندگان (وضعیت تأهل، تعداد فرزندان، حقوق) در یک فایل متنی اول به نام [taxpayersdata.txt] قرار دارد؛
  • نتایج محاسبه مالیات (وضعیت تأهل، تعداد فرزندان، حقوق، مالیات) در یک فایل متنی دوم به نام [resultats.txt] ذخیره می‌شوند؛

اسکریپت [version-01/main.php] به شرح زیر است:


<?php

// انواع سخت‌گیرانه برای پارامترهای تابع
declare(strict_types=1);

// ثوابت سراسری
define("PLAFOND_QF_DEMI_PART", 1551);
define("PLAFOND_REVENUS_CELIBATAIRE_POUR_REDUCTION", 21037);
define("PLAFOND_REVENUS_COUPLE_POUR_REDUCTION", 42074);
define("VALEUR_REDUC_DEMI_PART", 3797);
define("PLAFOND_DECOTE_CELIBATAIRE", 1196);
define("PLAFOND_DECOTE_COUPLE", 1970);
define("PLAFOND_IMPOT_COUPLE_POUR_DECOTE", 2627);
define("PLAFOND_IMPOT_CELIBATAIRE_POUR_DECOTE", 1595);
define("ABATTEMENT_DIXPOURCENT_MAX", 12502);
define("ABATTEMENT_DIXPOURCENT_MIN", 437);

// تعریف ثابت‌های محلی
$DATA = "taxpayersdata.txt";
$RESULTATS = "resultats.txt";
$limites = array(9964, 27519, 73779, 156244, 0);
$coeffR = array(0, 0.14, 0.3, 0.41, 0.45);
$coeffN = array(0, 1394.96, 5798, 13913.69, 20163.45);

// خواندن داده‌ها
$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);
  //بازیابی سه فیلد «married:children:salary» که $ligne را تشکیل می‌دهند
  list($marié, $enfants, $salaire) = explode(",", $ligne);
  //مالیات محاسبه می‌شود
  $result = calculImpot($marié, (int) $enfants, (float) $salaire, $limites, $coeffR, $coeffN);
  //نتیجه در فایل نتایج نوشته می‌شود
  $result = ["marié" => $marié, "enfants" => $enfants, "salaire" => $salaire] + $result;
  fputs($résultats, \json_encode($result, JSON_UNESCAPED_UNICODE) . "\n");
  //رکورد بعدی
}
// بستن فایل‌ها
fclose($data);
fclose($résultats);

//پایان
exit;

// --------------------------------------------------------------------------
function cutNewLinechar(string $ligne): string {
  // در صورت وجود، نشانگر پایان خط را از $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 calculImpot(string $marié, int $enfants, float $salaire, array $limites, array $coeffR, array $coeffN): array {

  // نتیجه
  return ["impôt" => floor($impot), "surcôte" => $surcôte, "décôte" => $décôte, "réduction" => $réduction, "taux" => $taux];
}

// --------------------------------------------------------------------------
function calculImpot2(string $marié, int $enfants, float $salaire, array $limites, array $coeffR, array $coeffN): array {

  // نتیجه
  return ["impôt" => $impôt, "surcôte" => $surcôte, "taux" => $coeffR[$i]];
}

// revenuImposable=حقوق سالانه-مزایا
// مبلغ معافیت حداقل و حداکثری دارد
function getRevenuImposable(float $salaire): float {

  // نتیجه
  return floor($revenuImposable);
}

// هرگونه کاهش را محاسبه می‌کند
function getDecote(string $marié, float $salaire, float $impots): float {

  // نتیجه
  return ceil($décôte);
}

//هرگونه کاهش را محاسبه می‌کند
function getRéduction(string $marié, float $salaire, int $enfants, float $impots): float {
  /
  // نتیجه
  return ceil($réduction);
}

فایل داده taxpayersdata.txt (وضعیت تأهل، فرزندان، حقوق):

oui,2,55555
oui,2,50000
oui,3,50000
non,2,100000
non,3,100000
oui,3,100000
oui,5,100000
non,0,100000
oui,2,30000
non,0,200000
oui,3,200000

فایل résultats.txt (وضعیت تأهل، فرزندان، حقوق، مالیات، عوارض، تخفیف، کاهش، نرخ مالیات) حاوی نتایج به‌دست‌آمده:

{"marié":"oui","enfants":"2","salaire":"55555","impôt":2814,"surcôte":0,"décôte":0,"réduction":0,"taux":0.14}
{"marié":"oui","enfants":"2","salaire":"50000","impôt":1384,"surcôte":0,"décôte":384,"réduction":347,"taux":0.14}
{"marié":"oui","enfants":"3","salaire":"50000","impôt":0,"surcôte":0,"décôte":720,"réduction":0,"taux":0.14}
{"marié":"non","enfants":"2","salaire":"100000","impôt":19884,"surcôte":4480,"décôte":0,"réduction":0,"taux":0.41}
{"marié":"non","enfants":"3","salaire":"100000","impôt":16782,"surcôte":7176,"décôte":0,"réduction":0,"taux":0.41}
{"marié":"oui","enfants":"3","salaire":"100000","impôt":9200,"surcôte":2180,"décôte":0,"réduction":0,"taux":0.3}
{"marié":"oui","enfants":"5","salaire":"100000","impôt":4230,"surcôte":0,"décôte":0,"réduction":0,"taux":0.14}
{"marié":"non","enfants":"0","salaire":"100000","impôt":22986,"surcôte":0,"décôte":0,"réduction":0,"taux":0.41}
{"marié":"oui","enfants":"2","salaire":"30000","impôt":0,"surcôte":0,"décôte":0,"réduction":0,"taux":0}
{"marié":"non","enfants":"0","salaire":"200000","impôt":64210,"surcôte":7498,"décôte":0,"réduction":0,"taux":0.45}
{"marié":"oui","enfants":"3","salaire":"200000","impôt":42842,"surcôte":17283,"décôte":0,"réduction":0,"taux":0.41}

توضیحات

  • خط ۴: رعایت دقیق نوع پارامترهای تابع اعمال می‌شود؛
  • خطوط ۷–۱۶: تعریف تمام ثابت‌های مورد نیاز برای محاسبه مالیات؛
  • خط ۱۹: نام فایل متنی حاوی داده‌های مالیات‌دهندگان (متأهل، فرزندان، حقوق)؛
  • خط ۲۰: نام فایل متنی حاوی نتایج (وضعیت تأهل، تعداد فرزندان، حقوق، مالیات) محاسبه مالیات؛
  • خطوط ۲۱–۲۳: سه جدول داده که طبقات مختلف مالیاتی مورد استفاده در محاسبه مالیات را تعریف می‌کنند؛
  • خطوط ۲۶–۳۰: باز کردن فایل داده‌های مالیات‌دهنده در حالت فقط-خوانی با استفاده از [r]. تابع [fopen] مقدار بولین FALSE را در صورتی که فایل باز نشود، برمی‌گرداند؛
  • خطوط ۳۳–۳۷: باز کردن فایل نتایج برای نوشتن با استفاده از [w];
  • خطوط ۴۰–۵۱: حلقه برای خواندن خطوط (همسر، فرزندان، حقوق) از فایل داده‌های مالیات‌دهنده؛
  • خط ۴۰: تابع [fgets] صد کاراکتر را می‌خواند و در اولین نشانگر پایان خطی که برخورد می‌کند، متوقف می‌شود. در اینجا، تمام خطوط کمتر از ۱۰۰ کاراکتر طول دارند. اگر کاراکتر پایان خط یافت شود، در رشته بازگشتی گنجانده می‌شود. هنگامی که به انتهای فایل رسید، تابع [fgets] مقدار FALSE را برمی‌گرداند؛
  • خط ۴۲: کاراکتر پایان خط حذف می‌شود؛
  • خط ۴۴: اجزای (همسر، فرزندان، حقوق) خط بازیابی می‌شوند؛
  • خط ۴۶: مالیات محاسبه می‌شود. نتیجه به صورت یک آرایهٔ asociative (خط ۷۶) بازگردانده می‌شود؛
  • خط ۴۸: کلیدهای [marié, enfants, salaire] به آرایهٔ بازیابی‌شدهٔ قبلی اضافه می‌شوند؛
  • خط ۴۹: نتیجه به صورت یک رشته در فایل نتایج ذخیره می‌شود jSON;
  • خطوط ۵۳–۵۴: پس از پردازش کامل فایل داده‌های مالیات‌دهنده، فایل‌ها بسته می‌شوند؛
  • خط ۶۰: تابعی که کاراکتر پایان خط را از خط $ligne حذف می‌کند. کاراکتر پایان خط، رشته "\r\n" در سیستم‌های ویندوز و "\n" در سیستم‌های یونیکس است. نتیجه، رشته ورودی بدون کاراکتر پایان خط آن است.
  • خطوط ۶۳–۶۴: substr($chaîne, $début,$taille) زیر رشته‌ای از $chaîne است که از کاراکتر $début شروع شده و حداکثر $taille کاراکتر دارد؛

تابع [calculImpot] به صورت زیر است:


// ثوابت جهانی
define("PLAFOND_QF_DEMI_PART", 1551);

//محاسبه مالیات
// --------------------------------------------------------------------------
function calculImpot(string $marié, int $enfants, float $salaire, array $limites, array $coeffR, array $coeffN): array {
  // $marié: بله، نه
  // $enfants: تعداد فرزندان
  // $salaire: حقوق سالانه
  // $limites, $coeffR, $coeffN: جداول داده‌ای مورد استفاده برای محاسبه مالیات
  //
  //محاسبه مالیات با فرزندان
  $result1 = calculImpot2($marié, $enfants, $salaire, $limites, $coeffR, $coeffN);
  $impot1 = $result1["impôt"];
  //محاسبه مالیات بدون احتساب فرزندان
  if ($enfants != 0) {
    $result2 = calculImpot2($marié, 0, $salaire, $limites, $coeffR, $coeffN);
    $impot2 = $result2["impôt"];
    // اعمال سقف ضریب خانوادگی
    if ($enfants < 3) {
      // $PLAFOND_QF_DEMI_PART یورو برای دو فرزند اول
      $impot2 = $impot2 - $enfants * PLAFOND_QF_DEMI_PART;
    } else {
      //$PLAFOND_QF_DEMI_PART یورو برای دو فرزند اول، دو برابر آن برای فرزندان بعدی
      $impot2 = $impot2 - 2 * PLAFOND_QF_DEMI_PART - ($enfants - 2) * 2 * PLAFOND_QF_DEMI_PART;
    }
  } else {
    $impot2 = $impot1;
    $result2 = $result1;
  }
  // بالاترین مبلغ مالیات در نظر گرفته می‌شود، همراه با نرخ و عوارض مربوطه
  if ($impot1 > $impot2) {
    $impot = $impot1;
    $taux = $result1["taux"];
    $surcôte = $result1["surcôte"];
  } else {
    $surcôte = $impot2 - $impot1 + $result2["surcôte"];
    $impot = $impot2;
    $taux = $result2["taux"];
  }
  // محاسبه هرگونه معافیت مالیاتی
  $décôte = getDecote($marié, $salaire, $impot);
  $impot -= $décôte;
  // محاسبه هرگونه معافیت مالیاتی
  $réduction = getRéduction($marié, $salaire, $enfants, $impot);
  $impot -= $réduction;
  // نتیجه
  return ["impôt" => floor($impot), "surcôte" => $surcôte, "décôte" => $décôte, "réduction" => $réduction, "taux" => $taux];
}

// --------------------------------------------------------------------------
function calculImpot2(string $marié, int $enfants, float $salaire, array $limites, array $coeffR, array $coeffN): array {

  // نتیجه
  return ["impôt" => $impôt, "surcôte" => $surcôte, "taux" => $coeffR[$i]];
}

// revenuImposable=حقوق سالانه-مزایا
// مبلغ ۱۰٪ معافیت دارای حداقل و حداکثر است
function getRevenuImposable(float $salaire): float {

}

// هر تخفیف ممکن را محاسبه می‌کند
function getDecote(string $marié, float $salaire, float $impots): float {

  // نتیجه
  return ceil($décôte);
}

//هرگونه کاهش را محاسبه می‌کند
function getRéduction(string $marié, float $salaire, int $enfants, float $impots): float {

  // نتیجه
  return ceil($réduction);
}

نظرات

  • خط ۱۰: مالیات ناخالص شامل افراد تحت تکفل محاسبه می‌شود. نتیجه به شکل ["impôt" => $impôt, "surcôte" => $surcôte, "taux" => $coeffR[$i]] با:
    • [‘impôt’]: مالیات ناخالص؛
    • [‘surcôte’]: مبلغ اضافه بهای اعمال‌شده، در صورت وجود. این مورد زمانی اعمال می‌شود که معافیت ۱۰ درصدی از آستانه ۱۲٬۵۰۲ یورو فراتر رود؛
    • [‘taux’]: نرخ مالیاتی مودی؛
  • خط ۱۱: مالیات ناخالص قابل پرداخت [impot1];
  • رده‌های ۱۳–۱۴: اگر مؤدی حداقل یک فرزند داشته باشد، محاسبه مالیات با استفاده از همان داده‌ها اما با فرض ۰ فرزند، مجدداً انجام می‌شود. این محاسبه دوم برای تعیین اینکه آیا کاهش حاصل از داشتن فرزند (nbParts*coeffN) از آستانه مشخصی فراتر می‌رود، ضروری است؛
  • خط ۱۵: مالیات ناخالص قابل پرداخت [impot2
  • رده‌های ۱۶–۲۳: برای مالیات ناخالص [impot2]، معافیت فرزندان اکنون اعمال می‌شود: هر سهم نیم‌شریک ارائه‌شده توسط فرزندان منجر به کاهش [PLAFOND_QF_DEMI_PART] یورو می‌شود؛
  • رده‌های ۲۵–۲۶: در صورتی که مؤدی فرزند نداشته باشد. در این صورت، نیازی به محاسبه [impot2] نیست. این مقدار با [impot1] برابر است؛
  • رده‌های ۲۹–۳۷: دو مبلغ مالیات ناخالص محاسبه شده است: [impot1, impot2]. مقامات مالیاتی بالاترین مقدار را از بین این دو انتخاب می‌کنند. این امر منجر به مبلغ مالیات ناخالص [impot] می‌شود؛
  • رده‌های ۳۹–۴۰: مبلغ ناخالص [impot] ممکن است مشمول کاهش شود؛
  • رده‌های ۴۲–۴۳: مبلغ ناخالص [impot] ممکن است مشمول کاهش شود؛
  • خط ۴۵: [impot] اکنون مالیات خالص قابل پرداخت است. نتایج بازگردانده می‌شوند؛

تابع [calculImpot2] به شرح زیر است:


// --------------------------------------------------------------------------
function calculImpot2(string $marié, int $enfants, float $salaire, array $limites, array $coeffR, array $coeffN): array {
  // $marié: بله، نه
  // $enfants: تعداد فرزندان
  // $salaire: حقوق سالانه
  // $limites, $coeffR, $coeffN: جداول داده‌ای مورد استفاده برای محاسبه مالیات
  //
  //تعداد سهام
  $marié = strtolower($marié);
  if ($marié === "oui") {
    $nbParts = $enfants / 2 + 2;
  } else {
    $nbParts = $enfants / 2 + 1;
  }
  // ۱ معافیت برای هر فرزند از فرزند سوم به بعد
  if ($enfants >= 3) {
    // نیمه معافیت اضافی برای هر فرزند از سوم به بعد
    $nbParts += 0.5 * ($enfants - 2);
  }
  // درآمد مشمول مالیات
  $revenuImposable = getRevenuImposable($salaire);
  // سربار
  $surcôte = floor($revenuImposable - 0.9 * $salaire);
  // برای مسائل گرد کردن
  if ($surcôte < 0) {
    $surcôte = 0;
  }
  // ضریب خانوادگی
  $quotient = $revenuImposable / $nbParts;
  //در انتهای جدول محدودیت‌ها قرار می‌گیرد تا حلقهٔ زیر را خاتمه دهد
  $limites[count($limites) - 1] = $quotient;
  //محاسبه مالیات
  $i = 0;
  while ($quotient > $limites[$i]) {
    $i++;
  }
  // زیرا $quotient در انتهای جدول $limites قرار گرفته است، حلقه قبلی
  // نمی‌تواند از آرایه $limites فراتر رود
  //اکنون می‌توانیم مالیات را محاسبه کنیم
  $impôt = floor($revenuImposable * $coeffR[$i] - $nbParts * $coeffN[$i]);
  // نتیجه
  return ["impôt" => $impôt, "surcôte" => $surcôte, "taux" => $coeffR[$i]];
}

//revenuImposable = حقوق سالانه – معافیت
// معافیت مالیاتی حداقل و حداکثری دارد
function getRevenuImposable(float $salaire): float {
  
  // نتیجه
  return floor($revenuImposable);
}

توضیحات

  • در اینجا، مالیات با استفاده از آنچه به اصطلاح جدول ترقی‌یافته نامیده می‌شود، محاسبه می‌شود؛
  • خط ۹: تابع strtolower($chaîne) مقدار $chaîne را به حروف کوچک تبدیل می‌کند؛
  • خطوط ۱۰–۱۹: محاسبه تعداد سهام مودی؛
  • خط ۲۱: درآمد مشمول مالیات با استفاده از یک تابع محاسبه می‌شود. همانطور که دیدیم، این مقدار همیشه 0.9*revenusAnnuels نیست. معافیت ۱۰ درصدی در واقع به ۱۲,۵۰۲ یورو محدود شده است؛
  • خط ۲۳: محاسبه هرگونه عوارض اضافی در صورتی که درآمد مشمول مالیات از 0.9*revenusAnnuels تجاوز کند؛
  • رده‌های ۲۵–۲۷: این خطا را که به دلیل اشتباهات گرد کردن، رقم گاهی [$surcôte=-1] می‌شود، اصلاح می‌کند؛
  • خط ۲۹: ضریب خانوادگی؛
  • رده‌های ۳۰–۳۶: این کسر برای تعیین رده مالیاتی مودی استفاده می‌شود؛
  • خط ۴۰: پس از تعیین طبقه مالیاتی مودی، مالیات ناخالص او قابل محاسبه است. تابع floor($x) مقدار صحیح بلافاصله کمتر از [$x] را برمی‌گرداند؛
  • خط ۴۲: اطلاعات محاسبه شده بازگردانده می‌شود؛

تابع [getRevenuImposable] به شرح زیر است:


// ثوابت جهانی
define("ABATTEMENT_DIXPOURCENT_MAX", 12502);
define("ABATTEMENT_DIXPOURCENT_MIN", 437);

// revenuImposable=سالانه حقوق-مزایا
// این فوق‌العاده حداقل و حداکثری دارد
function getRevenuImposable(float $salaire): float {
  // علاوه بر حقوق به میزان ۱۰٪
  $abattement = 0.1 * $salaire;
  //این کسورات نمی‌تواند از ABATTEMENT_DIXPOURCENT_MAX تجاوز کند
  if ($abattement > ABATTEMENT_DIXPOURCENT_MAX) {
    $abattement = ABATTEMENT_DIXPOURCENT_MAX;
  }
  // این فوق‌العاده نمی‌تواند کمتر از ABATTEMENT_DIXPOURCENT_MIN باشد
  if ($abattement < ABATTEMENT_DIXPOURCENT_MIN) {
    $abattement = ABATTEMENT_DIXPOURCENT_MIN;
  }
  //درآمد مشمول مالیات
  $revenuImposable = $salaire - $abattement;
  //سود
  return floor($revenuImposable);
}

نظرات

  • خط ۵: معافیت استاندارد ۱۰ درصد از حقوق سالانه است؛
  • خطوط ۷–۹: این فوق‌العاده نباید از حداکثر فوق‌العاده [ABATTEMENT_DIXPOURCENT_MAX] تجاوز کند؛
  • رده‌های ۱۰–۱۳: معافیت نمی‌تواند کمتر از حداقل معافیت [ABATTEMENT_DIXPOURCENT_MIN] باشد؛
  • خط ۱۵: محاسبه درآمد مشمول مالیات؛

تابع [getDecote] به شرح زیر است:


// ثوابت جهانی
define("PLAFOND_DECOTE_CELIBATAIRE", 1196);
define("PLAFOND_DECOTE_COUPLE", 1970);
define("PLAFOND_IMPOT_COUPLE_POUR_DECOTE", 2627);
define("PLAFOND_IMPOT_CELIBATAIRE_POUR_DECOTE", 1595);

//هرگونه تخفیف را محاسبه می‌کند
function getDecote(string $marié, float $salaire, float $impots): float {
  // در ابتدا، تخفیف صفر
  $décôte = 0;
  // حداکثر مبلغ مالیات برای واجد شرایط شدن جهت تخفیف
  $plafondImpôtPourDécôte = $marié === "oui" ? PLAFOND_IMPOT_COUPLE_POUR_DECOTE : PLAFOND_IMPOT_CELIBATAIRE_POUR_DECOTE;
  if ($impots < $plafondImpôtPourDécôte) {
    // حداکثر مبلغ تخفیف
    $plafondDécôte = $marié === "oui" ? PLAFOND_DECOTE_COUPLE : PLAFOND_DECOTE_CELIBATAIRE;
    // تخفیف نظری
    $décôte = $plafondDécôte - 0.75 * $impots;
    // تخفیف نمی‌تواند از مبلغ مالیات تجاوز کند
    if ($décôte > $impots) {
      $décôte = $impots;
    }
    // هیچ تخفیفی <0
    if ($décôte < 0) {
      $décôte = 0;
    }
  }
  // نتیجه
  return ceil($décôte);
}

نظرات

  • خط ۶: حداکثر مبلغ ناخالص مالیات که برای کاهش مالیات واجد شرایط است. این مبلغ برای افراد مجرد و متأهلین متفاوت است؛
  • خط ۷: اینکه آیا مودی مشمول معافیت مالیاتی است؛
  • خط ۱۱: فرمول مربوط به تخفیف مالیاتی. [plafondDécôte] حداکثر مبلغ تخفیف مالیاتی است. این مبلغ حداکثر در خط ۹ محاسبه می‌شود. در اینجا نیز، این مبلغ به وضعیت مالیاتی مؤدی بستگی دارد – اینکه متأهل است یا مجرد؛
  • رده‌های ۱۳–۱۵: معافیت مالیاتی نمی‌تواند از مالیات ناخالص قابل پرداخت بیشتر باشد. این امر، برای مثال، زمانی صادق است که [impots] در ردیف ۱۱ برابر ۰ باشد؛
  • رده‌های ۱۷–۱۹: برای جلوگیری از گرد شدن به سمت پایین به مقدار –۱؛

تابع [getRéduction] به شرح زیر است:


// ثوابت جهانی
define("PLAFOND_REVENUS_CELIBATAIRE_POUR_REDUCTION", 21037);
define("PLAFOND_REVENUS_COUPLE_POUR_REDUCTION", 42074);
define("VALEUR_REDUC_DEMI_PART", 3797);

//هرگونه کاهش را محاسبه می‌کند
function getRéduction(string $marié, float $salaire, int $enfants, float $impots): float {
  //آستانه درآمد برای برخورداری از کاهش ۲۰٪
  $plafondRevenuPourRéduction = $marié === "oui" ? PLAFOND_REVENUS_COUPLE_POUR_REDUCTION : PLAFOND_REVENUS_CELIBATAIRE_POUR_REDUCTION;
  $plafondRevenuPourRéduction += $enfants * VALEUR_REDUC_DEMI_PART;
  if ($enfants > 2) {
    $plafondRevenuPourRéduction += ($enfants - 2) * VALEUR_REDUC_DEMI_PART;
  }
  // درآمد مشمول مالیات
  $revenuImposable = getRevenuImposable($salaire);
  // کاهش
  $réduction = 0;
  if ($revenuImposable < $plafondRevenuPourRéduction) {
    // کاهش ۲۰ درصدی
    $réduction = 0.2 * $impots;
  }
  // نتیجه
  return ceil($réduction);
}

نظرات

  • رده‌ها ۴–۱۰: برای واجد شرایط بودن جهت کاهش مالیات، درآمد مشمول مالیات (رده‌ی ۱۰) باید کمتر از آستانه‌ای باشد که در رده‌های ۴–۸ محاسبه شده است؛
  • رده‌های ۱۳–۱۶: اگر مؤدی شرایط را احراز کند، مستحق کاهش ۲۰ درصدی مالیات است (رده‌ی ۱۵)؛

4.3.2. نتایج

فایل داده taxpayersdata.txt (متأهل، فرزندان، حقوق):

oui,2,55555
oui,2,50000
oui,3,50000
non,2,100000
non,3,100000
oui,3,100000
oui,5,100000
non,0,100000
oui,2,30000
non,0,200000
oui,3,200000

فایل résultats.txt (ازدواج، فرزندان، حقوق، مالیات، عوارض، تخفیف، کاهش، نرخ مالیات) که نتایج به‌دست‌آمده را نشان می‌دهد:

{"marié":"oui","enfants":"2","salaire":"55555","impôt":2814,"surcôte":0,"décôte":0,"réduction":0,"taux":0.14}
{"marié":"oui","enfants":"2","salaire":"50000","impôt":1384,"surcôte":0,"décôte":384,"réduction":347,"taux":0.14}
{"marié":"oui","enfants":"3","salaire":"50000","impôt":0,"surcôte":0,"décôte":720,"réduction":0,"taux":0.14}
{"marié":"non","enfants":"2","salaire":"100000","impôt":19884,"surcôte":4480,"décôte":0,"réduction":0,"taux":0.41}
{"marié":"non","enfants":"3","salaire":"100000","impôt":16782,"surcôte":7176,"décôte":0,"réduction":0,"taux":0.41}
{"marié":"oui","enfants":"3","salaire":"100000","impôt":9200,"surcôte":2180,"décôte":0,"réduction":0,"taux":0.3}
{"marié":"oui","enfants":"5","salaire":"100000","impôt":4230,"surcôte":0,"décôte":0,"réduction":0,"taux":0.14}
{"marié":"non","enfants":"0","salaire":"100000","impôt":22986,"surcôte":0,"décôte":0,"réduction":0,"taux":0.41}
{"marié":"oui","enfants":"2","salaire":"30000","impôt":0,"surcôte":0,"décôte":0,"réduction":0,"taux":0}
{"marié":"non","enfants":"0","salaire":"200000","impôt":64210,"surcôte":7498,"décôte":0,"réduction":0,"taux":0.45}
{"marié":"oui","enfants":"3","salaire":"200000","impôt":42842,"surcôte":17283,"décôte":0,"réduction":0,"taux":0.41}

نتایج به‌دست‌آمده با نتایج به‌دست‌آمده با استفاده از شبیه‌ساز سازمان امور مالیاتی مطابقت دارد.

4.3.3. نتیجه‌گیری

الگوریتم محاسبه مالیات، حتی در مواردی که ساده به نظر می‌رسند، پیچیده است. ما دیگر به آن بازنمی‌گردیم. در نسخه‌های مختلف، هسته اصلی آن علی‌رغم برخی تغییرات در ارائه، یکسان باقی می‌ماند. بنابراین، تنها روی تغییرات اخیر نظر خواهیم داد.

4.4. نسخه ۲

4.4.1. تغییرات

در نسخه قبلی، داده‌های مورد نیاز برای محاسبه مالیات به‌صورت کدهای سخت در قالب ثابت‌ها و آرایه‌ها درج شده بود. این روش باید اجتناب شود. در نسخه جدید، این داده‌ها به یک فایل خارجی به نام jSON منتقل شده‌اند:

Image

محتویات فایل [taxadmindata.json] به شرح زیر است:


{
    "limites": [9964, 27519, 73779, 156244, 0],
    "coeffR": [0, 0.14, 0.3, 0.41, 0.45],
    "coeffN": [0, 1394.96, 5798, 13913.69, 20163.45],
    "PLAFOND_QF_DEMI_PART": 1551,
    "PLAFOND_REVENUS_CELIBATAIRE_POUR_REDUCTION": 21037,
    "PLAFOND_REVENUS_COUPLE_POUR_REDUCTION": 42074,
    "VALEUR_REDUC_DEMI_PART": 3797,
    "PLAFOND_DECOTE_CELIBATAIRE": 1196,
    "PLAFOND_DECOTE_COUPLE": 1970,
    "PLAFOND_IMPOT_COUPLE_POUR_DECOTE": 2627,
    "PLAFOND_IMPOT_CELIBATAIRE_POUR_DECOTE": 1595,
    "ABATTEMENT_DIXPOURCENT_MAX": 12502,
    "ABATTEMENT_DIXPOURCENT_MIN": 437
}

نسخه جدید [version-02/main.php] به شرح زیر است:


<?php

// پابندی سخت‌گیرانه به انواع اعلام‌شده پارامترهای تابع
declare (strict_types=1);

// تعریف ثابت‌ها
$TAXPAYERSDATA = "taxpayersdata.txt";
$RESULTATS = "resultats.txt";
$TAXADMINDATA = "taxadmindata.json";

//بازیابی محتویات فایل داده‌های مالیاتی
$fileContents = \file_get_contents($TAXADMINDATA);
$erreur = FALSE;
// خطا؟
if (!$fileContents) {
  //خطا ثبت می‌شود
  $erreur = TRUE;
  $message = "Le fichier des données [$TAXADMINDATA] n'existe pas";
}

if (!$erreur) {
  //بازیابی کد jSON از فایل پیکربندی در یک آرایهٔ انجمنی
  $taxAdminData = \json_decode($fileContents, true);
  //خطا؟
  if (!$taxAdminData) {
    //ثبت خطا
    $erreur = TRUE;
    $message = "Le fichier de données jSON [$TAXADMINDATA] n'a pu être exploité correctement";
  }
}

//خطا؟
if ($erreur) {
  print "$message\n";
  exit;
}

// فایل نتایج را باز کنید
$résultats = fopen($RESULTATS, "w");
if (!$résultats) {
  print "Impossible de créer le fichier des résultats [$RESULTATS]\n";
  //خروجی
  exit;
}

// باز کردن فایل داده‌های مالیات‌دهنده
$taxpayersdata = fopen($TAXPAYERSDATA, "r");
if (!$taxpayersdata) {
  print "Impossible d'ouvrir le fichier des contribuables [$TAXPAYERSDATA]\n";
  //خروجی
  exit;
}

// پردازش خط فعلی فایل داده
while ($ligne = fgets($taxpayersdata, 100)) {
  // حذف هر کاراکتر پایان خط
  $ligne = cutNewLineChar($ligne);
  //بازیابی سه فیلد «married:children:salary» که $ligne را تشکیل می‌دهند
  list($marié, $enfants, $salaire) = explode(",", $ligne);
  //مالیات محاسبه می‌شود
  $result = calculImpot($taxAdminData, $marié, (int) $enfants, (int) $salaire);
  //نتیجه در فایل نتایج نوشته می‌شود
  $result = ["marié" => $marié, "enfants" => $enfants, "salaire" => $salaire] + $result;
  fputs($résultats, \json_encode($result, JSON_UNESCAPED_UNICODE) . "\n");
  //رکورد بعدی
}
// بستن فایل‌ها
fclose($taxpayersdata);
fclose($résultats);

// پایان
exit;

// --------------------------------------------------------------------------
function cutNewLinechar(string $ligne) {

  //پایان
  return($ligne);
}

//محاسبه مالیات
// --------------------------------------------------------------------------
function calculImpot(array $taxAdminData, string $marié, int $enfants, float $salaire) {
  // $marié: بله، نه
  // $enfants: تعداد فرزندان
  //$salaire: حقوق سالانه
  // $taxAdminData: داده‌های اداره مالیات
  //
  // محاسبه مالیات شامل فرزندان
  $result1 = calculImpot2($taxAdminData, $marié, $enfants, $salaire);
  $impot1 = $result1["impôt"];
  //محاسبه مالیات بدون احتساب فرزندان
  if ($enfants != 0) {
    $result2 = calculImpot2($taxAdminData, $marié, 0, $salaire);
    $impot2 = $result2["impôt"];
    // اعمال سقف ضریب خانوادگی
    if ($enfants < 3) {
      // $PLAFOND_QF_DEMI_PART یورو برای دو فرزند اول
      $impot2 = $impot2 - $enfants * $taxAdminData["PLAFOND_QF_DEMI_PART"];
    } else {
      //$PLAFOND_QF_DEMI_PART یورو برای دو فرزند اول، دو برابر آن برای فرزندان بعدی
      $impot2 = $impot2 - 2 * $taxAdminData["PLAFOND_QF_DEMI_PART"] - ($enfants - 2) * 2 * $taxAdminData["PLAFOND_QF_DEMI_PART"];
    }
  } else {
    $impot2 = $impot1;
    $result2 = $result1;
  }
  // بالاترین مبلغ مالیات در نظر گرفته می‌شود، همراه با نرخ و عوارض مربوطه
  if ($impot1 > $impot2) {
    $impot = $impot1;
    $taux = $result1["taux"];
    $surcôte = $result1["surcôte"];
  } else {
    $surcôte = $impot2 - $impot1 + $result2["surcôte"];
    $impot = $impot2;
    $taux = $result2["taux"];
  }
  // محاسبه هرگونه معافیت مالیاتی
  $décôte = getDecote($taxAdminData, $marié, $salaire, $impot);
  $impot -= $décôte;
  // محاسبه هرگونه معافیت مالیاتی
  $réduction = getRéduction($taxAdminData, $marié, $salaire, $enfants, $impot);
  $impot -= $réduction;
  // نتیجه
  return ["impôt" => floor($impot), "surcôte" => $surcôte, "décôte" => $décôte, "réduction" => $réduction, "taux" => $taux];
}

// --------------------------------------------------------------------------
function calculImpot2(array $taxAdminData, string $marié, int $enfants, float $salaire) {
  // $marié: بله، نه

  // نتیجه
  return ["impôt" => $impôt, "surcôte" => $surcôte, "taux" => $coeffR[$i]];
}

//revenuImposable=حقوق سالانه-مزایا
// مبلغ کمک‌هزینه حداقل و حداکثر دارد
function getRevenuImposable(array $taxAdminData, float $salaire): float {

  // نتیجه
  return floor($revenuImposable);
}

// هرگونه کاهش را محاسبه می‌کند
function getDecote(array $taxAdminData, string $marié, float $salaire, float $impots): float {

  // نتیجه
  return ceil($décôte);
}

//هرگونه کاهش را محاسبه می‌کند
function getRéduction(array $taxAdminData, string $marié, float $salaire, int $enfants, float $impots): float {

  // نتیجه
  return ceil($réduction);
}

نظرات

  • خطوط ۱۱–۱۹: تلاشی برای خواندن محتویات فایل jSON، با نام [TAXADMINDATA]، انجام می‌شود؛
  • خطوط ۲۱–۳۰: اگر فایل jSON با موفقیت خوانده شده باشد، محتویات آن در آرایهٔ asociative [$taxAdminData] رمزگشایی می‌شود؛
  • خطوط ۳۲–۳۶: اگر در حین هر یک از دو عملیات قبلی خطایی رخ دهد، یک پیام خطا به کنسول نوشته می‌شود و برنامه خاتمه می‌یابد؛
  • تفاوت با نسخه 01 در این است که در اینجا داده‌های سازمان مالیاتی (آرایه‌ها و ثابت‌ها) در آرایهٔ asociative [$taxAdminData] ذخیره می‌شوند، در حالی که در نسخه 01 در آرایه‌ها و ثابت‌های سراسری ذخیره می‌شدند. ماهیت سراسری این ثابت‌ها است که این دو نسخه را از هم متمایز می‌کند:
    • در نسخه 01، ثابت‌ها برای همه توابع در [main.php] قابل دسترس بودند؛
    • برای دستیابی به همان نتیجه در نسخه 02، آرایه asociative [$taxAdminData] باید به عنوان پارامتر به همه توابع ارسال شود (خطوط 83، 129، 138، 145، 152);
  • هر تابع در نسخه 02 باید از محتویات آرایه [$taxAdminData] استفاده کند؛
  • خطوط ۸۳–۱۲۶: در تابع [calculerImpot]، در جایی که قبلاً از ثابت‌های سراسری یا آرایه‌های [limites, coeffR, coeffN] استفاده می‌شد، اکنون از محتویات آرایه [$taxAdminData] که به عنوان پارامتر دریافت شده است، استفاده می‌شود (خطوط 99، 102);
  • تمام توابع دیگر به همین شکل بازنویسی شده‌اند؛

نتایج به‌دست‌آمده با نتایج نسخه قبلی یکسان است.

4.4.2. نتیجه‌گیری

نسخه ۰۲ بسیار انعطاف‌پذیرتر از نسخه ۰۱ است. در سال ۲۰۲۰، الگوریتم محاسبه مالیات احتمالاً همانند سال ۲۰۱۹ خواهد بود. تنها محدوده‌های مالیاتی و ثابت‌های محاسباتی تغییر خواهند کرد. در آن صورت، صرفاً به روزرسانی فایل [taxadmindata.json] کافی خواهد بود. در نسخه 01، برای اصلاح محدوده‌های مالیاتی و ثابت‌های محاسباتی باید وارد کد شوید. با این حال، احتمالاً کسانی که نیاز به تغییر مقادیر محدوده‌های مالیاتی و ثابت‌های محاسباتی دارند، به کد الگوریتم دسترسی ندارند.