ابحث عن طريقة احتساب المعاش التقاعدي في السعودية، وستجد أن الإجابة الأكثر تداولًا هي هذه:
الراتب الأساسي الأخير × أشهر الخدمة ÷ 480
أُعيد نشرها آلاف المرات. وتظهر بصياغة قريبة منها في حاسبة التقاعد المجانية التي تحتلّ حاليًا المركز الثالث في نتائج البحث السعودية. وهي خاطئة من ثلاث جهات في آنٍ واحد.
هي خاطئة في الأجر: فالمؤسسة العامة للتأمينات الاجتماعية لا تعتمد الراتب الأساسي الأخير، بل متوسط أجور الأشهر الأربعة والعشرين الأخيرة الخاضعة للاشتراك — ثم تضع حدًّا أعلى لهذا المتوسط. وهي خاطئة في المقسوم: فالرقم 480 لا ينطبق إلا على المدة اللاحقة لتاريخ 1/1/1422هـ، أما المدة السابقة فتُحتسب على 600. وهي ساكتة تمامًا عن أحدث ما تغيّر — تعديلات نظام التأمينات الاجتماعية النافذة في الأربعاء 27/12/1445هـ الموافق 3 يوليو 2024م، التي نقلت السن النظامية للتقاعد من رقم ثابت إلى جدول متدرّج.
كل واحدة من هذه الثلاث خطأ قابل للنشر في نظام إنتاجي. ومجتمعةً، هي الفرق بين أن تخبر شخصًا أنه يتقاعد في الستين على 5,000 ريال شهريًا، وأن تخبره أنه يتقاعد في الحادية والستين وثمانية أشهر على 4,750.
هذا الدرس يبني المحرّك بشكل صحيح.
ما الذي ستبنيه
وحدة TypeScript تستقبل تواريخ المشترك وسجلّ أجوره وتعيد تقييم استحقاق قابلًا للدفاع عنه:
- تصنيف النظام — ثلاث فئات لا فئتان، يحدّدها شرطان يجب تحقّقهما معًا
- السن النظامية — ثابت هجري لفئة، وجدول ميلادي لفئة، و65 سنة لفئة ثالثة
- التأهّل للتقاعد المبكر — جدول ثانٍ، من 300 إلى 360 شهرًا
- وعاء الأجر — متوسط 24 شهرًا مع حدّ أعلى، أو متوسط أعلى 180 شهرًا، بحسب النظام
- المعاش — موزّعًا على نسبتَي الاستحقاق 600 و480 عند حدّ 1/1/1422هـ
كل قاعدة يغطّيها اختبار، وأحد هذه الاختبارات يعيد إنتاج المثال المنشور من التأمينات نفسها بالريال الواحد.
المتطلبات المسبقة
- Node.js 20 أو أحدث و TypeScript 5 أو أحدث
- إلمام بـ
Intl.DateTimeFormatوالتقويمات غير الميلادية - لا حاجة لبيانات اعتماد من التأمينات — هذا محرّك حسابي خالص يعمل دون اتصال
ويُستحسن أن تقرأ درس محرّك اشتراكات التأمينات إن لم تكن قد فعلت. ذاك يعالج الاشتراكات الداخلة، وهذا يعالج المنافع الخارجة، ويتشاركان نموذج المشترك ولا يكادان يتشاركان شيئًا آخر.
الخطوة 1: ثلاثة أنظمة لا نظامان
أكثر الأخطاء المعمارية شيوعًا هنا هو المتغيّر المنطقي. يقرأ المهندس أن النظام تغيّر في يوليو 2024 فيكتب isNewLaw. الفئات ثلاث، والفئة الوسطى هي التي يعجز المتغيّر المنطقي عن تمثيلها.
قصر مجلس الوزراء تطبيق نظام التأمينات الاجتماعية الجديد على الملتحقين الجدد بسوق العمل ممن ليست لديهم مدد اشتراك سابقة. أما المشتركون الحاليون فيستمرّون على الأحكام القائمة — باستثناء الأحكام المتصلة بالسن النظامية للتقاعد وبالمدد المؤهّلة لاستحقاق المعاش قبل بلوغها. هذا الاستثناء هو أصل المشكلة كلها: فهو ينشئ فئة وسطى تحكمها معادلة المنافع القديمة وقواعد السن الجديدة في الوقت نفسه.
والانتماء إلى هذه الفئة الوسطى ليس تلقائيًا. إنه يشترط تحقّق شرطين معًا، يُقاسان في 3 يوليو 2024:
- أن يكون عمر المشترك أقل من 50 سنة هجرية، و
- أن تكون لديه مدد اشتراك سابقة أقل من 240 شهرًا
فإن تخلّف أحد الشرطين، لم يتغيّر لك شيء على الإطلاق.
export const REFORM_DATE = new Date('2024-07-03T00:00:00Z'); // 27/12/1445H
export const ACCRUAL_SPLIT_DATE = new Date('2001-03-26T00:00:00Z'); // 1/1/1422H
export type Regime = 'legacy' | 'amended' | 'new';
export function classifyRegime(s: Subscriber): Regime {
const joinedAfterReform =
s.firstRegisteredAt.getTime() >= REFORM_DATE.getTime();
// النظام الجديد للملتحقين الجدد فعلًا. والعائد إلى العمل بمدد سابقة
// ليس ملتحقًا جديدًا، مهما كان تاريخ تسجيله الأخير قريبًا.
if (joinedAfterReform && s.monthsAtReform === 0) return 'new';
const ageHijriAtReform = hijriYearsBetween(s.dateOfBirth, REFORM_DATE);
const covered = ageHijriAtReform < 50 && s.monthsAtReform < 240;
return covered ? 'amended' : 'legacy';
}انتبه إلى الشقّ الثاني من اختبار new. فمن عمل ستّ سنوات ثم ترك العمل ثم سُجّل من جديد في سبتمبر 2024 لديه تاريخ تسجيل لاحق للتعديلات، وهو قطعًا ليس ملتحقًا جديدًا. والاعتماد على التاريخ وحده ينقله بصمت إلى نظام له وعاء أجر مختلف وسنّ تقاعد عند 65.
الشرطان معًا، أو لا شيء. من عمره 47 سنة ولديه 21 سنة اشتراك يبقى على الأحكام القائمة. ومن عمره 51 سنة ولديه 8 سنوات يبقى على الأحكام القائمة. ولا ينتقل إلى الجدول إلا المشترك الصغير في السنّ والقصير في المدة معًا.
الخطوة 2: خطأ التقويم الذي يكلّف سنتين
بموجب الأحكام القائمة، السن النظامية للتقاعد ستون سنة. وتكاد كل التطبيقات تكتب صورة من هذا:
// خطأ — يقارن عمرًا ميلاديًا بعتبة هجرية
const age = (Date.now() - dateOfBirth.getTime()) / (365.2425 * 86400000);
const eligible = age >= 60;السنّ القائمة عند ستين هي ستون سنة هجرية. والسنة الهجرية نحو 354.37 يومًا. وستون منها تساوي قرابة 21,262 يومًا، أي نحو 58.2 سنة ميلادية. فمقارنة عمر ميلادي بالرقم 60 تؤخّر المشترك قرابة سنتين بعد التاريخ الذي استحقّ فيه فعلًا.
وليست هذه مسألة تقريب، بل هي سبب أن الجدول المعدّل يبدأ حيث يبدأ. فحين نشرت التأمينات الجدول الجديد عبّرت عن الأعمار بالسنوات الميلادية، وجاءت شريحة «دون تغيير» في أعلاه عند 58 لا عند 60. والملخّص الرسمي يصف النطاق الناتج بأنه بين 58 و65 سنة ميلادية. ولا تتصالح هاتان الحقيقتان إلا حين تعلم أن الستين القديمة كانت هجرية.
لذلك لا تُجرِ التحويل. قيّم كل نظام على التقويم الذي كُتبت به قاعدته:
const HIJRI = new Intl.DateTimeFormat('en-u-ca-islamic-umalqura', {
year: 'numeric', month: 'numeric', day: 'numeric', timeZone: 'UTC',
});
function hijriParts(date: Date) {
const p = Object.fromEntries(
HIJRI.formatToParts(date).map((x) => [x.type, x.value]),
);
return { y: Number(p.year), m: Number(p.month), d: Number(p.day) };
}
/** السنوات الهجرية المكتملة بين تاريخين. */
export function hijriYearsBetween(from: Date, to: Date): number {
const a = hijriParts(from), b = hijriParts(to);
let years = b.y - a.y;
if (b.m < a.m || (b.m === a.m && b.d < a.d)) years -= 1;
return years;
}استخدم islamic-umalqura تحديدًا. فهو تقويم أم القرى، وهو الذي تعمل عليه الدولة فعليًا؛ أما تقويم islamic العام فهو تقريب جدولي ينزاح بيوم، وهذا كافٍ لنقل تاريخ ميلاد عبر حدّ الشهر.
الخطوة 3: جدول السن النظامية
بالنسبة للفئة المشمولة بالتعديلات، تنشر التأمينات السن النظامية بوصفها دالّة في عمر المشترك الميلادي يوم 3 يوليو 2024. وترتفع بأربعة أشهر عن كل سنة من صغر السنّ:
| العمر في 3 يوليو 2024 | السن النظامية |
|---|---|
| 48.5 فأكثر | دون تغيير |
| من 48 إلى أقل من 48.5 | 58 سنة و4 أشهر |
| من 47 إلى أقل من 48 | 58 سنة و8 أشهر |
| من 46 إلى أقل من 47 | 59 سنة |
| من 43 إلى أقل من 44 | 60 سنة |
| من 40 إلى أقل من 41 | 61 سنة |
| من 29 إلى أقل من 30 | 64 سنة و8 أشهر |
| أقل من 29 | 65 سنة |
بدلًا من ترميز عشرين شريحة يدويًا، اشتقّها. الجدول كله ينهار إلى تعبير واحد:
/** يعيد السن النظامية للتقاعد بالأشهر الكاملة. */
export function amendedRetirementAgeMonths(gregorianAgeAtReform: number): number {
const a = gregorianAgeAtReform;
if (a >= 48.5) return 58 * 12; // دون تغيير
if (a >= 48) return 58 * 12 + 4; // 58 سنة و4 أشهر
if (a < 29) return 65 * 12; // قاع الجدول
return 704 + (47 - Math.floor(a)) * 4; // +4 أشهر عن كل سنة صغر
}ثم تحقّق من الاشتقاق في مقابل الجدول المنشور بدلًا من الثقة به. فالثابت 704 هو 58 سنة و8 أشهر، أي قيمة شريحة السابعة والأربعين، وكل صفّ آخر ينتج عن الحساب.
الخطوة 4: الجدول الثاني — التقاعد المبكر
للتقاعد المبكر انتقاله الخاص، وهو يتحرّك بخطوات من اثني عشر شهرًا لا أربعة. ويرتبط بطول مدة الاشتراك في 3 يوليو 2024، لا بالعمر:
| مدة الاشتراك في 3 يوليو 2024 | الأشهر المطلوبة |
|---|---|
| 240 شهرًا فأكثر | 300 |
| من 19 إلى أقل من 20 سنة | 300 |
| من 18 إلى أقل من 19 سنة | 312 |
| من 15 إلى أقل من 16 سنة | 348 |
| أقل من 15 سنة | 360 |
export function earlyRetirementMonthsRequired(
regime: Regime,
monthsAtReform: number,
): number {
if (regime === 'legacy') return 300;
if (regime === 'new') return 360;
const yearsAtReform = Math.floor(monthsAtReform / 12);
if (yearsAtReform >= 19) return 300;
return Math.min(360, 300 + (19 - yearsAtReform) * 12);
}الملخّص الأكثر تداولًا لهذا التغيير على وسائل التواصل يذكر حالة 19 سنة فأكثر وحالة ما بين 15 و19، ثم يقف. وهو يغفل القاع: فمن لديه أقل من خمس عشرة سنة في تاريخ التعديلات يحتاج 360 شهرًا كاملة. وهذه هي الفئة الأكثر احتمالًا أن تخطّط بناءً على هذه القاعدة، والأقلّ احتمالًا أن تكون قد سمعت حقيقتها.
انتبه للحافّة. من لديه 18 سنة و11 شهرًا في 3 يوليو 2024 يحتاج 312 شهرًا. وشهر واحد إضافي من الخدمة قبل ذلك التاريخ كان سينقله إلى شريحة 19 سنة ويكلّفه 300 فقط. شهر واحد في التسجيل بأثر رجعي يزحزح خطّ النهاية سنةً كاملة.
الخطوة 5: وعاء الأجر
نظامان، وطريقتا تجميع مختلفتان تمامًا. ولهذا لا يمكن لدالّة averageWage() واحدة أن تخدم المحرّك.
النظامان القائم والمعدّل يعتمدان متوسط أجور الأشهر الأربعة والعشرين الأخيرة الخاضعة للاشتراك. لكن هذا المتوسط مقيَّد: تحدّه اللائحة بـ 150% من أجر الاشتراك في بداية السنوات الخمس الأخيرة. وهو قيد موجود لمنع رفع الأجر قبيل التقاعد لتضخيم معاش العمر كله.
export function averageWageLegacy(
last24Wages: number[],
wageAtStartOfLast5Years: number,
): number {
if (last24Wages.length !== 24) {
throw new Error(`expected 24 monthly wages, received ${last24Wages.length}`);
}
const mean = last24Wages.reduce((a, b) => a + b, 0) / 24;
const cap = wageAtStartOfLast5Years * 1.5;
return Math.min(mean, cap);
}أما النظام الجديد فيفعل شيئًا مختلفًا بنيويًا: يأخذ متوسط أعلى 180 شهرًا من الأجور الخاضعة للاشتراك عبر المسار المهني كله.
export function averageWageNew(allMonthlyWages: number[]): number {
if (allMonthlyWages.length < 180) {
throw new Error(
`need at least 180 insurable months, received ${allMonthlyWages.length}`,
);
}
const top = [...allMonthlyWages].sort((a, b) => b - a).slice(0, 180);
return top.reduce((a, b) => a + b, 0) / 180;
}والنتيجة تستحقّ التصريح بها، لأنها تقلب قاعدة شائعة في تخطيط التقاعد. ففي الوعاء القائم، إنهاء المسار المهني على أجر منخفض — الانتقال لدوام جزئي أو النزول درجة — يقتطع من المعاش مباشرةً، لأن الأشهر الأربعة والعشرين الأخيرة هي الوعاء. أما في الوعاء الجديد فلا يكاد يفعل شيئًا، لأن تلك الأشهر المنخفضة ببساطة لا تدخل ضمن أعلى 180. والنصيحة المبنية على النظام القديم تضلّل فعليًا كل من هو على الجديد.
ورفض المصفوفة ذات الطول الخاطئ أهمّ ممّا يبدو. فكلتا الدالّتين كانتا ستحسبان متوسط ما يُمرَّر إليهما براحة تامة، وتصدير رواتب يعيد 23 شهرًا بصمت ينتج رقمًا معقولًا وخاطئًا ببضع نقاط مئوية — وهو أصعب أصناف الأخطاء اكتشافًا لاحقًا.
الخطوة 6: مقسومان، والفاصل 1/1/1422هـ
نظام التأمينات الاجتماعية الصادر بالمرسوم الملكي م/33 بدأ العمل به في 1/1/1422هـ، الموافق 26 مارس 2001. ولذلك تُقسم مدة الاشتراك إلى مدة سابقة ومدة لاحقة، وتُحتسبان بنسبتين مختلفتين: المدة السابقة بواقع جزء من خمسين من متوسط الأجر عن كل سنة، واللاحقة بواقع جزء من أربعين. وبالأشهر، هذا يعني 600 و480.
export function splitServiceMonths(serviceStart: Date, serviceEnd: Date) {
const total = gregorianMonthsBetween(serviceStart, serviceEnd);
if (serviceStart >= ACCRUAL_SPLIT_DATE) {
return { priorMonths: 0, subsequentMonths: total };
}
if (serviceEnd <= ACCRUAL_SPLIT_DATE) {
return { priorMonths: total, subsequentMonths: 0 };
}
const priorMonths = gregorianMonthsBetween(serviceStart, ACCRUAL_SPLIT_DATE);
return { priorMonths, subsequentMonths: total - priorMonths };
}
export function pensionLegacy(
averageWage: number,
priorMonths: number,
subsequentMonths: number,
): number {
return averageWage * (priorMonths / 600 + subsequentMonths / 480);
}
export function pensionNew(averageWage: number, contributionMonths: number): number {
return averageWage * contributionMonths * (0.0225 / 12); // 2.25% سنويًا
}تنشر التأمينات مثالًا محلولًا يثبّت هذا بدقّة: 60 شهرًا من المدة السابقة تنتج 1,000 ريال، و180 شهرًا من المدة اللاحقة تنتج 3,750. وكلاهما يقود إلى متوسط أجر واحد قدره 10,000 — وهي ملاحظة مفيدة، لأنها تعني أن المثال متّسق داخليًا وصالح للاستخدام كبيانات اختبار.
والآن قِس كلفة الخطأ الذي يقع فيه الجميع. المسار نفسه بمدة 240 شهرًا، محسوبًا كلّه على 480 كما تأمر المعادلة المتداولة:
الصحيح: 10,000 × (60/600 + 180/480) = 4,750 ريالًا
الخاطئ: 10,000 × (240/480) = 5,000 ريالًا
مئتان وخمسون ريالًا شهريًا. كل شهر، وطوال بقية حياة المشترك. والخطأ غير مرئي في المخرجات، لأن 5,000 يبدو معاشًا معقولًا تمامًا.
الخطوة 7: تركيب التقييم
export function assessPension(s: Subscriber) {
const regime = classifyRegime(s);
const totalMonths = gregorianMonthsBetween(s.serviceStart, s.assessmentDate);
const statutoryAgeMonths =
regime === 'new' ? 65 * 12
: regime === 'amended'
? amendedRetirementAgeMonths(gregorianAgeAtReform(s.dateOfBirth))
: null; // القائم يُقاس بستين سنة هجرية، لا بثابت ميلادي
const reachedStatutoryAge =
regime === 'legacy'
? hijriYearsBetween(s.dateOfBirth, s.assessmentDate) >= 60
: gregorianMonthsBetween(s.dateOfBirth, s.assessmentDate)
>= statutoryAgeMonths!;
const earlyRequired = earlyRetirementMonthsRequired(regime, s.monthsAtReform);
const minimumForAgePension = regime === 'new' ? 180 : 120;
let entitlement: 'age_pension' | 'early_pension' | 'lump_sum_only';
if (reachedStatutoryAge && totalMonths >= minimumForAgePension) {
entitlement = 'age_pension';
} else if (totalMonths >= earlyRequired) {
entitlement = 'early_pension';
} else {
entitlement = 'lump_sum_only';
}
let monthlyPension = 0;
if (entitlement !== 'lump_sum_only') {
if (regime === 'new') {
monthlyPension = pensionNew(averageWageNew(s.allMonthlyWages!), totalMonths);
} else {
const { priorMonths, subsequentMonths } =
splitServiceMonths(s.serviceStart, s.assessmentDate);
const wage = averageWageLegacy(s.last24Wages!, s.wageAtStartOfLast5Years!);
monthlyPension = pensionLegacy(wage, priorMonths, subsequentMonths);
}
}
return { regime, statutoryAgeMonths, totalMonths,
earlyRetirementMonthsRequired: earlyRequired,
entitlement, monthlyPension };
}إعادة statutoryAgeMonths: null للنظام القائم مقصودة. فلا يوجد ثابت ميلادي صحيح يُوضع هناك، واختراع واحد — 58 أو 58.2 أو 60 — هو الطريق الذي يعود منه خطأ التقويم على يد أول من يلمس الملف بعدك. القيمة الفارغة تُجبر المستدعي على السؤال: في أي تقويم نحن؟
ولاحظ كذلك أن التصنيف يحدّد الاستحقاق، والاستحقاق يحدّد هل هناك معاش أصلًا. فمن قصُر عن العتبتين معًا يستحقّ تعويض الدفعة الواحدة لا معاشًا شهريًا، والمحرّك الذي يعيد له رقم معاش قد أجاب عن سؤال لم يطرحه أحد.
اختبار التنفيذ
اختبر في مقابل قيم منشورة، لا في مقابل إعادة تنفيذك أنت للحساب نفسه. الاختبارات الثلاثة التي تستحقّ مكانها:
test('the two anchor dates are the Hijri dates the law names', () => {
const f = new Intl.DateTimeFormat('en-u-ca-islamic-umalqura',
{ year: 'numeric', month: 'numeric', day: 'numeric', timeZone: 'UTC' });
assert.equal(f.format(REFORM_DATE), '12/27/1445 AH');
assert.equal(f.format(ACCRUAL_SPLIT_DATE), '1/1/1422 AH');
});
test('60 Hijri years is about 58.2 Gregorian years, not 60', () => {
const born = new Date('1960-01-01T00:00:00Z');
let d = new Date('2016-01-01T00:00:00Z');
while (hijriYearsBetween(born, d) < 60) d = new Date(d.getTime() + 86400000);
const gregorianYears = (d.getTime() - born.getTime()) / (365.2425 * 86400000);
assert.ok(gregorianYears > 58.1 && gregorianYears < 58.3);
});
test("GOSI's published worked example reproduces exactly", () => {
assert.equal(pensionLegacy(10000, 60, 0), 1000);
assert.equal(pensionLegacy(10000, 0, 180), 3750);
assert.equal(pensionLegacy(10000, 60, 180), 4750);
});أضف اختبار خصائص على الجدول أيضًا — لكل عمر من 20 إلى 60 بخطوات ربع السنة، يجب أن تبقى السن النظامية داخل نطاق 58 إلى 65، وألّا تنخفض أبدًا كلما صغر المشترك. هذا الاختبار وحده يلتقط انزياحًا بواحد في حساب الشرائح لن يكشفه أي قدر من الفحص العشوائي.
مجموعة الاختبارات الكاملة خلف هذا الدرس سبعة عشر اختبارًا، وكلها تنجح قبل أن يقترب أيّ من هذا الكود من نظام رواتب.
استكشاف الأخطاء
تواريخ التقاعد تتأخّر نحو 1.8 سنة. أنت تقارن عمرًا ميلاديًا بالرقم 60. راجع الخطوة 2.
العائد إلى العمل على النظام الخاطئ. اختبار new لديك يعتمد على تاريخ التسجيل وحده. يجب أن يشترط كذلك أن تكون مدد الاشتراك السابقة صفرًا.
المعاش أعلى ببضع نقاط مئوية لطويلي الخدمة. أنت تقسم المسار كله على 480. افصل عند 26 مارس 2001.
ترقية متأخّرة تنتج معاشًا غير معقول. لم تطبّق حدّ الـ150% في مقابل الأجر في بداية السنوات الخمس الأخيرة.
التواريخ الهجرية تنزاح بيوم. استخدمت تقويم islamic بدل islamic-umalqura.
ما لا يفعله هذا المحرّك عمدًا
التصريح بالحدود أهمّ في كود الامتثال منه في معظم البرمجيات:
- خصم التقاعد المبكر في النظام الجديد. يتيح النظام الجديد التقاعد قبل السن النظامية بعشر سنوات بشرط 360 شهر اشتراك، مع تطبيق خصم على المعاش. ونِسب هذا الخصم لم نتمكّن من تأكيدها من مصدر أوّلي، لذلك يؤهّل المحرّك المشترك ويتوقّف قبل تخفيض الرقم. لا تخمّن هذه النسب.
- علاوات المعالين، والحدّ الأدنى للعجز غير المهني، والحدّ الأدنى للمعاش.
- ضمّ المدد بين نظام التقاعد المدني والتأمينات الاجتماعية، وله قواعد نقل خاصة به.
كل ما لا تستطيع الاستشهاد بمصدره، اتركه واعرضه فجوةً صريحة. فمحرّك معاشات يعيد رقمًا خاطئًا بثقة أسوأ بكثير من محرّك يعيد نطاقًا وملاحظة.
الخطوات التالية
- المعاش ليس المبلغ الوحيد المستحقّ عند نهاية المسار المهني. مكافأة نهاية الخدمة بموجب المادتين 84 و85 استحقاق منفصل يدفعه صاحب العمل فوقه — احسبها عبر حاسبة مكافأة نهاية الخدمة.
- لجانب الاشتراكات من سجلّ المشترك نفسه، راجع محرّك اشتراكات التأمينات والتسوية.
- ولما يُخصم فعليًا من الراتب شهريًا، ولماذا تتبع النسبة الموظف لا المنشأة، راجع نسبة خصم التأمينات موضّحة.
- وإن انتهى المسار بالفصل لا بالتقاعد، فإن محرّك تسوية إنهاء الخدمة يحتسب ذلك المسار.
الخاتمة
السبب في أن هذا المجال ينتج هذا القدر من البرمجيات الخاطئة بثقة هو أن كل قاعدة على حدة تبدو بسيطة. ستون سنة. اقسم على 480. خذ متوسط راتبك. كل واحدة قريبة من الصحّة بما يكفي لألّا تبدو المخرجات مقلقة أبدًا، ولا واحدة منها تصمد أمام النصّ النظامي.
الأمور الثلاثة الجديرة بالحمل معك: السن النظامية في الأحكام القائمة تُقاس بالسنوات الهجرية، فستون منها تصل عند نحو 58.2 ميلادية؛ ومدة الاشتراك تُقسم عند 1/1/1422هـ إلى نسبتَي استحقاق لا واحدة؛ وتعديلات يوليو 2024 أنشأت فئة وسطى تحكمها قواعد منافع قديمة وقواعد سنّ جديدة في آنٍ واحد، ولا يستطيع أي متغيّر منطقي تمثيلها.
ابنِ التصنيف أولًا والحساب ثانيًا. الحساب هو النصف السهل.
هل تدير أنظمة رواتب أو موارد بشرية في السعودية ولست واثقًا من أن أرقام نهاية الخدمة والمعاش لديك تعكس تعديلات 2024؟ تحدّث إلينا — سنراجع منطق الاحتساب في مقابل القواعد المنشورة ونخبرك أين الفجوات.