BUH_bot/docs/xml_fixes_applied.md
Игорь Надеин a16ffca725 Refactor validator for zero-price detection and fix XML generator for 1C EnterpriseData 1.20 compatibility
- Enhanced validator with critical zero-price validation
- Fixed currency GUIDs and money formatting in XML generator
- Removed incompatible VidED field
- Added comprehensive documentation
- Updated test files
2025-11-06 09:03:35 +03:00

12 KiB
Raw Blame History

Исправления XML генератора - 6 ноября 2025

Выполненные критичные исправления

✅ 1. Исправлена потеря копеек (КРИТИЧНО)

Было:

etree.SubElement(row_elem, "Сумма").text = str(int(total))  # Отбрасывались копейки
etree.SubElement(row_elem, "Цена").text = str(int(price))   # Отбрасывались копейки

Стало:

etree.SubElement(row_elem, "Сумма").text = f"{total:.2f}"  # 2 знака после запятой
etree.SubElement(row_elem, "Цена").text = f"{price:.2f}"   # 2 знака после запятой

Результат тестирования:

  • Цена: 1234.56 руб ✅ (было бы 1234)
  • Количество: 10 шт
  • Сумма: 12345.60 руб ✅ (было бы 12345)
  • Разница: 56 коп на строку, 5.60 руб на документ - это критично для налогового учёта!

✅ 2. Удалено поле ВидЭД (КРИТИЧНО)

Было:

etree.SubElement(doc, "ВидЭД").text = "ТОРГ12"

Стало:

# Поле удалено - его нет в схеме EnterpriseData 1.20

Причина:

  • Поле ВидЭД используется в УПД/ФормализованныхДокументах
  • В EnterpriseData 1.20 этого поля нет
  • Приводило к ошибке валидации по XSD

✅ 3. Fallback даты заменён на исключение (КРИТИЧНО)

Было:

except Exception as e:
    logger.error(f"Ошибка форматирования даты: {e}")
    return datetime.now().strftime("%Y-%m-%dT%H:%M:%S")  # Подставляем текущую дату

Стало:

except Exception as e:
    logger.error(f"Критическая ошибка: некорректная дата '{date_str}': {e}")
    raise ValueError(
        f"Невозможно сформировать документ с некорректной датой: {date_str}. "
        "Проверьте исходные данные."
    )

Причина:

  • Подстановка текущей даты вместо корректной - искажение первичного документа
  • Риск налоговых проблем (неверный период)
  • Теперь генерация прерывается с понятной ошибкой

⚠️ 4. Счета учёта закомментированы (опционально)

Было:

etree.SubElement(row_elem, "СчетУчета").text = "43"
etree.SubElement(row_elem, "СчетДоходов").text = "90.01.1"
etree.SubElement(row_elem, "СчетРасходов").text = "90.02.1"
etree.SubElement(row_elem, "СчетУчетаНДСПоРеализации").text = "90.03"

Стало:

# ВНИМАНИЕ: Следующие поля могут отсутствовать в XSD некоторых версий 1С
# Если импорт падает - закомментируйте эти строки
etree.SubElement(row_elem, "ТипЗапасов").text = "СобственныеТовары"
# TODO: Сделать опциональными через config
# etree.SubElement(row_elem, "СчетУчета").text = "43"
# etree.SubElement(row_elem, "СчетДоходов").text = "90.01.1"
# etree.SubElement(row_elem, "СчетРасходов").text = "90.02.1"
# etree.SubElement(row_elem, "СчетУчетаНДСПоРеализации").text = "90.03"

Причина:

  • Эти поля есть не во всех версиях EnterpriseData
  • Зависит от конфигурации 1С клиента
  • Оставлен только ТипЗапасов (более универсален)

Проблемы, требующие проверки с клиентом

⚠️ 1. Жёстко прошитые GUID справочников

Местоположение:

  • Валюта: 72357d18-63a8-11e8-80dd-0050569f5448 (RUB)
  • Страна: 67700c1b-63a8-11e8-80dd-0050569f5448 (Россия)
  • ЕдиницаИзмерения: cdf130e2-63a8-11e8-80dd-0050569f5448 (штука)

Риск:

  • Эти GUID уникальны для конкретной базы
  • В базе клиента могут быть другие GUID
  • Импорт завершится ошибкой "Объект не найден"

Решения:

  1. Получить GUID из базы клиента (запросом к 1С)
  2. Убрать <Ссылка>, передавать только коды (643, 796, RUB)
  3. Включить флаг "создавать отсутствующие объекты" в настройках обмена

Рекомендация:

<!-- Вариант А: Без Ссылки (пусть 1С найдёт по коду) -->
<Валюта>
  <ДанныеКлассификатора>
    <Код>643</Код>
    <НаименованиеПолное>Российский рубль</НаименованиеПолное>
    <КодЦифровой>643</КодЦифровой>
    <КодСимвольный>RUB</КодСимвольный>
  </ДанныеКлассификатора>
</Валюта>

<!-- Вариант Б: Получить GUID из базы клиента через HTTP-сервис -->

⚠️ 2. Структура валюты/банков

Текущая структура:

<Валюта>
  <Ссылка>guid</Ссылка>
  <ДанныеКлассификатора>
    <Код>643</Код>
    <Наименование>руб.</Наименование>
  </ДанныеКлассификатора>
</Валюта>

Проблема:

  • Структура может не соответствовать XSD 1.20 клиента
  • В разных версиях ED структура отличается

TODO:

  • Получить от клиента актуальный XSD EnterpriseData 1.20
  • Сверить структуру валюты, банка, страны
  • При необходимости адаптировать

⚠️ 3. Банк/счёт - некорректные ссылки

Текущий код (строка 833):

bank_elem = etree.SubElement(bank_acc_elem, "Банк")
etree.SubElement(bank_elem, "Ссылка").text = acc_id  # ❌ ID счёта вместо ID банка

Проблема:

  • Для банка должен быть свой GUID (из справочника "Банки")
  • Используется GUID счёта - это неверно

Рекомендация:

# Вариант А: Убрать Ссылку, передавать только БИК
bank_elem = etree.SubElement(bank_acc_elem, "Банк")
# НЕ создавать <Ссылка>
bank_data = etree.SubElement(bank_elem, "ДанныеКлассификатораБанков")
etree.SubElement(bank_data, "БИК").text = acc.get("bic", "")
# 1С найдёт банк по БИК

# Вариант Б: Получить GUID банка из МойСклад или 1С
bank_id = get_bank_guid_by_bic(acc.get("bic"))
etree.SubElement(bank_elem, "Ссылка").text = bank_id

⚠️ 4. Договор - сложная структура

Текущая структура:

<Договор>
  <Ссылка>uuid</Ссылка>
  <ВидДоговора>СПокупателем</ВидДоговора>
  <Организация>...</Организация>
  <Контрагент>...</Контрагент>
</Договор>

Проблема:

  • Детальная структура может не соответствовать XSD
  • Обычно договор - это просто ссылка

Варианты:

  1. Если договор УЖЕ существует в базе - передавать только <Ссылка>
  2. Если нужно создать - выносить в отдельный блок Message
  3. Уточнить у клиента бизнес-логику

Что нужно от клиента

1. XSD EnterpriseData 1.20

  • Актуальная схема для их версии 1С
  • Версия платформы (8.3.xx.xxxx)
  • Конфигурация (УТ, КА, ERP)

2. GUID справочников

Три варианта:

  • Получить через HTTP-сервис 1С
  • Экспортировать из базы вручную
  • Использовать коды без GUID (рекомендуется)

3. Тестовая среда

  • Доступ к тестовой базе для импорта
  • Логи ошибок импорта
  • Возможность итерации

4. Бизнес-требования

  • Как обрабатывать договоры? (создавать/ссылаться)
  • Как обрабатывать банки? (создавать/ссылаться)
  • Нужны ли счета учёта в строках?

План тестирования

Этап 1: Локальная проверка ✅

  • Копейки сохраняются
  • ВидЭД убран
  • Дата не подменяется
  • Счета учёта закомментированы

Этап 2: Проверка с XSD

  • Получить XSD от клиента
  • Валидация по XSD (xmllint или lxml)
  • Исправление несоответствий

Этап 3: Импорт в тестовую 1С

  • Импорт тестового XML
  • Проверка ошибок
  • Проверка контрольных сумм
  • Проверка НДС

Этап 4: Production

  • Финальные правки
  • Документация для пользователя
  • Мониторинг первых импортов

Риски и митигация

Риск Вероятность Влияние Митигация
GUID не найдены в базе Высокая Критично Убрать GUID, использовать коды
Структура не соответствует XSD Средняя Критично Получить XSD, адаптировать
Банк/счёт не создаётся Средняя Высоко Использовать БИК без GUID
Договор не распознаётся Низкая Средне Упростить до Ссылки
Копейки всё ещё теряются Низкая Критично Уже исправлено ✅

Выводы

✅ Что сделано:

  1. Копейки сохраняются - критично для налогового учёта
  2. ВидЭД убран - больше не ломает валидацию
  3. Даты проверяются - нет риска искажения
  4. Счета учёта опциональны - совместимость с разными версиями

⚠️ Что требует внимания:

  1. GUID справочников - высокий риск, нужен XSD клиента
  2. Структура объектов - зависит от версии ED
  3. Банк/счёт - нужна корректная логика

📋 Следующие шаги:

  1. Запросить у клиента XSD EnterpriseData 1.20
  2. Протестировать импорт в их тестовой базе
  3. Получить обратную связь по структуре
  4. Доработать под реальную схему

Готовность к продакшену: ~70%

  • Критичные баги исправлены ✅
  • Нужна проверка совместимости с клиентской 1С ⚠️