Files
portal/docs/superpowers/specs/2026-06-17-format-rub-demo-spec.md
T
Дмитрий 3ba703d9c9 docs(приёмка): корпус приёмочного теста + поправка №15 + статусы реестра
F-CORPUS: ключевые документы приёмки liderra.ru лежали untracked — мастер-
хэндофф ссылался на отсутствующие в git файлы (битые ссылки в новом клоне).
Закоммичены: R0–R5 + stepbystep ранбуки, хартия, prod-logic-map, эфир-хэндофф,
imitation-checks-table, live-demo/ (эфир-плеер) + смежные specs/планы серий
f1-card/phase1/televizor/g1/g2 (решение владельца — «корпус + смежные»).

F-DELPROJ: пункт №15 checks-table → «удаление проекта со сделками запрещено
(422), сделки целы» (было неточно «сделки сохранены», сверено по
ProjectService::delete).

Реестр находок: статусы F-DEPTRAC/F-CSV/F-REMIND/F-DELPROJ/F-CORPUS → закрыто.
.gitleaks.toml: ранбуки приёмки добавлены в allowlist (синтетические тест-
телефоны, та же категория что plans/specs/audits).
live-demo HTML: stylelint --fix (#fff→#ffffff).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 04:48:50 +03:00

3.5 KiB

Спецификация: чистый помощник форматирования рублёвых сумм formatRub

Цель

Дать единый чистый помощник для отображения денежных сумм в интерфейсе: на вход — целое число копеек, на выход — человекочитаемая строка вида 1 234,56 ₽. Помощник не обращается к БД, не читает локаль из окружения, не имеет побочных эффектов — только детерминированное преобразование числа в строку.

Контракт функции

formatRub(kopecks) принимает целое число копеек (integer, может быть отрицательным) и возвращает строку. Тысячи рублёвой части разделяются узким неразрывным пробелом, копейки отделяются запятой и всегда показываются двумя цифрами, в конце — неразрывный пробел и символ . Функция чистая: один и тот же вход всегда даёт один и тот же выход, внешнее состояние не читается и не меняется.

Краевые случаи

  • 00,00 ₽ (ноль показывается явно, не пустой строкой).
  • Отрицательная сумма → знак минус перед числом: -500 копеек → -5,00 ₽.
  • Не целое (12.5) или не число (NaN, null, строка) → выбрасывается TypeError с понятным сообщением; молчаливое округление запрещено (потеря копеек недопустима).
  • Крупная сумма (123456789 копеек) → 1 234 567,89 ₽: разделитель тысяч ставится в каждой группе из трёх цифр рублёвой части.

Конвенция представления

Рублёвая и копеечная части получаются делением на 100 без потери точности через работу с целыми (рубли = Math.trunc, копейки = остаток по модулю 100), а не через плавающую арифметику над результатом деления. Разделитель тысяч — символ U+202F (narrow no-break space), десятичный разделитель — запятая (российская конвенция), суффикс валюты — U+00A0 + .

Критерий приёмки

Набор примеров вход→выход проходит как тесты: 0 → "0,00 ₽", -500 → "-5,00 ₽", 123456789 → "1 234 567,89 ₽", 99 → "0,99 ₽", 100 → "1,00 ₽". Передача 12.5 и "abc" приводит к TypeError. Функция не делает ни одного обращения к внешним ресурсам (проверяется отсутствием импортов кроме чистых утилит).

[
  {
    "id": "ctx-pricing-freeze",
    "kind": "EXTRACTED",
    "ref": "tools/cost-pricing.mjs",
    "anchor": "export const PRICING = Object.freeze("
  }
]