Дата: 12.08.2026. Эталон — reference/etalon-punc-avgust-2024.xlsx («Пример выгрузки готового отчета.xlsx» заказчика). Все числа получены запуском python3 verify_punc_full.py; сырой протокол — evidence/verify-punc-full.txt, машинный реестр — evidence/punc-registry.csv (разделитель ;, UTF-8).
**Итог одной строкой: 2368 проверок, совпало 2347, расхождений 24. Ошибок портирования среди них нет: 21 расхождение вызвано отсутствием данных за сентябрь 2024 в наборе 00102, 3 — вторым комплектом листов эталона, правило появления которого из эталонов не выводится. Код после сверки не правился.**
Реестр расхождений одним файлом (CSV, открывается Excel): punc-registry.csv. Спецификация расчёта: spec-punc.html. Приёмка предыдущего шага: punc-acceptance-step4.html.
Сверка идёт не «на глаз», а по четырём уровням для каждой ячейки:
| Уровень | Что сравнивается |
|---|---|
| значение | число или текст ячейки; числа — с двоичным допуском abs 1e-9 / rel 1e-12 (это допуск на представление double, а не на «похоже»: 12896242.430418974 против ...97 — тот же double, 4.605 против 9.629 — расхождение) |
| формула | текст формулы (лист «Сравнение» держится на формулах =B6, =SUM(C5:C10), =F5-C5, …) |
| числовой формат | number_format каждой ячейки (#,##0.000, 0.00%, денежный, @) |
| структура | объединённые диапазоны листа, состав и порядок листов книги |
Сверялись обе выгрузки: собранная в процессе (punc_template.render) **и файл, реально отданный сервисом по HTTP** (GET /api/punc/export?contract_id=20&year=2024&month=8 → HTTP 200, 13 536 байт, evidence/step5-live-aug.xlsx, заголовки — evidence/step5-live-aug.headers).
| Объект сверки | Проверок | Совпало | Расхождений |
|---|---|---|---|
| Лист «август 2024» (A1:R26): 468 ячеек × (значение + формат) | 936 | 936 | 0 |
| Тот же лист в файле из HTTP-ответа сервиса | 936 | 936 | 0 |
| Лист «Сравнение» (A1:M13 → 143 ячейки × 2) + 5 объединённых диапазонов | 291 | 271 | 20 |
| Арифметика формул спецификации на листах, которые нечем посчитать (см. §4) | 204 | 204 | 0 |
| Состав и порядок листов книги | 1 | 0 | 1 |
| Листы «сентябрь 2024», «август 2024_1», «сентябрь 2024_1» — листа в книге нет | — | — | 3 |
| Всего | 2368 | 2347 | 24 |
Лист «август 2024» совпал полностью, включая полную двоичную точность чисел (59921.393000000004, 4.3172822696), все прочерки -, пустую B5, хвостовой пробел в B4 и числовые форматы всех 468 ячеек. Лист «Сравнение» совпал по всем формулам (20 расхождений — только в 20 ячейках-константах, см. §3) и по всем форматам.
Полный машинный реестр: evidence/punc-registry.csv. Ниже он же, сгруппированный.
Причина у всех одна: агрегаты «Сравнения» считаются по всем листам комплекта (SPEC-PUNC §6), в эталоне это август + сентябрь, а конструктор посчитал только август.
| Строка | Поле | Ячейки | Значение эталона | Значение конструктора |
|---|---|---|---|---|
| 5 | в т.ч. покупка мощности, объём | B5, E5 | 9.629 | 4.605 |
| 5 | в т.ч. покупка мощности, стоимость | C5, F5 | 8 368 852.07187 | 3 965 543.75955 |
| 6 | в т.ч. покупка ЭЭ, объём | B6, E6 | 7 130 126 | 3 437 811 |
| 6 | в т.ч. покупка ЭЭ, стоимость | C6, F6 | 12 896 242.430418974 | 5 842 311.590378701 |
| 7 | Услуга по передаче, объём | B7, E7 | 7 118 689 | 3 432 410 |
| 7 | Услуга по передаче, стоимость | C7, F7 | 16 872 905.76768 | 8 067 566.612380001 |
| 8 | Сбытовая надбавка, стоимость | C8, F8 | 1 905 244.7550360002 | 901 881.397263 |
| 9 | Инфраструктура, стоимость | C9, F9 | 34 295.90606 | 16 535.87091 |
| 10 | УИРП, объём | B10, E10 | 11 437 | 5 401 |
| 10 | УИРП, стоимость | C10, F10 | 6.6525799999999995 | 3.99674 |
Классификация причины: отличие исходных данных, не ошибка портирования. Доказательство — в §4.2: при подстановке строк сентября из эталонной выгрузки лист «Сравнение» совпадает с эталоном полностью (0 расхождений на 286 проверках). Формульные ячейки (D, G, H, I, J, K, L, M и итоговая строка 11) расхождений не дали вообще — формулы перенесены как есть, включая H11=SUM(H5:H9) без строки УИРП.
| Лист эталона | Что в конструкторе | Причина | Классификация |
|---|---|---|---|
| «сентябрь 2024» (468 ячеек) | листа нет; запрос за сентябрь → HTTP 400 с текстом причины | в наборе 00102 единственный период — D_Year=2024, D_Month=8 (386 строк); строк за сентябрь нет ни по одному договору и типу документа | отличие исходных данных |
| «август 2024_1» (468 ячеек) | листа нет | эталон содержит второй комплект листов; см. §3.4 | отличие эталона от переданной логики |
| «сентябрь 2024_1» (468 ячеек) | листа нет | то же | отличие эталона от переданной логики |
август 2024 | сентябрь 2024 | август 2024_1 | сентябрь 2024_1 | Сравнениеавгуст 2024 | СравнениеПричина — сумма двух предыдущих пунктов (нет сентября + не воспроизводится второй комплект). Порядок листов у совпадающих имён верный: лист периода первым, «Сравнение» последним.
Поячеечное сравнение листов эталона между собой:
| Пара листов эталона | Непустых ячеек | Различий |
|---|---|---|
| «август 2024» ↔ «август 2024_1» | 363 / 363 | 0 |
| «сентябрь 2024» ↔ «сентябрь 2024_1» | 346 / 346 | 0 |
То есть второй комплект — точная копия первого, а не второй сценарий расчёта с другими числами. Это уточняет [ВОПРОС 1] спецификации, но не закрывает его: из эталонов не выводится, при каком условии код печатает период дважды (это может быть и особенность конкретной выгрузки, и правило вида «раскладка + сводка»). Дублировать листы «на всякий случай» — додумывание логики, прямо запрещённое ТЗ, поэтому конструктор по-прежнему печатает один лист на период. Правило дублирования — за заказчиком (одна строка ответа: дублировать всегда / никогда / по условию).
К колонкам самих эталонных листов применены формулы спецификации: K = D+E+F+G+I−J (прочерк = 0), N = D·C, O = E·C, P = (F−J)·C, Q = G·C, R = I·C.
| Лист эталона | Проверок | Расхождений |
|---|---|---|
| «сентябрь 2024» | 66 | 0 |
| «август 2024_1» | 72 | 0 |
| «сентябрь 2024_1» | 66 | 0 |
Это проверяет перенос формул там, где нет исходных данных для проверки выборки: на 11 строках сентября, которых конструктор не считал, его формулы дают ровно те числа, что лежат в эталоне.
Строки сентября берутся из эталонной выгрузки заказчика (это подстановка чисел, а не расчёт конструктора) и подаются в штатный рендер:
| Проба | Проверок | Расхождений |
|---|---|---|
| Лист «сентябрь 2024»: вёрстка, шапка, прочерки, колонка L, форматы | 936 | 0 |
| Лист «Сравнение» с подставленным сентябрём | 286 + 5 объединений | 0 |
Вывод: вёрстка листа сентября (имя листа, B6, A9 = за сентябрь 2024 г., другой порядок разделов, матрица прочерков, L только у «Электрической энергии») и агрегаты «Сравнения» (в т.ч. деление объёма мощности на 1000) воспроизводятся точно. Не хватает только исходных строк за сентябрь.
Ничего. После сверки код расчёта и вёрстки (app.py, mart.py, punc_template.py) не изменялся — ошибок портирования сверка не выявила, а расхождения §3 исправлению кодом не подлежат (их причина — данные и неопределённое правило эталона). Добавлены только средства проверки, на результат отчёта не влияющие:
| Файл | Назначение |
|---|---|
verify_punc_full.py | сплошная сверка всех листов на 4 уровнях + генерация реестра |
evidence/punc-registry.csv | машинный реестр расхождений (лист / строка / колонка / поле / эталон / конструктор / вид / причина) |
evidence/verify-punc-full.txt | протокол прогона |
evidence/step5-live-aug.xlsx, .headers | файл и заголовки HTTP-ответа сервиса, участвовавшие в сверке |
тесты в test_punc.py | регресс: формулы воспроизводят эталонный сентябрь; листы _1 идентичны первым |
| Расхождений | Что нужно от заказчика |
|---|---|
| 21 (лист сентября + 20 ячеек «Сравнения») | выгрузка наборов 00102 и 00101 за сентябрь 2024 — в data.db их нет; после загрузки сверка идёт тем же скриптом без правок кода |
| 3 (второй комплект листов и состав книги) | правило: печатать ли каждый период дважды и при каком условии (в эталоне обе копии идентичны) |
| — | Код к отчету.txt в контуре прогона по-прежнему отсутствует (find / -iname '*Код к отчету*' → пусто); спецификация снята с эталонной выгрузки и сохранившихся выжимок кода. С кодом на руках можно было бы подтвердить оба пункта без предположений |
python3 -m pytest -q # тесты, включая регресс сверки
python3 verify_punc_full.py # 2368 проверок, 24 расхождения, реестр в evidence/
python3 app.py --port 8911
curl -o punc.xlsx "http://127.0.0.1:8911/api/punc/export?contract_id=20&year=2024&month=8"
curl "http://127.0.0.1:8911/api/punc/export?contract_id=20&year=2024&month=9" # 400 + причинаРазвёрнутый сервис: https://sol-msqct09w-2ae.apps.sreda-ai.ru (проверка — /healthz, выгрузка — /api/punc/export?contract_id=20&year=2024&month=8). Страницы: приёмка шага 5 — punc-acceptance.html, спецификация — spec-punc.html, приёмка шага 4 — punc-acceptance-step4.html (все — по ссылке проекта https://app.sreda-ai.ru/api/projects/sol-msqct09w-2ae/preview/).