- 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
18 KiB
Анализ генератора XML EnterpriseData 1.20
Дата анализа: 6 ноября 2025 г.
Проверенные проблемы и их статус
❌ КРИТИЧНО: 1. Жёстко прошитые GUID справочников
Местоположение:
- Строки 773-776 (валюта RUB)
- Строки 878, 1027 (страна Россия)
- Строки 990-994 (единица измерения "шт")
Проблема:
# Валюта - жёстко прошитый GUID
if not currency_id:
currency_id = "72357d18-63a8-11e8-80dd-0050569f5448" # RUB
# Страна - жёстко прошитый GUID
etree.SubElement(country_elem, "Ссылка").text = "67700c1b-63a8-11e8-80dd-0050569f5448"
# Единица измерения - жёстко прошитый GUID
if not uom_id:
uom_id = "cdf130e2-63a8-11e8-80dd-0050569f5448" # шт (796)
Почему это критично:
- GUID справочников уникальны для каждой базы 1С
- В другой базе эти GUID не существуют
- Импорт завершится ошибкой "Объект не найден"
Рекомендация:
# ПРАВИЛЬНО: Передавать только код и наименование, без Ссылки
# Либо позволить 1С создать объект автоматически
<Валюта>
<!-- Убрать <Ссылка> если объект не существует -->
<ДанныеКлассификатора>
<Код>643</Код>
<НаименованиеПолное>Российский рубль</НаименованиеПолное>
<КодЦифровой>643</КодЦифровой>
<КодСимвольный>RUB</КодСимвольный>
</ДанныеКлассификатора>
</Валюта>
Решение:
- Либо получать GUID из конфигурации целевой базы
- Либо использовать флаг "создавать отсутствующие объекты"
- Либо убрать
<Ссылка>и передавать только классификаторы
⚠️ КРИТИЧНО: 2. Структура валюты/банков не соответствует XSD
Местоположение: Строки 767-780
Проблема:
currency_elem = etree.SubElement(doc, "Валюта")
etree.SubElement(currency_elem, "Ссылка").text = currency_id
currency_data = etree.SubElement(currency_elem, "ДанныеКлассификатора")
etree.SubElement(currency_data, "Код").text = currency.get("isoCode", "643")
Почему это проблема:
- Структура с вложенным
ДанныеКлассификатораможет не соответствовать XSD 1.20 - В типовых схемах ED часто используется плоская структура:
<Валюта><Ссылка/><Код/><Наименование/></Валюта>
Рекомендация:
- ОБЯЗАТЕЛЬНО сверить структуру с XSD принимающей системы
- Возможно, нужна плоская структура без
ДанныеКлассификатора
TODO:
- Получить актуальный XSD от клиента
- Проверить версию EnterpriseData в целевой 1С
- Адаптировать структуру под реальную схему
❌ КРИТИЧНО: 3. Неверные ссылки на банк/счёт
Местоположение: Строки 825-838
Проблема:
bank_acc_elem = etree.SubElement(doc, "БанковскийСчетОрганизации")
acc_id = acc.get("id", "")
etree.SubElement(bank_acc_elem, "Ссылка").text = acc_id # ID счёта
# Банк
bank_elem = etree.SubElement(bank_acc_elem, "Банк")
etree.SubElement(bank_elem, "Ссылка").text = acc_id # ❌ ОШИБКА: используем тот же ID
Почему это критично:
- Для банка должна быть ссылка на объект справочника "Банки" (другой GUID)
- Для счёта - ссылка на объект справочника "БанковскиеСчета"
- Использование одного ID для обоих объектов неверно
Рекомендация:
# ПРАВИЛЬНО: Разные ID для банка и счёта
bank_elem = etree.SubElement(bank_acc_elem, "Банк")
bank_id = acc.get("bank_id") or generate_bank_id_by_bic(acc.get("bic"))
etree.SubElement(bank_elem, "Ссылка").text = bank_id
# Или передавать без Ссылки, только классификатор
<Банк>
<ДанныеКлассификатораБанков>
<Наименование>Сбербанк</Наименование>
<БИК>044525225</БИК>
<КоррСчет>30101810400000000225</КоррСчет>
</ДанныеКлассификатораБанков>
</Банк>
Решение:
- Убрать
<Ссылка>для банка, передавать только БИК и наименование - 1С сама найдёт/создаст банк по БИК
⚠️ СРЕДНЕ: 4. Договор внутри "ДанныеВзаиморасчетов"
Местоположение: Строки 887-922
Проблема:
contract_elem = etree.SubElement(settlement_elem, "Договор")
contract_uuid = str(uuid.uuid5(uuid.NAMESPACE_DNS, f"contract-{cp_id}-{org_id}"))
etree.SubElement(contract_elem, "Ссылка").text = contract_uuid
etree.SubElement(contract_elem, "ВидДоговора").text = "СПокупателем"
# Далее вложенные Организация, Контрагент...
Почему это проблема:
- Детальная структура договора (с Организацией/Контрагентом внутри) может не соответствовать XSD
- В ED обычно ссылка на договор - это просто
<Ссылка>на существующий объект - Полное описание договора должно быть отдельной сущностью в Message
Рекомендация:
<!-- Вариант 1: Только ссылка (если договор уже есть) -->
<Договор>
<Ссылка>uuid-договора</Ссылка>
</Договор>
<!-- Вариант 2: Полный объект в отдельном блоке Message -->
<Message>
<Body>
<Справочник.ДоговорыКонтрагентов>
<Ссылка>uuid</Ссылка>
<ВидДоговора>СПокупателем</ВидДоговора>
<!-- ... -->
</Справочник.ДоговорыКонтрагентов>
<Документ.РеализацияТоваровУслуг>
<Договор>
<Ссылка>uuid</Ссылка> <!-- Ссылка на объект выше -->
</Договор>
</Документ.РеализацияТоваровУслуг>
</Body>
</Message>
TODO:
- Уточнить у клиента: договоры уже есть в базе или нужно создавать?
- Если создавать - вынести договор в отдельный блок Message
- Если использовать существующие - передавать только Ссылка
❌ КРИТИЧНО: 5. Потеря копеек
Местоположение: Строки 1012-1014
Проблема:
price = pos.get("price", 0) / 100 # Конвертируем из копеек
total = price * quantity
etree.SubElement(row_elem, "Сумма").text = str(int(total)) # ❌ Отбрасываем копейки
etree.SubElement(row_elem, "Цена").text = str(int(price)) # ❌ Отбрасываем копейки
Почему это критично:
- Округление вниз приводит к расхождению сумм
- НДС рассчитывается неверно
- Контрольные суммы не сходятся
- Невозможно сопоставить с УПД/счётом-фактурой
Пример:
Цена: 1234.56 руб → становится 1234 руб (потеря 56 коп)
Количество: 100 шт
Сумма должна быть: 123456.00 руб
Сумма получается: 123400 руб (потеря 56 руб!)
Рекомендация:
# ПРАВИЛЬНО: Сохранять копейки
price = pos.get("price", 0) / 100
total = price * quantity
etree.SubElement(row_elem, "Сумма").text = f"{total:.2f}" # 2 знака после запятой
etree.SubElement(row_elem, "Цена").text = f"{price:.2f}" # 2 знака после запятой
Решение:
- Использовать
Decimalдля денежных расчётов - Форматировать с 2 знаками:
f"{amount:.2f}" - НЕ использовать
int()для денежных сумм
⚠️ СРЕДНЕ: 6. Лишние поля в строке товара
Местоположение: Строки 1036-1039
Проблема:
etree.SubElement(row_elem, "ТипЗапасов").text = "СобственныеТовары"
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"
Почему это проблема:
- Эти поля есть не во всех версиях ED
- Не во всех прикладных решениях 1С используются эти поля
- Если их нет в XSD - валидация провалится
Рекомендация:
- Сделать эти поля опциональными (через настройку)
- Или убрать совсем - 1С подставит по умолчанию
- Или уточнить у клиента, нужны ли эти поля
TODO:
- Проверить XSD целевой системы
- Добавить флаг
include_accounting_fieldsв конфиг - По умолчанию отключить
⚠️ СРЕДНЕ: 7. ВидЭД внутри ED-документа
Местоположение: Строки 967-968
Проблема:
# ВидЭД
etree.SubElement(doc, "ВидЭД").text = "ТОРГ12"
Почему это проблема:
- Поле
ВидЭДсо значением "ТОРГ12" не входит в типовую схему ED 1.20 - Это поле используется в УПД/ФормализованныхДокументах, но не в EnterpriseData
- При валидации по XSD произойдёт ошибка
Рекомендация:
- Убрать это поле из документа ED
- Если нужно указать тип документа - использовать корректное поле из XSD
- Возможно, это поле относится к другому формату (УПД)
Решение:
# УБРАТЬ эту строку
# etree.SubElement(doc, "ВидЭД").text = "ТОРГ12"
⚠️ НИЗКО: 8. Резервные заглушки дат
Местоположение: Строки 648-657
Проблема:
def _format_datetime(self, date_str: str) -> str:
try:
dt = datetime.fromisoformat(date_str.replace('Z', '+00:00'))
return dt.strftime("%Y-%m-%dT%H:%M:%S")
except Exception as e:
logger.error(f"Ошибка форматирования даты: {e}")
return datetime.now().strftime("%Y-%m-%dT%H:%M:%S") # ❌ Подставляем текущую дату
Почему это проблема:
- Если дата не парсится - подставляется текущая
- Для первичных документов это искажение данных
- Риск налоговых проблем (неверная дата = неверный период)
Рекомендация:
def _format_datetime(self, date_str: str) -> str:
try:
dt = datetime.fromisoformat(date_str.replace('Z', '+00:00'))
return dt.strftime("%Y-%m-%dT%H:%M:%S")
except Exception as e:
logger.error(f"Критическая ошибка: некорректная дата '{date_str}': {e}")
raise ValueError(f"Невозможно сформировать документ с некорректной датой: {date_str}")
Решение:
- Поднимать исключение при ошибке парсинга даты
- НЕ подставлять резервные значения для критичных полей
- Блокировать генерацию XML с некорректными данными
Приоритеты исправления
🔴 СРОЧНО (блокируют импорт в 1С):
- ✅ Потеря копеек - исправить форматирование денежных сумм
- ⚠️ GUID справочников - убрать жёсткие UUID или получать из базы
- ⚠️ Банк/счёт - исправить структуру ссылок
- ✅ ВидЭД - убрать поле
🟡 ВАЖНО (могут вызвать проблемы):
- ⚠️ Структура валюты - сверить с XSD клиента
- ⚠️ Договор - упростить или вынести в отдельный блок
- ⚠️ Счета учёта - сделать опциональными
🟢 ЖЕЛАТЕЛЬНО (улучшение качества):
- ✅ Заглушки дат - поднимать исключения вместо fallback
Рекомендуемый план действий
Этап 1: Критичные исправления (сегодня)
- Исправить форматирование денежных сумм (добавить
.2f) - Убрать поле
ВидЭД - Заменить fallback даты на исключение
Этап 2: Проверка со стороны клиента (завтра)
- Получить актуальный XSD EnterpriseData 1.20 от клиента
- Проверить структуру валюты/банков/договоров в реальной схеме
- Уточнить: нужны ли счета учёта в строках?
Этап 3: Адаптация под реальную схему (2-3 дня)
- Убрать жёсткие GUID, использовать только классификаторы
- Исправить структуру банка (убрать Ссылку, оставить БИК)
- Упростить договор или вынести в отдельный блок
- Сделать счета учёта опциональными
Этап 4: Тестирование (1 день)
- Тестовый импорт в реальную 1С клиента
- Проверка контрольных сумм
- Проверка НДС
- Сопоставление с УПД/счетами-фактурами
Скептическая оценка анализа ИИ
✅ Что верно на 100%:
- Потеря копеек - КРИТИЧНО, будет ошибка в суммах
- GUID справочников - КРИТИЧНО, не будет работать в другой базе
- ВидЭД - верно, этого поля нет в ED
- Заглушки дат - верно, риск искажения данных
⚠️ Что нужно проверить:
- Структура валюты - зависит от версии XSD (нужен реальный XSD)
- Банк/счёт - вероятно верно, но нужна проверка по документации
- Договор - может быть по-разному в разных версиях 1С
- Счета учёта - зависит от конфигурации 1С клиента
📋 Что точно нужно сделать:
- Получить от клиента XSD EnterpriseData 1.20 их версии
- Протестировать импорт в реальной базе
- Исправить копейки и ВидЭД (это точно ошибки)
- Остальное - после проверки по реальной схеме
Вывод
Генератор работоспособен, но имеет критичные проблемы для продакшена:
- ✅ Структура документа в целом корректна
- ❌ Денежные суммы теряют копейки
- ⚠️ Жёсткие GUID не будут работать в чужой базе
- ⚠️ Структура может не совпадать с XSD клиента
Рекомендация:
- Срочно исправить копейки и убрать ВидЭД
- Получить XSD от клиента
- Протестировать в реальной базе
- Доработать под реальную схему
Риск: Без тестирования в реальной 1С клиента есть высокая вероятность ошибок импорта.