écrits/tutorial/2026/08
Tutorial18 août 2026·24 min

Indemnité de fin de service saoudienne en TypeScript (art. 84/85)

Construisez un moteur de calcul de l'indemnité de fin de service pour la paie saoudienne en TypeScript, en implémentant les articles 84, 85, 87 et 88 du Code du travail — le barème à deux tranches, l'échelle de démission, l'ancienneté mesurée en anniversaires et la provision mensuelle qui transforme l'indemnité en charge anticipée plutôt qu'en surprise.

Tout système de paie opérant en Arabie saoudite doit répondre correctement à une seule question : lorsque ce salarié franchit la porte pour la dernière fois, que lui devons-nous ?

L'article 84 du Code du travail fait de l'indemnité de fin de service — مكافأة نهاية الخدمة, souvent abrégée EOSB — une obligation légale pesant sur l'employeur, et non un avantage que l'entreprise accorde. L'article 88 vous laisse une semaine pour la payer. Et l'article 85 fait discrètement du même salarié, à salaire égal et à ancienneté égale, trois montants totalement différents selon qui a mis fin au contrat.

La plupart des implémentations internes se trompent sur l'un de ces quatre points : elles calculent l'ancienneté en divisant les jours par 365, elles appliquent le taux de la mauvaise tranche, elles retiennent le salaire de base là où la loi dit salaire, ou elles traitent l'indemnité comme un événement de paiement au lieu d'un passif qui s'accumule chaque mois depuis le premier jour du salarié. Chacune de ces erreurs produit un chiffre qui survit à la revue interne et échoue devant le tribunal du travail.

Ce tutoriel construit le calcul correctement en TypeScript — l'arithmétique, les cas limites légaux, les tests qui figent chacun d'eux, et la provision mensuelle qui transforme l'ensemble en une charge que votre direction financière peut voir venir.

Ceci est un guide d'ingénierie, pas un conseil juridique. Le texte légal fait foi, et un contrat peut toujours être plus généreux que le minimum. Lorsqu'un cas est réellement contesté — une rupture inhabituelle, une définition du salaire discutée — faites trancher les données d'entrée par un avocat en droit du travail saoudien avant de les coder.

Prérequis

Avant de commencer, assurez-vous de disposer de :

  • Node.js 20 ou plus récent, et TypeScript 5.x
  • Une familiarité avec l'arithmétique entière et les raisons pour lesquelles le flottant est dangereux pour les montants
  • Un SIRH ou un système de paie exposant les dates d'entrée et une définition du salaire interrogeable
  • Le texte en vigueur du Code du travail saoudien sous les yeux — le ministère des Ressources humaines et du Développement social (HRSD) le publie, et le centre de connaissances de Qiwa en propose une version lisible des mêmes articles

Ce que vous allez construire

Une fonction pure, endOfService, qui prend une date d'entrée, une date de sortie, le dernier salaire et le motif de la rupture, et retourne une décomposition complète : jours d'ancienneté, mois de salaire acquis au titre de l'article 84, indemnité intégrale, quote-part de l'article 85 et montant réellement dû. Plus une fonction de provision mensuelle qui répond à la question financière : où en est ce passif aujourd'hui, avant que quiconque ait démissionné.

Aucune dépendance, aucune bibliothèque de dates, aucun flottant.

Étape 1 : lire le texte avant d'écrire la formule

Quatre articles portent tout le calcul. Il vaut la peine d'être précis sur chacun, car les bugs d'implémentation courants sont tous des erreurs de lecture plutôt que des erreurs de code.

Article 84 — l'indemnité elle-même. Un demi-mois de salaire pour chacune des cinq premières années d'ancienneté, et un mois entier pour chaque année au-delà. Les fractions d'année sont payées au prorata.

Le piège est que les tranches sont cumulatives, non sélectives. Sept années d'ancienneté ne font pas sept mois, et ne font pas trois mois et demi. Elles font cinq années à un demi-mois, plus deux années à un mois entier : 2,5 plus 2, soit 4,5 mois.

Article 85 — la réduction pour démission. Lorsque c'est le salarié qui rompt le contrat, l'indemnité est proratisée selon l'ancienneté :

Ancienneté accompliePart de l'indemnité de l'article 84
Moins de 2 ansrien
De 2 ans à moins de 5 ansun tiers
De 5 ans à moins de 10 ansdeux tiers
10 ans et plusl'intégralité

Lorsque c'est l'employeur qui rompt le contrat, l'indemnité intégrale est due quelle que soit l'ancienneté. C'est la principale source de litiges, et la raison pour laquelle le motif doit être une donnée d'entrée de la fonction plutôt qu'une valeur par défaut que quelqu'un a supposée.

Article 87 — les exceptions qui priment sur l'article 85. Le salarié qui part pour un cas de force majeure indépendant de sa volonté perçoit l'indemnité intégrale quelle que soit son ancienneté. De même pour la salariée qui rompt le contrat dans les six mois de son mariage ou dans les trois mois de son accouchement. Ce ne sont pas des cas limites que l'on peut différer — ils sont assez fréquents dans les effectifs saoudiens pour mériter un indicateur explicite plutôt qu'une correction manuelle.

Article 88 — le délai. Lorsque l'employeur met fin à la relation, l'ensemble des droits est soldé dans la semaine suivant la sortie. Lorsque le salarié démissionne, dans les deux semaines. Un calcul qui demande dix jours à votre équipe financière est déjà non conforme sur le premier chemin, ce qui est l'argument pratique en faveur de son automatisation.

Une définition supplémentaire compte. L'article 84 se règle sur le salaire, et l'article des définitions du Code du travail distingue le salaire de base du salaire réel — le base augmenté des indemnités et primes versées régulièrement. Les indemnités de logement et de transport sont celles qui déplacent le chiffre. Retenir le seul salaire de base sous-évalue l'indemnité, parfois de trente pour cent ou plus, et c'est l'erreur qui transforme le plus souvent un départ de routine en contentieux.

Étape 2 : conserver les montants en halalas, jamais en flottants

0.1 + 0.2 ne vaut pas 0.3, et une indemnité est une chaîne de multiplications appliquée à un salaire. Travaillez en unités mineures entières — les halalas — et n'arrondissez qu'une seule fois, au moment de la sortie.

/** 100 halalas to the riyal. */
export const MINOR_PER = 100;
 
/** Divide and round half-away-from-zero, staying in integers. */
export function divRound(numerator: number, denominator: number): number {
  const sign = numerator < 0 ? -1 : 1;
  return sign * Math.round(Math.abs(numerator) / denominator);
}
 
/** '10000' or '10,000.50' to whole halalas. */
export function parseAmount(input: string): number {
  const cleaned = String(input).replace(/[,\s]/g, '');
  if (!/^\d+(\.\d{1,2})?$/.test(cleaned)) throw new TypeError('Not an amount');
  const [whole, frac = ''] = cleaned.split('.');
  return Number(whole) * MINOR_PER + Number(frac.padEnd(2, '0'));
}
 
export function formatMinor(minor: number): string {
  const whole = Math.trunc(minor / MINOR_PER);
  const frac = String(Math.abs(minor % MINOR_PER)).padStart(2, '0');
  return `${whole}.${frac}`;
}

La règle qui en découle : dérivez les totaux des taux non arrondis, jamais de valeurs intermédiaires arrondies. Si vous arrondissez un taux d'un demi-mois puis le multipliez par cinq années, vous avez encaissé l'erreur d'arrondi cinq fois.

Étape 3 : mesurer l'ancienneté en anniversaires, pas en jours divisés par 365

Voici le bug qui survit à la revue de code, parce que le code a l'air manifestement juste :

// WRONG — and it will pass every test that uses round numbers.
const years = daysBetween(start, end) / 365;

Cinq années civiles contenant un jour bissextile font 1 826 jours. Divisées par 365, cela se lit 5,0027 années. Sur un salaire de 10 000 riyals, l'indemnité de l'article 84 est de 25 000,00 — mais le chiffre dérivé paie 25 013,70. Treize riyals ne sont rien ; le fait que votre moteur diverge du calculateur du ministère d'un montant non nul n'est pas rien, car c'est la première chose qu'un auditeur vérifie et la première dont un salarié sortant fait une capture d'écran.

L'indemnité s'exprime en années d'ancienneté, et une année d'ancienneté est un anniversaire. Mesurez-la comme des anniversaires accomplis plus une proportion de l'année en cours :

const MS_PER_DAY = 86_400_000;
/** Years held in ten-thousandths, so fractions stay exact in integers. */
const YEAR_UNIT = 10_000;
 
/** The calendar anniversary `years` after `from`. */
function anniversary(from: Date, years: number): Date {
  return new Date(
    Date.UTC(from.getUTCFullYear() + years, from.getUTCMonth(), from.getUTCDate()),
  );
}
 
function serviceUnitsBetween(from: Date, to: Date): number {
  let completed = 0;
  while (anniversary(from, completed + 1) <= to) completed++;
 
  const last = anniversary(from, completed);
  const next = anniversary(from, completed + 1);
  const yearLength = Math.round((next.getTime() - last.getTime()) / MS_PER_DAY);
  const remainder = Math.round((to.getTime() - last.getTime()) / MS_PER_DAY);
 
  return completed * YEAR_UNIT + divRound(remainder * YEAR_UNIT, yearLength);
}

Deux détails sont porteurs. Les dates sont interprétées à minuit UTC, de sorte qu'un serveur à Riyad et un serveur à Francfort s'accordent sur le jour où l'ancienneté a pris fin. Et la fraction de l'année en cours est mesurée par rapport à la durée de cette année précise, de sorte qu'une année partielle chevauchant février 2028 est divisée par 366 plutôt que par 365.

function parseDate(iso: string, label: string): Date {
  const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(String(iso).trim());
  if (!m) throw new TypeError(`${label} must be yyyy-mm-dd`);
  const [, y, mo, d] = m;
  const date = new Date(Date.UTC(Number(y), Number(mo) - 1, Number(d)));
  if (
    date.getUTCFullYear() !== Number(y) ||
    date.getUTCMonth() !== Number(mo) - 1 ||
    date.getUTCDate() !== Number(d)
  ) {
    throw new TypeError(`${label} is not a real date`);
  }
  return date;
}

Rejeter 2026-02-30 à la frontière vaut bien ces huit lignes. Les constructeurs de dates qui reportent silencieusement transforment une faute de frappe en paiement erroné.

Étape 4 : le barème à deux tranches de l'article 84

Avec l'ancienneté exprimée en dix-millièmes d'année, les deux tranches deviennent une répartition plutôt qu'un branchement :

const STEP_YEARS = 5;
 
const serviceUnits = serviceUnitsBetween(from, to);
const stepUnits = STEP_YEARS * YEAR_UNIT;
 
const unitsAtHalf = Math.min(serviceUnits, stepUnits);
const unitsAtFull = Math.max(0, serviceUnits - stepUnits);
 
// Half a month per year for the first five, a whole month thereafter.
const monthUnits = divRound(unitsAtHalf, 2) + unitsAtFull;
const fullMinor = divRound(monthly * monthUnits, YEAR_UNIT);

monthUnits représente des mois de salaire dans la même échelle en dix-millièmes, ce qui maintient tout le calcul en entiers jusqu'à la division finale. Vérifiez-le sur les deux cas que tout le monde connaît :

  • Exactement cinq ans : unitsAtHalf vaut 50 000, unitsAtFull vaut 0, monthUnits vaut 25 000 — soit deux mois et demi. Sur 10 000 riyals : 25 000,00.
  • Exactement sept ans : 50 000 au demi-mois plus 20 000 au mois entier donnent 45 000 unités — soit quatre mois et demi. Sur 10 000 riyals : 45 000,00.

Et une première année partielle, où la proratisation se manifeste : 182 jours dans une année de 366 jours font 0,4973 année au taux du demi-mois, soit 0,25 mois et une indemnité de 2 487,00.

Étape 5 : article 85 — la même ancienneté, trois montants différents

La réduction s'applique à l'indemnité, pas au salaire, et uniquement en cas de démission :

export type EndReason = 'termination' | 'resignation';
 
/** Service thresholds, in years, at which a resignation's share steps up. */
export const RESIGNATION_STEPS = [2, 5, 10] as const;
 
let numerator = 1;
let denominator = 1;
 
if (reason === 'resignation') {
  const [twoY, fiveY, tenY] = RESIGNATION_STEPS.map((y) => y * YEAR_UNIT);
  if (serviceUnits < twoY) [numerator, denominator] = [0, 1];
  else if (serviceUnits < fiveY) [numerator, denominator] = [1, 3];
  else if (serviceUnits < tenY) [numerator, denominator] = [2, 3];
}
 
const payableMinor = divRound(fullMinor * numerator, denominator);

Notez ce que le code se garde délibérément de faire : il ne met pas fullMinor à zéro pour une démission courte. L'indemnité a bien été acquise — l'article 85 régit ce qui est dû, non ce qui a été acquis. Cette distinction devient déterminante dès que le départ est requalifié, ce qui arrive dans environ un tiers des cas contentieux : un salarié enregistré comme démissionnaire s'avère avoir été licencié de fait, et le montant dû bascule à l'indemnité intégrale sans le moindre recalcul de l'ancienneté.

Conservez les deux montants dans le type de retour, pour que la requalification ne soit qu'un changement de champ :

export type EndOfServiceBreakdown = {
  serviceDays: number;
  serviceYears: number;
  /** Months of wage earned under Art. 84, before any Art. 85 reduction. */
  monthsOfWage: string;
  /** The Art. 84 award in full. */
  full: string;
  /** The Art. 85 share actually payable, as a readable fraction. */
  share: string;
  /** What is owed after the share is applied. */
  payable: string;
  fullMinor: number;
  payableMinor: number;
};

L'exemple concret à mettre sous les yeux d'un décideur : trois ans d'ancienneté sur un salaire de 10 000 riyals. Licencié, le salarié perçoit 15 000,00. Démissionnaire, le même salarié perçoit 5 000,00 — un tiers. Mêmes dates, même salaire, même indemnité acquise de 15 000,00. Si votre interface n'affiche que le montant dû, personne ne peut voir où sont passés les 10 000 restants, et cette opacité est ce qui engendre le litige.

Exposer share sous forme de fraction lisible plutôt que de décimale est un petit détail qui se rembourse en tickets de support. « 1/3 » correspond directement au vocabulaire de l'article 85 ; « 0,3333 » non.

Étape 6 : article 87 — les dérogations

Deux conditions rendent l'indemnité intégrale exigible même sur une démission que l'article 85 aurait réduite. Elles doivent être des données d'entrée, car aucun système ne peut les déduire :

export type EndOfServiceInput = {
  start: string;
  end: string;
  /** Last actual monthly wage — basic plus every regular allowance. */
  wage: string | number;
  reason?: EndReason;
  /**
   * Art. 87 — force majeure beyond the worker's control, or a female worker
   * ending the contract within six months of marriage or three months of
   * giving birth. Either pays the full award regardless of service.
   */
  fullAwardException?: boolean;
};

Dans le corps de la fonction, l'exception court-circuite entièrement l'échelle de l'article 85 :

if (reason === 'resignation' && !fullAwardException) {
  // ... the Article 85 steps
}

Un indicateur explicite accompagné d'un commentaire nommant l'article vaut mieux qu'une déduction astucieuse. Les RH savent si le départ tient à un mariage ; votre arithmétique des dates ne le saura jamais.

Étape 7 : l'indemnité n'est qu'une ligne du solde de tout compte

L'article 88 exige le règlement de tous les droits dans le délai, pas seulement de l'indemnité. Un moteur de production qui ne calcule que l'indemnité remet à la finance un chiffre sur lequel elle ne peut toujours pas payer. Les autres lignes légales :

  • Congés annuels non pris, articles 109 et 111. Vingt et un jours par an, portés à trente après cinq années continues. Les congés s'acquièrent réellement au jour le jour, contrairement à l'indemnité — une période chevauchant le cinquième anniversaire doit donc être scindée et acquise aux deux taux. Calculer toute la période à un taux unique est l'erreur standard ici, en sens inverse de celle de l'indemnité.
  • Indemnité de préavis, article 75. Trente jours sur un contrat à durée indéterminée payé au mois lorsque le préavis n'a pas été exécuté.
  • Indemnité de licenciement abusif, article 77. Quinze jours de salaire par année d'ancienneté sur un contrat à durée indéterminée, ou le salaire de la période restant à courir sur un contrat à durée déterminée — et dans tous les cas au moins deux mois de salaire. Ce plancher gouverne pour toute personne ayant moins de quatre ans d'ancienneté, c'est-à-dire la majorité de ceux qui se renseignent.
  • Salaires impayés, qui constituent la première ligne du calculateur du travail du ministère de la Justice lui-même.

Modélisez chacun de ces postes comme une fonction pure distincte retournant le même type monétaire, puis additionnez au niveau de la couche de solde. Une fonction monolithique calculateFinalSettlement devient intestable en l'espace d'un sprint.

Vous pouvez vérifier chacun de ces montants avec notre calculateur des droits du travail saoudien, qui exécute cette même bibliothèque, ou avec le calculateur de solde de congés pour le seul volet de l'article 109.

Étape 8 : provisionner mensuellement, sinon ce n'est pas une provision

C'est l'étape qui sépare une fonctionnalité de paie d'un système financier, et c'est celle que la plupart des développements internes sautent.

L'indemnité de fin de service est un passif qui croît chaque mois où le salarié reste. Si elle n'est calculée qu'au moment du départ, l'entreprise découvre une obligation à six chiffres le jour même où elle devient exigible sous une semaine. Au sens d'IAS 19, il s'agit d'un avantage du personnel qui devrait déjà être provisionné.

Le moteur que vous avez construit vous l'offre gratuitement — appelez-le avec la date du jour au lieu d'une date de sortie :

/** The award accrued as of a date, for provisioning. */
export function accruedLiability(
  employee: { start: string; wage: string },
  asOf: string,
) {
  // Provision against the full Art. 84 award, not the Art. 85 share:
  // the reduction is contingent on how the relationship ends, which is
  // not known on the reporting date.
  return endOfService({
    start: employee.start,
    end: asOf,
    wage: employee.wage,
    reason: 'termination',
  }).fullMinor;
}

Le commentaire porte le jugement professionnel. Provisionner sur le montant — en supposant que tout le monde démissionne — sous-évalue systématiquement le passif, car les licenciements et les fins de contrat paient l'intégralité. Provisionnez sur l'indemnité intégrale et laissez la réduction de l'article 85 être une reprise le jour où elle survient.

Étendez cela à l'effectif et vous obtenez une série mensuelle sur laquelle la finance peut réellement planifier :

export function provisionByMonth(
  employees: Array<{ id: string; start: string; wage: string }>,
  months: string[], // ['2026-01-31', '2026-02-28', ...]
) {
  return months.map((asOf) => ({
    asOf,
    totalMinor: employees
      .filter((e) => e.start <= asOf)
      .reduce((sum, e) => sum + accruedLiability(e, asOf), 0),
  }));
}

Deux faits de reporting en découlent, que personne ne demande avant de les avoir vus. L'écart d'un mois sur l'autre est la charge de la période. Et la marche au cinquième anniversaire de chaque salarié est visible à l'avance — le taux double, passant d'un demi-mois à un mois entier par année, si bien qu'une cohorte recrutée ensemble produit un saut de la provision à une date que vous pouvez nommer dès aujourd'hui.

Cette série est la couche de reporting, et c'est la raison pour laquelle ce calcul mérite d'être fait correctement plutôt que dans un tableur.

Tester votre implémentation

Figez chaque cas légal dans un test nommé. Chacun d'eux a fait l'objet d'un désaccord quelque part :

import test from 'node:test';
import assert from 'node:assert/strict';
import { endOfService } from './labour';
 
test('half a month for each of the first five years', () => {
  const r = endOfService({ start: '2019-01-01', end: '2024-01-01', wage: '10000' });
  assert.equal(r.monthsOfWage, '2.50');
  assert.equal(r.full, '25000.00');
  assert.equal(r.payable, '25000.00'); // termination pays in full
});
 
test('and a full month for each year after the fifth', () => {
  // Seven years: 2.5 months for the first five, 2 for the rest.
  const r = endOfService({ start: '2018-01-01', end: '2025-01-01', wage: '10000' });
  assert.equal(r.monthsOfWage, '4.50');
  assert.equal(r.full, '45000.00');
});
 
test('fractions of a year are paid in proportion', () => {
  // 182 days into a 366-day year is 0.4973 of a year, at the half-month rate.
  const r = endOfService({ start: '2024-01-01', end: '2024-07-01', wage: '10000' });
  assert.equal(r.monthsOfWage, '0.25');
  assert.equal(r.full, '2487.00');
});
 
test('resignation below two years pays nothing, but still accrues', () => {
  const r = endOfService({
    start: '2024-01-01',
    end: '2025-06-01',
    wage: '10000',
    reason: 'resignation',
  });
  assert.ok(Number(r.full) > 0, 'the award still accrues');
  assert.equal(r.payable, '0.00');
});
 
test('the same service settles at three different numbers', () => {
  const args = { start: '2021-01-01', end: '2024-01-01', wage: '10000' } as const;
  const sacked = endOfService({ ...args, reason: 'termination' });
  const quit = endOfService({ ...args, reason: 'resignation' });
  assert.equal(sacked.payable, '15000.00');
  assert.equal(quit.payable, '5000.00'); // one third, Art. 85
  assert.equal(sacked.fullMinor, quit.fullMinor, 'the award accrued is the same');
});
 
test('a leap day does not inflate the gratuity', () => {
  // days/365 would read five calendar years spanning a leap day as 5.0027
  // years and pay 25,013.70. Years of service are anniversaries.
  const r = endOfService({ start: '2019-01-01', end: '2024-01-01', wage: '10000' });
  assert.equal(r.serviceDays, 1826);
  assert.equal(r.full, '25000.00');
});
 
test('the Art. 85 steps are calendar anniversaries, not two times 365', () => {
  // 731 days is two years across a leap year — the one-third step must fire.
  const r = endOfService({
    start: '2022-03-01',
    end: '2024-03-01',
    wage: '10000',
    reason: 'resignation',
  });
  assert.equal(r.serviceDays, 731);
  assert.equal(r.share, '1/3');
});
 
test('bad input throws rather than paying a wrong number', () => {
  assert.throws(
    () => endOfService({ start: '2025-01-01', end: '2024-01-01', wage: '10000' }),
    RangeError,
  );
  assert.throws(() => endOfService({ start: 'nope', end: '2025-01-01', wage: '1' }), TypeError);
});

Lancez avec node --test. Le dernier test compte plus qu'il n'y paraît : un moteur d'indemnité qui retourne NaN sur une date malformée écrira volontiers NaN dans un fichier de paiement. Lever une exception est le comportement correct pour de l'argent.

Recoupez ensuite quelques cas réels avec le calculateur de fin de service du HRSD et le calculateur du travail du ministère de la Justice. Si votre moteur et celui du ministère divergent ne serait-ce que d'un halala, trouvez pourquoi avant de livrer — l'écart tient presque toujours à la convention de décompte des jours ou à la définition du salaire, et les deux méritent d'être connus avant qu'un auditeur ne vous les signale.

Dépannage

Le montant est légèrement supérieur à celui du ministère. Presque toujours une division des jours par 365 quelque part dans le calcul de l'ancienneté. Cherchez / 365 et remplacez par l'arithmétique des anniversaires.

Le montant est très inférieur à l'attendu. Vérifiez la définition du salaire. Si vous alimentez le salaire de base alors que le salaire réel contractuel inclut les indemnités de logement et de transport, vous serez court de la proportion que représentent ces indemnités — couramment vingt-cinq à trente-cinq pour cent.

La sixième année paie moins que la cinquième. Les tranches sont appliquées sélectivement plutôt que cumulativement — le code facture un mois par année pour toutes les années dès que l'ancienneté dépasse cinq ans, puis soustrait quelque part. Vérifiez que unitsAtHalf et unitsAtFull totalisent bien serviceUnits.

Une démission à exactement deux ans ne paie rien. Une erreur d'unité au seuil. L'article 85 accorde un tiers à deux ans d'ancienneté, la comparaison au seuil doit donc être strictement inférieure, et non inférieure ou égale.

Les totaux dérivent de quelques halalas sur un effectif important. Arrondi appliqué plus d'une fois. N'arrondissez qu'à la sortie, et dérivez chaque total du taux non arrondi.

Étapes suivantes

Conclusion

L'indemnité de fin de service saoudienne est un petit calcul enveloppé dans quatre articles de loi, et presque toutes les erreurs d'implémentation sont des erreurs de lecture plutôt que des bugs. Mesurez l'ancienneté en anniversaires. Appliquez les deux tranches cumulativement. Gardez l'indemnité acquise et la quote-part due comme deux montants distincts, pour qu'un départ requalifié soit un champ et non un recalcul. Réglez-vous sur le salaire réel. Et provisionnez mensuellement, afin que le délai d'une semaine de l'article 88 tombe sur une provision qui existe déjà plutôt que sur une découverte.

Si vous portez ce calcul dans un tableur, ou dans un SIRH dont les chiffres ne concordent pas avec le calculateur du ministère, cet écart mérite d'être mesuré avant qu'un salarié ne parte. Dites-nous à quoi ressemble votre stack et nous rapprocherons un échantillon de vos soldes réels du texte légal — les désaccords se logent en général aux trois mêmes endroits, et il est moins coûteux de les trouver maintenant que devant une commission du travail.