sync efactura-generator -> 0.9-beta-14
Mirror sincronizat cu repo canonic /workspace/efactura-generator. CLAUDE.md: documentat workflow sync + exclude config.json din rsync deploy. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
71
efactura-generator/js/validation/cif.js
Normal file
71
efactura-generator/js/validation/cif.js
Normal file
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* js/validation/cif.js — PR-VALID-IDS (A9)
|
||||
* Validare CIF/CUI românesc prin sumă ponderată (mod 11, mod 10).
|
||||
* Funcție pură, fără efecte secundare, fără dependențe externe.
|
||||
*/
|
||||
|
||||
// Greutățile pentru cifrele 1-9 (se aplică pe primele 9 cifre ale CIF-ului).
|
||||
const WEIGHTS = [7, 5, 3, 2, 1, 7, 5, 3, 2];
|
||||
|
||||
/**
|
||||
* Validează un CIF/CUI românesc.
|
||||
*
|
||||
* Algoritm:
|
||||
* 1. Elimină prefixul "RO" dacă există (case-insensitive).
|
||||
* 2. Elimină spații.
|
||||
* 3. Verifică că are între 2 și 10 cifre.
|
||||
* 4. Completează cu zerouri la stânga până la 10 cifre.
|
||||
* 5. Calculează suma ponderată pe primele 9 cifre cu WEIGHTS.
|
||||
* 6. (sumă * 10) % 11 % 10 trebuie să fie egal cu cifra de control (ultima).
|
||||
*
|
||||
* @param {string} value — valoarea brută din câmp (poate fi goală, poate conține "RO")
|
||||
* @returns {{ valid: boolean, message: string }}
|
||||
*/
|
||||
export function validateCIF(value) {
|
||||
if (!value || value.trim() === '') {
|
||||
return { valid: true, message: '' }; // câmp gol — valid (nu e required check)
|
||||
}
|
||||
|
||||
let normalized = value.trim().toUpperCase();
|
||||
|
||||
// Elimină prefixul RO
|
||||
if (normalized.startsWith('RO')) {
|
||||
normalized = normalized.slice(2).trim();
|
||||
}
|
||||
|
||||
// Elimină spații și cratime rămase
|
||||
normalized = normalized.replace(/[\s\-]/g, '');
|
||||
|
||||
// Trebuie să conțină doar cifre
|
||||
if (!/^\d+$/.test(normalized)) {
|
||||
return { valid: false, message: 'CIF invalid: conține caractere nepermise' };
|
||||
}
|
||||
|
||||
// Lungime: minim 2, maxim 10 cifre
|
||||
if (normalized.length < 2 || normalized.length > 10) {
|
||||
return { valid: false, message: 'CIF invalid: lungimea trebuie să fie între 2 și 10 cifre' };
|
||||
}
|
||||
|
||||
// Completează cu zerouri la stânga până la 10 cifre
|
||||
const padded = normalized.padStart(10, '0');
|
||||
|
||||
// Extrage primele 9 cifre (pentru ponderare) și cifra de control (ultima)
|
||||
const digits = padded.split('').map(Number);
|
||||
const checkDigit = digits[9];
|
||||
const controlDigits = digits.slice(0, 9);
|
||||
|
||||
// Calculează suma ponderată
|
||||
let sum = 0;
|
||||
for (let i = 0; i < 9; i++) {
|
||||
sum += controlDigits[i] * WEIGHTS[i];
|
||||
}
|
||||
|
||||
// Cifra de control calculată
|
||||
const computed = (sum * 10) % 11 % 10;
|
||||
|
||||
if (computed !== checkDigit) {
|
||||
return { valid: false, message: 'CIF invalid: cifra de control nu se potrivește' };
|
||||
}
|
||||
|
||||
return { valid: true, message: '' };
|
||||
}
|
||||
Reference in New Issue
Block a user