Обновили печатную форму счёта-фактуры под форму, действующую с 01.04.2026 (Постановление Правительства РФ №26 от 23.01.2026, с учётом более поздних правок). Прод одного из клиентов работает на Odoo 10, и заняло это не один заход, а три, с реальной сверкой по бланку от клиента.
Первым делом — не тот модуль
Первые правки сделали в модуле l10n_ru_accounting, написанном под Odoo 17. Оказалось, что на проде эта версия вообще не установлена — клиентский сервер работает на Odoo 10 (Python 2.7), а реальная форма счёта-фактуры лежит в других модулях: l10n_ru_doc и l10n_ru_doc_update, ветка 10.0. Пришлось переносить изменения в правильное место, прежде чем что-либо деплоить.
Заход первый: строка 5б, ОГРНИП, альбомная ориентация
- Добавлена строка 5б — ссылка на счёт-фактуру, выставленную при получении аванса
- «Свидетельство о государственной регистрации» ИП заменено на ОГРНИП (свидетельств как физического документа больше не существует)
- Найден и исправлен независимый баг: отчёт «Счёт-фактура без подписей и печати» печатался в книжной ориентации вместо альбомной — неверный
paperformat_id, скопированный по ошибке с другого отчёта
Вставка новой строки сдвинула позиционные XPath (TR[11], TR[12]...) в наследуемом шаблоне. Чтобы не полагаться на ручной подсчёт — ошибка здесь молча портит боевой документ, — смоделировали финальное наследование локально через lxml и проверили порядок строк до деплоя.
Заход второй: реальный бланк от клиента
После первого деплоя клиент прислал реальный образец формы. Сверка показала три расхождения: не было строки «Исправление», ссылка на постановление в шапке была устаревшей, а строки шапки должны быть пронумерованы по полям — (2), (2а), (2б)... (8), как в официальном бланке. Обновили и то, и другое, и третье:
- Добавлена видимая строка «Исправление № – от –»
- Шапка «Приложение № 1» дополнена актуальными реквизитами: (в ред. Постановления Правительства РФ от 16.08.2024 № 1096) и (в ред. Письма ФНС от 26.12.2025 № СД-4-3/11730@)
- Полная нумерация строк на полях: (2), (2а), (2б), (3), (4), (5), (5а), (5б), (6), (6а), (6б), (7), (8)
Заход третий: скрытый третий наследник
При финальной сверке нашли ещё одну мелочь — дублирование «к постановлению к постановлению» из-за лишнего span. А заодно обнаружился модуль l10n_ru_inn, о котором никто не знал: он полностью подменяет строку «Адрес» покупателя через хрупкий XPath following-sibling::* и из-за этого стирал только что добавленный номер (6а). Без этой находки нумерация осталась бы неполной, несмотря на то что в первых двух модулях всё было верно.
Как проверяли каждый деплой
После каждого обновления модулей на проде: остановка Odoo → -u l10n_ru_doc,l10n_ru_doc_update,l10n_ru_inn → проверка лога на ошибки/трейсбеки → запуск сервиса → рендер обоих шаблонов напрямую через env['report'].get_html() на реальном счёте → построчная сверка извлечённого текста с образцом.
Итог
Финальная сверка — 100% совпадение с образцом клиента: цитата постановления без дублей, строка «Исправление» на месте, нумерация строк идёт без пропусков. Три коммита, три модуля (l10n_ru_doc, l10n_ru_doc_update, l10n_ru_inn), задеплоены на прод без единого падения сервиса дольше нескольких секунд на каждое обновление.