كل نظام موارد بشرية يعمل في السعودية يحمل التزامًا ماليًا يكبر كل يوم ولا يظهر على أي فاتورة: رصيد الإجازة السنوية. المادة 109 من نظام العمل تمنح كل موظف ما لا يقل عن 21 يومًا من الإجازة المدفوعة سنويًا — ترتفع إلى 30 يومًا بعد خمس سنوات متصلة من الخدمة — والمادة 111 تحوّل كل ما لم يُستخدم منها إلى نقد يوم مغادرته العمل.
معظم الأنظمة تخطئ في المواضع الثلاثة نفسها. تمنح الاستحقاق دفعة واحدة في أول السنة بدل أن تراكمه يومًا بيوم. وتطبّق معدل الثلاثين يومًا على كامل السنة التي تقع فيها الذكرى الخامسة بدل المزج بين المعدلين حول تاريخ الذكرى نفسه. وتخزّن الرصيد كعدد عشري من الأيام مضروبًا في أجر يومي عشري، وهكذا تنتهي تسوية نهائية بفارق 3 هللات وينتهي ملف لدى المحكمة العمالية على مكتب أحدهم.
في هذا الدرس نبني المحرك بالطريقة الصحيحة: دالة تراكم تتبع نص النظام، وسجل يفسّر كل رصيد يعرضه، وحساب تسوية يُخرج الرقم نفسه الذي يصل إليه خبير المحكمة العمالية. وإن أردت الجانب النظامي بلغة الموارد البشرية قبل الكود، فابدأ بدليلنا المفصّل عن حساب رصيد الإجازات السنوية في نظام العمل. كل ما نبنيه هنا هو المنطق الذي تعمل به حاسبة رصيد الإجازات المجانية على موقعنا، فاستخدمها للتحقق من تنفيذك في أي خطوة.
المتطلبات المسبقة
قبل البدء تأكد من توفر:
- Node.js 20 أو أحدث
- TypeScript 5 أو أحدث (
npm install -D typescript vitest) - إلمام أساسي بحساب التواريخ في JavaScript
- نسخة من المواد 109 إلى 111 من نظام العمل مفتوحة في تبويب مجاور — سنتبع النص لا الشائع
لا حاجة لأي إطار عمل. المحرك مكتبة TypeScript خالصة يمكنك وضعها في مسار API في Next.js أو مهمة رواتب دورية أو دالة Lambda.
ماذا ستبني
مكتبة صغيرة باسم saudi-leave-engine تكشف أربع دوال:
accruedDays(hireDate, asOf, policy)— التراكم النظامي من تاريخ المباشرة إلى أي تاريخ، مع معالجة الانتقال من 21 إلى 30 عند ذكرى المباشرة لا عند رأس السنةleaveBalance(employee, ledger, asOf)— المتراكم ناقص المستخدم، من سجل أحداثexitCashOut(employee, ledger, exitDate)— رقم تسوية المادة 111 بالهللاتleaveLiability(employees, asOf)— المخصص الذي ينبغي لفريق المالية قيده شهريًا
مع حزمة اختبارات تثبّت كل قاعدة نظامية في سيناريو يمكنك عرضه على مدقق.
الخطوة 1: اقرأ النظام قبل كتابة المعادلة
ثلاث مواد تقوم بكل العمل. أتقن شكلها يصبح الكود شبه آلي.
المادة 109 تحدد الاستحقاق: لا يقل عن 21 يومًا من الإجازة السنوية، يرتفع إلى ما لا يقل عن 30 يومًا متى أتمّ العامل خمس سنوات متصلة لدى صاحب العمل نفسه. تفصيلان مهمان للكود. الأول أن هذه حدود دنيا — يجوز للعقد أن يزيد ولا يجوز أن ينقص، فالأرقام مدخلات سياسة لا ثوابت. والثاني أن أجر الإجازة يُدفع مقدمًا عند التمتع بها، بالأجر الساري حينها.
المادة 110 تنظّم الجدولة. يجوز للعامل بموافقة صاحب العمل تأجيل إجازته إلى السنة التالية. ويجوز لصاحب العمل تأجيلها بعد نهاية سنة استحقاقها لمدة لا تتجاوز 90 يومًا إذا اقتضت ظروف العمل؛ فإن اقتضت الظروف أكثر وجب موافقة العامل كتابةً، وحتى حينها لا تتجاوز نهاية السنة التالية لسنة الاستحقاق. ولاحظ ما لا تقوله المادة 110: لا تقول أبدًا إن الرصيد غير المستخدم يسقط. هي تضبط الجدولة لا الاستحقاق.
المادة 111 هي مادة المال. العامل الذي يترك العمل قبل استخدام إجازته المتراكمة يستحق أجرًا عن الأيام التي لم يأخذها، بما في ذلك كسور السنة بنسبة ما قضاه منها في العمل، على أساس الأجر في تاريخ استحقاق الإجازة. وعمليًا — وفي حاسبات الوزارة نفسها — الأجر اليومي هو الأجر الشهري مقسومًا على 30.
وثمة تعريف أخير مهم: منذ تعديل المرسوم الملكي م/46 لعام 2019 يعرّف نظام العمل السنة بأنها 365 يومًا ما لم ينص العقد على خلاف ذلك. العقود القديمة المكتوبة على التقويم الهجري موجودة؛ اجعل أساس عدّ الأيام إعدادًا قابلًا للتهيئة، والافتراضي 365.
تحذير: أكثر أخطاء التنفيذ شيوعًا هو منح الإجازة سنويًا بدل تراكمها يوميًا. قاعدة النسبة والتناسب في المادة 111 تجعل المنظور اليومي هو المعتبر نظامًا: موظف يستقيل في اليوم 100 من سنته الإجازية يستحق 100 على 365 من استحقاق تلك السنة، سواء «منحه» نظامك تلك الأيام أم لا.
الخطوة 2: احفظ المال بالهللات، لا بالأعداد العشرية أبدًا
القاعدة نفسها في كل محرك رواتب نبنيه: المال عدد صحيح من أصغر وحدة. الريال 100 هللة. أيام التراكم قد تكون كسرية — هذا حتمي وغير ضار — لكن لحظة التقاء الأيام بالمال نقرّب مرة واحدة، في النهاية، ولا نراكم خطأ الفاصلة العائمة إطلاقًا.
// src/money.ts
/** Money is always an integer number of halalas (1 SAR = 100 halalas). */
export type Halalas = number;
export function sar(amount: number): Halalas {
return Math.round(amount * 100);
}
export function formatSar(h: Halalas): string {
return (h / 100).toFixed(2) + " SAR";
}
/**
* The daily wage under the Ministry's convention: monthly wage / 30.
* Kept as an exact rational (numerator over 30) until the final rounding.
*/
export function leaveValue(days: number, monthlyWage: Halalas): Halalas {
return Math.round((days * monthlyWage) / 30);
}دالة leaveValue تضرب قبل أن تقسم وتقرّب مرة واحدة. 21.5 يومًا على أجر 8,000 ريال تساوي
Math.round(21.5 * 800000 / 30) أي 573,333 هللة أي 5,733.33 ريال — قابلة للتكرار حتى
الهللة على أي جهاز.
الخطوة 3: نمذج السياسة لا النظام وحده
المادة 109 تعطي حدودًا دنيا. العقود الحقيقية تمنح 22 أو 25 أو 30 يومًا من اليوم الأول؛ وبعض اللوائح الداخلية تحسّن شروط الأقدمية. اجعل النظام هو الافتراضي، وكل رقم قابلًا للتجاوز:
// src/policy.ts
export interface LeavePolicy {
/** Days per year before the seniority threshold. Statutory floor: 21. */
baseDays: number;
/** Days per year after the threshold. Statutory floor: 30. */
seniorDays: number;
/** Consecutive years of service that trigger the senior rate. Statute: 5. */
seniorAfterYears: number;
/** Days in a leave year. 365 since the M/46 amendment, unless the contract says otherwise. */
yearBasis: number;
}
export const STATUTORY_POLICY: LeavePolicy = {
baseDays: 21,
seniorDays: 30,
seniorAfterYears: 5,
yearBasis: 365,
};
export function resolvePolicy(overrides?: Partial<LeavePolicy>): LeavePolicy {
const p = { ...STATUTORY_POLICY, ...overrides };
if (p.baseDays < STATUTORY_POLICY.baseDays || p.seniorDays < STATUTORY_POLICY.seniorDays) {
throw new Error(
"Policy below the Article 109 floor: contracts may improve on 21/30 days, never reduce them."
);
}
return p;
}هذا الحارس ليس زينة. المادة الثامنة من نظام العمل تبطل كل شرط يمنح العامل أقل من النظام — ولا يجوز لملف إعدادات أن يكون قادرًا على ترميز عقد مخالف.
الخطوة 4: راكم يومًا بيوم، وامزج المعدلين عند الذكرى
التواريخ هي الجزء الذي يستحق التمهل. نعمل بتواريخ UTC مجردة من الوقت لتفادي انزياح المناطق الزمنية، ونحسب ذكرى المباشرة بالتاريخ التقويمي — الذكرى الخامسة لمباشرة في 2021-03-15 هي 2026-03-15 بما فيها السنوات الكبيسة، وليست «المباشرة زائد 1,825 يومًا».
// src/accrual.ts
import { LeavePolicy, resolvePolicy } from "./policy";
const DAY_MS = 86_400_000;
function utc(date: string): number {
const [y, m, d] = date.split("-").map(Number);
return Date.UTC(y, m - 1, d);
}
/** Whole days between two ISO dates (end exclusive). */
export function daysBetween(from: string, to: string): number {
return Math.round((utc(to) - utc(from)) / DAY_MS);
}
/** The nth service anniversary of a hire date, as an ISO date. */
export function anniversary(hireDate: string, n: number): string {
const [y, m, d] = hireDate.split("-").map(Number);
const t = new Date(Date.UTC(y + n, m - 1, d));
return t.toISOString().slice(0, 10);
}
/**
* Statutory accrued leave days from hire to `asOf` (exclusive).
* Days before the seniority anniversary accrue at baseDays/yearBasis,
* days after it at seniorDays/yearBasis — blended, not retroactive.
*/
export function accruedDays(
hireDate: string,
asOf: string,
overrides?: Partial<LeavePolicy>
): number {
const policy = resolvePolicy(overrides);
const switchDate = anniversary(hireDate, policy.seniorAfterYears);
const totalDays = Math.max(0, daysBetween(hireDate, asOf));
const baseServiceDays = Math.max(0, Math.min(totalDays, daysBetween(hireDate, switchDate)));
const seniorServiceDays = totalDays - baseServiceDays;
return (
(baseServiceDays * policy.baseDays) / policy.yearBasis +
(seniorServiceDays * policy.seniorDays) / policy.yearBasis
);
}جرّب الرقم الذي يخطئ فيه الجميع. موظف باشر في 2021-03-15، والفحص في 2026-09-15 — أي بعد ستة أشهر من ذكراه الخامسة:
accruedDays("2021-03-15", "2026-09-15");
// base period : 2021-03-15 → 2026-03-15 = 1,826 days at 21/365 = 105.06 days
// senior : 2026-03-15 → 2026-09-15 = 184 days at 30/365 = 15.12 days
// total ≈ 120.18 daysالنسخة الساذجة تطبّق معدل الثلاثين يومًا على كامل السنة التي تقع فيها الذكرى — رجوعًا إلى 2025-03-15 — فتضخّم الرصيد 9 أيام، أي خطأ بقيمة 2,400 ريال على أجر 8,000 ريال، يجلس في الدفاتر حتى تكشفه تسوية نهاية خدمة. المزج هو ما يقتضيه منطق النسبة والتناسب في المادة 111.
الخطوة 5: السجل — رصيد يمكنك الدفاع عنه
الرصيد الذي هو مجرد رقم في عمود لا يصمد أمام نزاع. خزّن الأحداث واشتق الرصيد. كل إجازة أُخذت، وكل تعديل يدوي، وكل رصيد افتتاحي من ترحيل نظام قديم هو صف بتاريخ وسبب:
// src/ledger.ts
import { Halalas } from "./money";
import { LeavePolicy } from "./policy";
import { accruedDays } from "./accrual";
export type LeaveEvent =
| { type: "taken"; from: string; to: string; note?: string }
| { type: "adjustment"; date: string; days: number; note: string };
export interface Employee {
id: string;
hireDate: string;
/** Current monthly wage in halalas — the Article 111 basis at exit. */
monthlyWage: Halalas;
policy?: Partial<LeavePolicy>;
}
function takenDays(e: LeaveEvent): number {
if (e.type === "adjustment") return -e.days; // positive adjustment credits the balance
// Leave spans are inclusive on both ends: 2026-08-02 → 2026-08-06 is 5 days.
const ms = Date.parse(e.to) - Date.parse(e.from);
return Math.round(ms / 86_400_000) + 1;
}
export function leaveBalance(
employee: Employee,
ledger: LeaveEvent[],
asOf: string
): number {
const accrued = accruedDays(employee.hireDate, asOf, employee.policy);
const consumed = ledger
.filter((e) => (e.type === "taken" ? e.from : e.date) <= asOf)
.reduce((sum, e) => sum + takenDays(e), 0);
return accrued - consumed;
}قراران تصميميان يستحقان الوقوف عندهما.
المدد شاملة الطرفين. في العرف السعودي إجازة «من اليوم الثاني إلى السادس» خمسة أيام، بحساب الطرفين. ترميز المدة بدل عدد الأيام يمكّن السجل لاحقًا من الإجابة عن أسئلة لا يجيب عنها الرصيد — كم من هذه الإجازة وقع داخل نافذة تأجيل، وهل تداخلت مع عطلة عيد تستثنيها لائحتك الداخلية.
الرصيد السالب حالة نظامية لا خطأ. قاعدة الدفع المقدم في المادة 109 تعني أن أصحاب العمل يمنحون الإجازة قبل اكتمال تراكمها بشكل اعتيادي — موظف جديد يأخذ عشرة أيام في شهره الرابع يكون ببساطة على رصيد سالب بأيام قليلة يسدّدها التراكم القادم. لواجهتك أن تحذّر؛ أما محركك فيجب ألا يرمي استثناء. وعند انتهاء الخدمة يتحول الرصيد السالب إلى حسم من التسوية النهائية، وهو تمامًا ما ستنتجه دالة البدل، والإشارة السالبة تقوم بالعمل.
الخطوة 6: تتبّع ساعة المادة 110
المادة 110 لا تُسقط الأرصدة، لكنها تضع عليها تواريخ، والمحرك العاجز عن الإجابة عن سؤال «أي من هذه الأيام الأربعة والثلاثين داخل نافذة تأجيله النظامية؟» يترك الموارد البشرية مكشوفة في الاتجاهين — الضغط على موظفين في إجازات مؤجلة تأجيلًا نظاميًا، أو الانزلاق نحو كومة التزامات متقادمة بمتطلبات موافقات كتابية لم يجمعها أحد.
تختزل القاعدة إلى أفق زمني: إجازة السنة «ن» تؤخذ في السنة «ن»؛ ولصاحب العمل وحده دفعها حتى 90 يومًا داخل السنة التالية؛ وبموافقة العامل الكتابية حتى نهاية السنة التالية، ولا أبعد. نُخرج تقرير تقادم ونترك قرار السياسة للبشر:
// src/deferral.ts
import { anniversary, daysBetween } from "./accrual";
export interface LeaveYearAging {
/** Leave year index (1 = first year of service). */
year: number;
dueYearEnd: string;
employerDeferralEnd: string; // dueYearEnd + 90 days
consentDeferralEnd: string; // end of the following leave year
status: "current" | "employer-window" | "consent-required" | "beyond-limit";
}
export function agingFor(hireDate: string, year: number, asOf: string): LeaveYearAging {
const dueYearEnd = anniversary(hireDate, year);
const employerDeferralEnd = addDays(dueYearEnd, 90);
const consentDeferralEnd = anniversary(hireDate, year + 1);
const status =
asOf <= dueYearEnd ? "current"
: asOf <= employerDeferralEnd ? "employer-window"
: asOf <= consentDeferralEnd ? "consent-required"
: "beyond-limit";
return { year, dueYearEnd, employerDeferralEnd, consentDeferralEnd, status };
}
function addDays(date: string, n: number): string {
const t = new Date(Date.parse(date) + n * 86_400_000);
return t.toISOString().slice(0, 10);
}علامة beyond-limit نتيجة امتثال لا شطب: مال الموظف محفوظ بالمادة 111 في كل الأحوال. ما
تخبر به هذه العلامة صاحبَ العمل هو أن التزام الجدولة فات — وهو النمط الذي يقرؤه مفتش العمل
على أنه خلل منهجي.
الخطوة 7: بدل الإجازة عند الخروج — المادة 111 في دالة واحدة
عند انتهاء العلاقة يلتقي كل شيء: التراكم يجري حتى تاريخ الخروج، والسجل يخصم ما أُخذ، والباقي يُقوَّم بالأجر اليومي. كسور السنة محسوبة — هذا نص المادة الصريح — والرصيد السالب ينقلب سلفة قابلة للاسترداد:
// src/settlement.ts
import { Employee, LeaveEvent, leaveBalance } from "./ledger";
import { Halalas, leaveValue } from "./money";
export interface LeaveCashOut {
balanceDays: number;
dailyWage: Halalas;
/** Positive: owed to the employee. Negative: advance leave recoverable from the settlement. */
amount: Halalas;
}
export function exitCashOut(
employee: Employee,
ledger: LeaveEvent[],
exitDate: string
): LeaveCashOut {
const balanceDays = leaveBalance(employee, ledger, exitDate);
return {
balanceDays,
dailyWage: Math.round(employee.monthlyWage / 30),
amount: leaveValue(balanceDays, employee.monthlyWage),
};
}هذا البند يجلس بجوار مكافأة نهاية الخدمة في التسوية النهائية — المادة 111 للإجازة، والمادتان 84 و85 للمكافأة. وقد شرحنا حساب المكافأة بالتفصيل في دليل مكافأة نهاية الخدمة في نظام العمل، ويمكنك التحقق من أرقامها عبر حاسبة نهاية الخدمة. ويختلف البندان في نقطة مهمة: المكافأة تُحسب على الأجر الأخير بنص النظام، بينما أجر الإجازة يتبع الأجر في تاريخ استحقاقها — يتطابقان في كسر السنة الجارية، لكن إن منحت زيادات في منتصف السنة وتحمل أرصدة قديمة فالفارق مال حقيقي، وتواريخ سجلك هي ما يتيح حسابه بأمانة.
الخطوة 8: قيّده شهريًا، وإلا صار الرصيد مفاجأة
الانضباط نفسه في مخصص نهاية الخدمة: الالتزام الذي لا يظهر إلا عند الخروج معتاد أن يظهر دفعة واحدة. ينبغي أن ترى المالية حركة التزام الإجازات كل شهر:
// src/liability.ts
import { Employee, LeaveEvent, leaveBalance } from "./ledger";
import { Halalas, leaveValue } from "./money";
export function leaveLiability(
staff: Array<{ employee: Employee; ledger: LeaveEvent[] }>,
asOf: string
): Halalas {
return staff.reduce((total, { employee, ledger }) => {
const days = leaveBalance(employee, ledger, asOf);
return total + Math.max(0, leaveValue(days, employee.monthlyWage));
}, 0);
}لشركة من 40 موظفًا بمتوسط أجر 7,000 ريال، كل سنة نظامية غير مستخدمة تعادل نحو 196,000 ريال من الالتزام الصامت. متابعته شهريًا هي أيضًا ما يجعل تقرير تقادم المادة 110 قابلًا للتنفيذ — فالرقمان يتحركان معًا.
اختبار التنفيذ
ثبّت كل قاعدة نظامية في سيناريو. هذه الاختبارات تمسك الأخطاء الكلاسيكية:
// test/engine.test.ts
import { describe, expect, it } from "vitest";
import { accruedDays, anniversary } from "../src/accrual";
import { leaveBalance } from "../src/ledger";
import { exitCashOut } from "../src/settlement";
import { sar } from "../src/money";
describe("Article 109 accrual", () => {
it("accrues 21 days over a full early year", () => {
expect(accruedDays("2025-01-01", "2026-01-01")).toBeCloseTo(21, 5);
});
it("blends the rate at the fifth anniversary, not the calendar year", () => {
const total = accruedDays("2021-03-15", "2026-09-15");
expect(total).toBeCloseTo((1826 * 21) / 365 + (184 * 30) / 365, 5);
});
it("rejects sub-statutory policies", () => {
expect(() => accruedDays("2025-01-01", "2026-01-01", { baseDays: 15 })).toThrow();
});
});
describe("Article 111 cash-out", () => {
const employee = {
id: "E-1001",
hireDate: "2023-06-01",
monthlyWage: sar(8000),
};
it("pays the pro-rated fraction on early exit", () => {
const { balanceDays, amount } = exitCashOut(employee, [], "2023-09-09");
expect(balanceDays).toBeCloseTo((100 * 21) / 365, 5); // 100 days of service
expect(amount).toBe(153_425); // 1,534.25 SAR, rounded once
});
it("turns advance leave into a negative settlement line", () => {
const ledger = [{ type: "taken", from: "2023-07-02", to: "2023-07-11" } as const];
const { amount } = exitCashOut(employee, ledger, "2023-09-09");
expect(amount).toBeLessThan(0); // 10 days taken, ~5.75 accrued
});
});
describe("service anniversaries", () => {
it("handles leap-day hires without drifting", () => {
expect(anniversary("2024-02-29", 5)).toBe("2029-03-01");
});
});ثم طابق عيّنة من موظفيك الحقيقيين مع حاسبة رصيد الإجازات — فهي تشغّل منطق التراكم هذا نفسه، وأي اختلاف يعني تباينًا في المدخلات يستحق التحقيق، وغالبًا هو تاريخ المباشرة أو تجاوز سياسة نسيت أنك أضفته.
استكشاف الأخطاء
أرصدة تختلف بهللات قليلة عن تقارير مزوّد الرواتب. غالبًا تقريب مبكر عندهم — أجر يومي
مقرّب مضروب في أيام كسرية. دالتك leaveValue تقرّب مرة واحدة؛ وعند اختلاف الرقمين فرقمك هو
القابل للدفاع. اعرض العملية الحسابية.
قفزات عند الذكرى الخامسة في التقارير التاريخية. إن أظهر تقرير تغيّرًا فجائيًا بعدة أيام عند الذكرى، فقد طبّق أحدهم معدل الثلاثين بأثر رجعي على السنة كاملة. أعد التشغيل بالتراكم الممزوج وصحّح البيانات.
عقود على الأساس الهجري. العقود السابقة لتعديل م/46 أو المنصوص فيها صراحة على الهجري
تحتاج yearBasis: 354 وذكرى مباشرة هجرية. واجهة Intl في JavaScript مع تقويم
islamic-umalqura تشتقها؛ وأبقِ هؤلاء الموظفين على تجاوز سياسة صريح لا على علم عام في
النظام.
الأرصدة الافتتاحية المرحّلة. لا تصطنع تاريخًا وهميًا أبدًا. حدث adjustment واحد بتاريخ
الترحيل، مع ملاحظة تشير إلى تقرير النظام القديم، يبقي السجل صادقًا ومسار التدقيق قصيرًا.
الخطوات التالية
- اقرأ الجانب النظامي كاملًا في دليل حساب رصيد الإجازات السنوية في نظام العمل السعودي
- غذِّ بيانات الموظفين نفسها إلى مولّد ومدقّق ملف حماية الأجور — فالإجازة بلا أجر المسجلة في هذا السجل يجب أن تتطابق مع ملف الأجور الذي ترفعه
- تتبّع مسار الأرقام بعد ذلك في الربط مع مدد للرواتب وفي منظومة منصة قوى
- دع الموظفين يتحققون من أرقامهم بأنفسهم عبر حاسبة رصيد الإجازات المجانية
الخاتمة
الإجازة السنوية في السعودية ليست ميزة تُتابع على استحياء — هي التزام نظامي له قاعدة تراكم يومية، ومفتاح أقدمية، وساعة جدولة، وتحويل نقدي مضمون عند الخروج. والمحرك الذي يعالجها بشكل صحيح صغير: مال بأعداد صحيحة، وتراكم يومي ممزوج، وسجل أحداث، وتقريب واحد في النهاية. وما يشتريه لك كبير — تسويات تطابق حساب المحكمة، ومخصصات تطابق الواقع، ومسار تدقيق يجيب عن الأسئلة بدل أن يثيرها.
إن كانت أرصدة الإجازات عندكم تعيش في جدول إكسل، أو كانت أرقام نظام الموارد البشرية وأرقام الرواتب لا تتفقان ولا أحد يعرف السبب، أخبرنا كيف تبدو منظومتكم — نمرّر عينة من بيانات موظفيكم الحقيقية عبر محرك كهذا ونريكم بالضبط أين يفترق الرقمان، قبل أن تفعلها تسوية نهاية خدمة بدلًا عنا.