Соберите УПД и счёт-фактуру в XML формата ФНС 5.03
Сборка и проверка XML УПД, счёта-фактуры и документа об отгрузке в формате ФНС 5.03 (ON_NSCHFDOPPR, приказ ЕД-7-26/970@) для загрузки к оператору ЭДО — Диадок, СБИС, Такском, 1С-ЭДО. Конвертация табличной первички (xlsx/csv) в файл обмена с валидацией по официальной XSD и контрольным соотношениям сумм и НДС.
Как агент работает
Формат один — 5.03 по приказу ФНС от 19.12.2023 № ЕД-7-26/970@ в редакции приказа от 15.11.2024 № ЕД-7-26/1032@; версии 5.01 и 5.02 недействительны с 01.04.2025, и оператор ЭДО отклоняет такой файл уже после загрузки. Собираются три титула: УПД со стороны продавца (СЧФДОП), счёт-фактура (СЧФ) и документ об отгрузке (ДОП).
Табличная часть переносится, а не пересобирается: строки идут через rows_to_positions, который распознаёт русские заголовки, подставляет ОКЕИ по единице измерения и называет отброшенные строки, а не пропускает их молча. Напечатанные суммы, НДС и итог попадают в XML как есть; расхождение до копейки — округление исходника, больше копейки — ошибка сборки, и чинится она в исходнике.
Отказы операторов почти всегда упираются в реквизиты: кодировка windows-1251 без BOM, дата 12.03.2026 и время 14.03.22, суммы в рублях с точкой, НомерДок и ДатаДок вместо НомерСчФ, СвЮЛУч вместо СвЮЛ, ТаблСчФакт со СведТов, вложенный СумНал, «без НДС» вместо ставки 0%, БезДокОснПер со значением 1. Имя файла обязано совпадать с ИдФайл, поэтому переименовывать его нельзя.
Готовый файл проверяется по официальной XSD и контрольным соотношениям, а сверку с исходником делает reconcile_with_source — без ожидаемых значений он отказывает, потому что сверять не с чем. За рамками навыка остаются ответный титул покупателя ON_NSCHFDOPPK и приём входящих УПД, электронная подпись, блок СвОЭДОтпр, а также ТОРГ-12 и акт выполненных работ.
Примеры задач
УПД из Excel в XML для Диадока
Агент превратит таблицу отгрузки (xlsx/csv) в файл обмена ON_NSCHFDOPPR формата ФНС 5.03 и проверит его по официальной XSD до загрузки к оператору ЭДО.
Проверка готового файла перед отправкой
XML прогоняется по схеме ФНС и контрольным соотношениям: суммы позиций, НДС и итоги сходятся до копейки, каждое расхождение показывается списком.
Счёт-фактура и документ об отгрузке отдельно
Кроме УПД (СЧФДОП) агент собирает отдельные счёт-фактуру (СЧФ) и документ об отгрузке (ДОП) — для документооборота, где они идут раздельно.
Вопросы и ответы
Какой формат файла на выходе?
XML по приказу ФНС № ЕД-7-26/970@ в редакции № ЕД-7-26/1032@, версия 5.03 — единственная, которую операторы ЭДО принимают с 01.04.2025. Форматы 5.01 и 5.02 недействительны.
С какими операторами ЭДО совместим файл?
Формат единый для всех операторов: Диадок, СБИС, Такском, ЭДО Лайт, 1С-ЭДО. Файл загружается в любой из них без доработок.
Что будет, если данные не проходят валидацию?
Файл не отдаётся. Агент показывает, какие поля не прошли XSD или контрольные соотношения сумм и НДС, и запрашивает недостающие данные.
УПД, счёт-фактура и ДОП в XML для ЭДО (формат ФНС 5.03)
Область: сборка и проверка файлов обмена
ON_NSCHFDOPPR— титул продавца УПД (СЧФДОП), счёта-фактуры (СЧФ) и документа об отгрузке (ДОП) для загрузки к любому оператору ЭДО (Диадок, СБИС, Такском, ЭДО Лайт, 1С-ЭДО). Не путать сcommerceml_ru(обмен 1С↔сайт),fns_xml_ru(2-НДФЛ/3-НДФЛ/ЕГРЮЛ) иaccounting_docs_ru(та же первичка, но в Excel).
Нормативная база: приказ ФНС от 19.12.2023 № ЕД-7-26/970@ в редакции приказа от 15.11.2024 № ЕД-7-26/1032@. Версия формата — только 5.03. Форматы 5.01 и 5.02 недействительны с 01.04.2025: оператор ЭДО отклоняет такой файл, а пользователь видит отказ уже после загрузки.
Главное правило
Собранный файл не патчится — ни регуляркой, ни побайтово, ни правкой текста: ошибка XSD означает неверный doc, его и чинить, а потом пересобирать save_upd_xml. Патч мимо сборщика ломает ИдФайл, кодировку windows-1251 и повторяется при каждом следующем запуске.
Табличная часть передаётся целиком — со всеми денежными колонками, какие есть в исходнике. rows_to_positions сам находит суммы, НДС и итог по строке; они попадают в XML как напечатаны, а не пересчитываются. Отсюда и reconcile_with_source(report, positions=positions) без expected_total: ожидаемый итог берётся из колонки исходника, а сверка расчёта с самим собой ничего не доказывает.
Конвертация, а не пересборка
Исходный документ — единственный источник содержания. Задача звучит как «переделай в XML», но по сути это перенос: то, что напечатано в присланном файле, обязано оказаться в XML без изменений и без потерь.
- Табличная часть входит в документ только через
rows_to_positions. Разбирать таблицу самостоятельно — по координатам ячеек (df.iloc[7, 3]), regex'ом по тексту, «на глаз» из превью — запрещено: именно так теряются строки с объединёнными ячейками и переносами в наименовании. - Строка без наименования больше не пропускается молча:
rows_to_positionsпадает и называет отброшенные строки. Служебные строки (итог, разделитель, повтор шапки) пропускаются только явнымallow_partial=True— и это решение надо озвучить клиенту. - Реквизиты берутся из исходника дословно: наименования, ИНН/КПП, адреса, номер и дата документа, основание передачи. Переформулировать, сокращать, «причёсывать» — нельзя.
- Чего в исходнике нет — спросить. Заглушки, «типовые» значения и данные из прошлых документов не подставлять.
- Суммы не пересчитываются, если они напечатаны: колонки суммы без налога, НДС и стоимости с налогом переносятся как есть, расчёт остаётся только запасным вариантом для колонок, которых в таблице нет. Расхождение до копейки — округление исходника, и побеждает исходник; расхождение больше копейки — ошибка сборки с обоими числами, и чинится оно в исходнике или в разметке колонок, а не подгонкой.
- XSD и контрольные соотношения проверяют файл сам по себе: собранный из половины таблицы документ проходит их полностью. Единственное, что связывает результат с исходником, —
reconcile_with_source.
Ловушки формата — источник почти всех отказов операторов
| Реквизит | Неверно | Верно |
|---|---|---|
| Кодировка | UTF-8, тем более с BOM | windows-1251, без BOM |
| Даты | 2026-03-12 | 12.03.2026 (ДатаТип) |
| Время | 14:03:22 | 14.03.22 (ВремяТип, разделитель — точка) |
| Суммы | копейки целым числом (6550000) | рубли с двумя знаками (65500.00), разделитель — точка |
| Номер СФ | НомерСчФ / ДатаСчФ | НомерДок / ДатаДок |
| Организация | СвЮЛ | СвЮЛУч (для ИП — СвИП + ФИО) |
| Табличная часть | <СвТов> | <ТаблСчФакт> → <СведТов> |
| Сумма НДС | атрибут СумНал="0" | вложенный <СумНал><СумНал>360.00</СумНал></СумНал> |
| Освобождение | НалСт="0%" | НалСт="без НДС" + <СумНал><БезНДС>без НДС</БезНДС></СумНал> |
| Валюта | атрибут КодОКВ на СвСчФакт | отдельный <ДенИзм КодОКВ="643" НаимОКВ="Российский рубль"/> |
| Адрес | <АдрРФ><АдрТекст>… | АдрРФТип не имеет дочерних узлов; свободную строку класть в <АдрИнф КодСтр="643" НаимСтран="РОССИЯ" АдрТекст="…"/> |
| Передача без договора | <БезДокОснПер>БЕЗ ДОКУМЕНТА-ОСНОВАНИЯ</БезДокОснПер> | <БезДокОснПер>1</БезДокОснПер> — по XSD это перечисление из одного значения 1 |
Обязательные блоки
Файл—ИдФайл,ВерсФорм="5.03",ВерсПрог(все три required).Документ—КНД="1115131",Функция,ДатаИнфПр,ВремИнфПр.СвСчФакт—НомерДок,ДатаДок,СвПрод,СвПокуп,ДенИзм.ТаблСчФакт— минимум однаСведТов(обязателенНалСти блокСумНал) плюсВсегоОплсСумНалВсего.СвПродПер— дляСЧФДОПиДОП:СодОпери либоОснПер(договор/спецификация), либоБезДокОснПер. УОснПеробязательны все три реквизита — наименование, номер и дата. Если в исходнике напечатано только «Основной договор» без номера и даты, дату не выдумывать: спросить клиента либо убратьоснованиеизпередача— тогда соберётсяБезДокОснПер, и это надо назвать в ответе.Подписант—СпосПодтПолномиФИО; блок обязателен, документ без него не проходит XSD.
ИдФайл строится по шаблону ON_NSCHFDOPPR_{ИНН+КПП продавца}_{ИНН+КПП покупателя}_{ГГГГММДД}_{UUID}_0_0_0_0_0_00 и обязан совпадать с именем файла — за это отвечает make_id_fajl, имя возвращает save_upd_xml. Переименовывать файл после сборки нельзя.
fns_upd — фасад, из него доступно всё:
save_upd_xml(doc, output_dir="/home/user/output")→ путь;build_upd_xml(doc)→(имя, байты).validate_upd_xml(path|bytes)→{"valid", "errors", "warnings", "summary", "reconciled"};format_report(report)— печатный вид.reconcile_with_source(report, expected_rows=None, expected_total=None, positions=None)— сверка готового XML с исходником; расхождение по числу позиций или итогу переводит отчёт вvalid=False. Ожидаемый итог берётся из колонки исходника; переданный вручнуюexpected_total, который с ней расходится, сам становится ошибкой. Без ожидаемых значений отказывает: сверять не с чем.rows_to_positions(rows, mapping=None, default_rate=None, allow_partial=False)— DataFrame /list[dict]/list[list]→ позиции; распознаёт русские заголовки, подставляет ОКЕИ по единице измерения. ВозвращаетPositionListсsource_rows,dropped,totals(уйдёт в XML) иsource_totals(напечатано в исходнике).line_amounts(line)— суммы одной позиции той же арифметикой, что и сборка;normalize_rate(value),guess_okei(unit),totals_of(positions),nds_amount(base, rate),money,fns_date,fns_time,make_id_fajl.- Имена колонок в
mappingи ключи позиций — одни и те же:наим,кол,ед,океи,цена,сумма_без_ндс,ставка,ндс,сумма_с_ндс,артикул,признак. Таблица, названная этими именами, разбирается безmapping.
Структура doc:
Контрагент с ИНН из 12 цифр автоматически собирается как ИП (нужны фамилия/имя), из 10 — как юрлицо. сумма_без_ндс в позиции имеет приоритет над цена × кол — так переносятся строки со скидкой; расхождение уходит в warnings, не в ошибку.
Ограничения
- Скилл собирает титул продавца. Ответный титул покупателя (
ON_NSCHFDOPPK) и приём входящих УПД сюда не входят. - Электронная подпись не формируется: файл загружается в ЭДО неподписанным, подпись накладывает оператор.
<СвОЭДОтпр>(идентификаторы участников ЭДО) не заполняется — оператор проставляет их при отправке.- ТОРГ-12 и акт выполненных работ — другие приказы и другие XSD, этим скиллом не покрываются.
Похожие навыки
Попробуйте этот навык
Зарегистрируйтесь и используйте навык «УПД и счета-фактуры в XML для ЭДО (ФНС 5.03)» бесплатно.