- synthgen/config.py: Config, load_config (YAML + --set), dump_config, проверки диапазонов §3 - synthgen/rng.py: rng_for (SHA-256 → Random), stable_hash - synthgen/__main__.py: разбор --config/--set/--out/--force, ошибка конфигурации → код 2 - synthgen/examples/default.yaml: все ключи §3 со значениями по умолчанию - копии из synthetic-group/gen (#35): inn, xlsx, ledger, chart (+80.09, 91.09 из seed arm-core) - тесты: config, inn, ledger; conftest с маркерами parser/slow - .gitignore: out/ - спека: решения 15–16 Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
37 lines
1.3 KiB
Python
37 lines
1.3 KiB
Python
"""Источник: synthetic-group/gen/inn.py (#35).
|
|
|
|
Вымышленные ИНН: регион `00` (не существует), верная контрольная сумма ФНС. Без случайности."""
|
|
|
|
_W10 = (2, 4, 10, 3, 5, 9, 4, 6, 8)
|
|
_W12_1 = (7, 2, 4, 10, 3, 5, 9, 4, 6, 8)
|
|
_W12_2 = (3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8)
|
|
|
|
|
|
def _check(digits: list[int], weights: tuple[int, ...]) -> int:
|
|
return sum(d * w for d, w in zip(digits, weights)) % 11 % 10
|
|
|
|
|
|
def make_inn10(seq: int) -> str:
|
|
"""ИНН юрлица: `00` + 7 цифр номера + контрольная цифра."""
|
|
body = [int(c) for c in f"00{seq:07d}"]
|
|
return "".join(map(str, body)) + str(_check(body, _W10))
|
|
|
|
|
|
def make_inn12(seq: int) -> str:
|
|
"""ИНН физлица/ИП: `00` + 8 цифр номера + две контрольные цифры."""
|
|
body = [int(c) for c in f"00{seq:08d}"]
|
|
body.append(_check(body, _W12_1))
|
|
body.append(_check(body, _W12_2))
|
|
return "".join(map(str, body))
|
|
|
|
|
|
def is_valid(inn: str) -> bool:
|
|
if not inn.isdigit():
|
|
return False
|
|
digits = [int(c) for c in inn]
|
|
if len(digits) == 10:
|
|
return digits[9] == _check(digits[:9], _W10)
|
|
if len(digits) == 12:
|
|
return digits[10] == _check(digits[:10], _W12_1) and digits[11] == _check(digits[:11], _W12_2)
|
|
return False
|