Однажды в наш отдел прилетела задача: наладить ЭДО с ПАО "Татнефть" с минимумом вложений по соглашению ЭДО, предусматривающему обязательное заполнение доп полей в счетах-фактурах и товарных накладных (номер договора, код подразделения получателя, ГУИД документа и т.д.).
Задача достаточно простая, но есть несколько нюансов, на которые стоит обратить внимание, чтобы не терять понапрасну время.
Далее написано для УПП 1.3.106.1 и платформы 8.2.19.130
Решение:
- Подключить 1С-Такском - система ЭДО, встроенная в большинство типовых конфигураций 1С 8, обратившись к обслуживающему партнеру. Буквально в течение часа специалист франчайзи подключил услугу, настроил ключи ЭЦП, форматы отправки, послал приглашения контрагенту. Бесплатно 100 документов в месяц при подписке ИТС Проф. Подробности на оф сайте https://portal.1c.ru/applications/8.
- Обязательно проверьте правильность заполнения данных в справочнике "Контрагенты", "Договоры контрагентов"
- Обновите КЛАДР, справочник банков (Устаревшее название банка в торг - отказ)
- Контактная информация должна быть заполнена и заполнена по классификатору адресов (российский адрес был заполнен как зарубежный - неизвестный код страны - отказ)
- У контрагента должен быть заведен банковский счет и он должен быть помечен как "Основной" (банковские реквизиты не попадали в торг-12 без пометки счета "Основным" - отказ)
- Суть обмена - создается файл xml, подписывается и средствами оператора ЭДО передается контрагенту, который его подписывает и тем принимает к учету.
В УПП этот файл создается как:- в процедуре СформироватьХМЛФайл общего модуля ЭлектронныеДокументыСлужебный определяется по ключу функция, для каждого вида электронного документа своя. Нас интересуют
- для ТОРГ-12 (формат 551 приказа ФНС) - ЭлектронныеДокументыВнутренний.СформироватьПередачаТоваровПродавец
- для счета-фактуры - ЭлектронныеДокументыВнутренний.СформироватьИнформациюПродавца
- В этих функциях происходит заполнение ДереваЗначений данными документа-источника и вызов одноименной функции с добавлением xml (ЭлектронныеДокументыВнутренний.СформироватьПередачаТоваровПродавецXML и т.д.), которая уже и формирует сам xml файл на основе переданного дерева значений.
- в процедуре СформироватьХМЛФайл общего модуля ЭлектронныеДокументыСлужебный определяется по ключу функция, для каждого вида электронного документа своя. Нас интересуют
- Таким образом нам остается только перед вызовом функции СформироватьПередачаТоваровПродавецXML дополнить ДеревоЗначений своими реквизитами. Все заполняемые доп. поля должны быть проверены на непустое значение (проблемы при отправке - несоответствие формату ФНС)
- Для ТОРГ-12 узел дерева называется "ДопДанные.Подписанные" и новые строки в него добавляются функцией ДобавитьЗначениеВДерево или ВставитьЗначениеВДерево. Отличия в том, что ВставитьЗначениеВДерево проверяет наличие узла дерева по имени и меняет его значение, если найдено, если не найдено - создает новый узел, а ДобавитьЗначениеВДерево без проверок добавляет новый узел в дерево.
- Для счета-фактуры - "ДопДанныеСчетаФактуры.ТекстоваяИнформация" и узлы добавляются функцией ОбщегоНазначенияЭД.ДобавитьЗаписьВТаблицуДерева.
В качестве примера привожу код по заполнению дополнительных полей, обязательных при ЭДО с ПАО "Татнефть им. Шашина Д.В.". Здесь доп поля используются для автоматических процессов согласования и доставки документа до адресата (http://1c-edo.ru/reviews/2601/). Передаются номер договора, дата договора, код подразделения (храним в свойствах контрагента), уникальный идентификатор документа -он используется для связи счета-фактуры и ТОРГ-12 и должен совпадать для одного комплекта документов.
Процедура ДобавитьДопПоляВТОРГ12Татнефть(СтрокаДерева, СсылкаНаОбъект) Экспорт; Если Не (СсылкаНаОбъект.Контрагент = ygЗначенияНепредопределенныхОбъектов.ПолучитьЗначениеПоИдентификатору("КонтрагентТатнефть")) Тогда Возврат; КонецЕсли; Попытка //Обязательные доп поля Номер_Договора = Лев(СсылкаНаОбъект.ДоговорКонтрагента.Номер, 200); Дата_Договора = Лев(Формат(СсылкаНаОбъект.ДоговорКонтрагента.Дата, "ДФ=dd.MM.yyyy"), 200); ИдентификаторСвойстваПодразделениеПолучателя = ygЗначенияНепредопределенныхОбъектов.ПолучитьЗначениеПоИдентификатору("ТатнефтьСвойствоПодразделение"); Подразделение_получатель = YgМодульПривилегированный.ПолучитьЗначениеСвойстваОбъекта(СсылкаНаОбъект.Грузополучатель, ИдентификаторСвойстваПодразделениеПолучателя); ИдентификаторДокументаОснования = Строка(СсылкаНаОбъект.УникальныйИдентификатор()); Исключение Сообщить("Обратись в ОИТ"); Сообщить(ОписаниеОшибки()); КонецПопытки; Если НЕ ЗначениеЗаполнено(Номер_Договора) Тогда ВызватьИсключение "Не заполнен номер договора в документе "; КонецЕсли; Если НЕ ЗначениеЗаполнено(Дата_Договора) Тогда ВызватьИсключение "Не заполнена дата договора в документе "; КонецЕсли; Если НЕ ЗначениеЗаполнено(Подразделение_получатель) Тогда ВызватьИсключение "Не заполнен код структурного подразделения Татнефти"; КонецЕсли; ДобавитьЗначениеВДерево(СтрокаДерева, "ДопДанные.Подписанные.Номер_договора", Номер_Договора); ДобавитьЗначениеВДерево(СтрокаДерева, "ДопДанные.Подписанные.Дата_договора", Дата_Договора); ДобавитьЗначениеВДерево(СтрокаДерева, "ДопДанные.Подписанные.Подразделение_получатель", Подразделение_получатель); ВставитьЗначениеВДерево(СтрокаДерева, "ДопДанные.Подписанные.ИдентификаторДокументаОснования", ИдентификаторДокументаОснования) КонецПроцедуры Процедура ДобавитьЗначениеВДерево(ДеревоДанных, ИмяРеквизита, ЗначениеРеквизита) НовСтрока = ДеревоДанных.Строки.Добавить(); НомерУровня = СтрЧислоВхождений(ИмяРеквизита, ".") + 1; НовСтрока.ПолныйПуть = ИмяРеквизита; НовСтрока["Уровень" + НомерУровня] = ОбщегоНазначенияЭД.НазваниеКолонки(ИмяРеквизита); НовСтрока.Значение = ЗначениеРеквизита; КонецПроцедуры Процедура ВставитьЗначениеВДерево(ДеревоДанных, ИмяРеквизита, ЗначениеРеквизита) НовСтрока = ДеревоДанных.Строки.Найти(ИмяРеквизита, "ПолныйПуть", Истина); Если НовСтрока = Неопределено Тогда НовСтрока = ДеревоДанных.Строки.Добавить(); НомерУровня = СтрЧислоВхождений(ИмяРеквизита, ".") + 1; НовСтрока.ПолныйПуть = ИмяРеквизита; НовСтрока["Уровень" + НомерУровня] = ОбщегоНазначенияЭД.НазваниеКолонки(ИмяРеквизита); КонецЕсли; НовСтрока.Значение = ЗначениеРеквизита; КонецПроцедуры Процедура ДобавитьДопПоляВСЧФТатнефть(ДеревоДанных, ТекстоваяИнформация, СсылкаНаОбъект) Экспорт; Если Не (СсылкаНаОбъект.Контрагент = ygЗначенияНепредопределенныхОбъектов.ПолучитьЗначениеПоИдентификатору("КонтрагентТатнефть")) Тогда Возврат; КонецЕсли; Попытка //Обязательные доп поля Номер_Договора = Лев(СсылкаНаОбъект.ДоговорКонтрагента.Номер, 200); Дата_Договора = Лев(Формат(СсылкаНаОбъект.ДоговорКонтрагента.Дата, "ДФ=dd.MM.yyyy"), 200); ИдентификаторСвойстваПодразделениеПолучателя = ygЗначенияНепредопределенныхОбъектов.ПолучитьЗначениеПоИдентификатору("ТатнефтьСвойствоПодразделение"); Подразделение_получатель = YgМодульПривилегированный.ПолучитьЗначениеСвойстваОбъекта(СсылкаНаОбъект.ДокументОснование.Грузополучатель, ИдентификаторСвойстваПодразделениеПолучателя); ДокументОснование = СсылкаНаОбъект.ДокументыОснования[0].ДокументОснование; ИдентификаторДокументаОснованияСчф = Строка(ДокументОснование.УникальныйИдентификатор()); Исключение Сообщить("Обратись в ОИТ"); Сообщить(ОписаниеОшибки()); ВызватьИсключение "Fatal error"; КонецПопытки; Если НЕ ЗначениеЗаполнено(Номер_Договора) Тогда ВызватьИсключение "Не заполнен номер договора в документе "; КонецЕсли; Если НЕ ЗначениеЗаполнено(Дата_Договора) Тогда ВызватьИсключение "Не заполнена дата договора в документе "; КонецЕсли; Если НЕ ЗначениеЗаполнено(Подразделение_получатель) Тогда ВызватьИсключение "Не заполнен код структурного подразделения Татнефти"; КонецЕсли; Если НЕ ЗначениеЗаполнено(ИдентификаторДокументаОснованияСчф) Тогда ВызватьИсключение "Не существующий документ"; КонецЕсли; НоваяСтрока = ТекстоваяИнформация.Добавить(); НоваяСтрока.Идентификатор = "Номер_договора"; НоваяСтрока.Значение = Номер_Договора; ОбщегоНазначенияЭД.ДобавитьЗаписьВТаблицуДерева(ДеревоДанных, НоваяСтрока, "ДопДанныеСчетаФактуры.ТекстоваяИнформация"); НоваяСтрока = ТекстоваяИнформация.Добавить(); НоваяСтрока.Идентификатор = "Дата_договора"; НоваяСтрока.Значение = Дата_Договора; ОбщегоНазначенияЭД.ДобавитьЗаписьВТаблицуДерева(ДеревоДанных, НоваяСтрока, "ДопДанныеСчетаФактуры.ТекстоваяИнформация"); НоваяСтрока = ТекстоваяИнформация.Добавить(); НоваяСтрока.Идентификатор = "ИдентификаторДокументаОснования"; НоваяСтрока.Значение = ИдентификаторДокументаОснованияСчф; ОбщегоНазначенияЭД.ДобавитьЗаписьВТаблицуДерева(ДеревоДанных, НоваяСтрока, "ДопДанныеСчетаФактуры.ТекстоваяИнформация"); НоваяСтрока = ТекстоваяИнформация.Добавить(); НоваяСтрока.Идентификатор = "Подразделение_получатель"; НоваяСтрока.Значение = Подразделение_получатель; ОбщегоНазначенияЭД.ДобавитьЗаписьВТаблицуДерева(ДеревоДанных, НоваяСтрока, "ДопДанныеСчетаФактуры.ТекстоваяИнформация"); КонецПроцедуры
Вызываем соответствующие процедуры в функциях прямо перед формированием xml файла
- В функции ЭлектронныеДокументыВнутренний.СформироватьПередачаТоваровПродавец
//............................................ //Мы заполняем доп поля mokЭДОТатнефть.ДобавитьДопПоляВТОРГ12Татнефть(СтрокаДопДанных, СсылкаНаОбъект); //Здесь формируется файл xml Если СформироватьПередачаТоваровПродавецCML(ДеревоДанных) И ПризнакЭД Тогда .......
- В функции ЭлектронныеДокументыВнутренний.СформироватьИнформациюПродавца
//............................................ ..... //Перед формированием файла добавляем свои доп поля mokЭДОТатнефть.ДобавитьДопПоляВСЧФТатнефть(ДеревоДанных, ТекстоваяИнформация, СсылкаНаОбъект); //Тут на основе ДеревоДанных формируется xml РезультатФормирования = СформироватьИнформациюПродавцаXML(ДеревоДанных); .......
UPD 17.04.2019
-
В УПП, начиная с версии 1.3.117.1 внесены изменения в модуль ЭлектронныеДокументыВнутренний
Теперь для заполнения доп полей в Счет-фактуре нужно внести изменения в процедуры
СформироватьИнформациюПродавца_5_01 и СформироватьИнформациюПродавца_2019