Во время обновления Бухгалтерии 3.0 КОРП с 3.0.40.24 до 3.0.43.155 неожиданно выяснилось, что перенести старый функционал поиска контрагента и договора не представляется возможным. Доработка заключалась в поиске в назначении платежа номера счета на оплату или номера договора с последующим заполнением соответствующих реквизитов обработки.
Долго ли, коротко ли, было найдено место в процедуре общего модуля ЗагрузкаВыпискиПоБанковскомуСчету.ЗаполнитьИдентификаторыУчастниковОперацийПоДаннымИзБанка
// Здесь же может быть описано получение идентификаторов по другим данным.
// Например, получателя можно идентифицировать по номеру карты, указанному в назначении платежа,
// номеру счета физ. лица, указанному в наименовании или назначении платежа и другим признакам.
После этих воодушевляющих слов можно вставить описание своего идентификатора. Передача параметра о том, что надо использовать новую схему поиска, из обработки в общий модуль не столь увлекательна и поэтому будет опущена.
Если Сторона = "Плательщик" И УчастникиОпераций.ИспользоватьПоискКлиентаПоНазначениюПлатежа Тогда
Позиция = СтрНайти(Документ.НазначениеПлатежа, "ЪЪ"); // интеллектуальный поиск
Если Позиция > 0 Тогда
НомерСчетаНаОплату = Врег(Сред(Документ.НазначениеПлатежа, Позиция, 9));
Идентификатор = ИдентификацияУчастниковБанковскихОпераций.ИдентификаторПоНомеруСчетаНаОплатуИлиДоговору(УчастникиОпераций, НомерСчетаНаОплату);
Если Идентификатор <> Неопределено Тогда
ИдентификаторыУчастника.Добавить(Идентификатор);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Схема — это упрощенно некий входящий параметр-идентификатор и процедура с запросом, в котором будет осуществлен поиск ссылки по этому идентификатору. Сначала добавляем идентификатор, потом выполняется поиск. Точка входа — функция ЗагрузкаВыпискиПоБанковскомуСчету.РаспознанныеДанныеИзБанка, в ней выполняется добавление идентификатора (вышеприведенная процедура) и поиск объекта ИБ по этому идентифкатору (об этом ниже).
Моя схема будет называться INSR, потому что речь идет о страховом брокере и поиске клиентов, оплачивающих страховые премии через банки. Счета на оплату подгружаются в бухгалтерию из внешней системы. Функция подготовки идентификатора по аналогии с другими схемами вынесена в общий модуль ИдентификацияУчастниковБанковскихОпераций
Функция ИдентификаторПоНомеруСчетаНаОплатуИлиДоговору(УчастникиОпераций, Номер) Экспорт
Состав = Новый Структура;
Состав.Вставить("Номер", Номер);
Точный = Истина;
БазовыйИдентификатор = "";
Возврат УстановитьИдентификатор(УчастникиОпераций, "INSR", Номер, Состав, Точный, БазовыйИдентификатор);
КонецФункции
Замечу, что это упрощенный вариант поиска. В рабочем варианте выполняется также поиск договоров, и идентификатор может быть также номером договора. Соответственно, чтобы различать какой это номер — договора или счета на оплату — нужен некий флаг, который надо добавить в Состав.
А теперь то, что надо сделать, чтобы сработал поиск по новому идентификатору в общем модуле ИдентификацияУчастниковБанковскихОпераций
Функция СхемыИдентифицирующиеТип(Тип)
// Схемы упорядочены по убыванию надежности для каждого типа данных.
// Так, если известны TXID и BBAN, при этом по TXID найден один контрагент, а по BBAN - другой, то следует предпочесть первого.
Схемы = Новый Массив;
Схемы.Добавить("UUID"); // позволяет идентифицировать любой тип
Если Тип = Тип("СправочникСсылка.Организации") Тогда
Схемы.Добавить("TXID");
Схемы.Добавить("BBAN");
ИначеЕсли Тип = Тип("СправочникСсылка.Контрагенты") Или Тип = Тип("СправочникСсылка.ДоговорыКонтрагентов") Тогда
Схемы.Добавить("INSR"); // ВСТАВЛЯЕМ СХЕМУ ПЕРВОЙ, СЧИТАЕМ ЕЕ САМОЙ ЛУЧШЕЙ
Схемы.Добавить("TXID");
Схемы.Добавить("TXZN");
Схемы.Добавить("IBAN");
Схемы.Добавить("BBAN");// см. СхемаПрименяетсяОграниченно()
Схемы.Добавить("BKNM");
ИначеЕсли Тип = Тип("СправочникСсылка.БанковскиеСчета") Тогда
Схемы.Добавить("BBAN");
Схемы.Добавить("IBAN");
ИначеЕсли Тип = Тип("СправочникСсылка.ФизическиеЛица") Тогда
Схемы.Добавить("TXID");
Схемы.Добавить("BBAN");// см. СхемаПрименяетсяОграниченно()
Схемы.Добавить("IBAN");
КонецЕсли;
Возврат Схемы;
КонецФункции
Важно вставить схему первой в списке (на самом деле она будет второй, но схема UUID я не заметил чтобы использовалась). В противном случае сработает, например, TXID и вместо нашего клиента мы получим банк, через который он платил. В свою очередь для клиента-физлица должна использоваться также схема поиска по наименованию (ИНН и адресу) PNNM, которой вообще нет в списке, то есть она или не используется (?), или в моей выписке в наименовании плательщика не было ИНН, что нынешний типовой алгоритм не учитывает.
В функции ОписаниеИдентификатораПоСхеме вставим отметку о своей схеме в конец оператора Если (я даже уже забыл, зачем именно это место надо править, но точно надо).
...
ИначеЕсли Схема = "INSR" Тогда
Идентификатор = ИдентификаторПоНомеруСчетаНаОплатуИлиДоговору(УчастникиОпераций, СведенияОбОбъектеИнформационнойБазы.Номер);
Иначе
...
Добавляем свою схему в общий список схем
Функция ОписаниеМетодовПоиска()
МетодыПоиска = Новый Массив;
МетодыПоиска.Добавить(ОписаниеМетодаПоискаBBAN());
МетодыПоиска.Добавить(ОписаниеМетодаПоискаIBAN());
МетодыПоиска.Добавить(ОписаниеМетодаПоискаTXID());
МетодыПоиска.Добавить(ОписаниеМетодаПоискаBKNM());
МетодыПоиска.Добавить(ОписаниеМетодаПоискаTXZN());
МетодыПоиска.Добавить(ОписаниеМетодаПоискаINSR()); // здесь порядок непринципиален
Возврат МетодыПоиска;
КонецФункции
Собственно само описание метода поиска. Оригинальный запрос поиска усечен в академических целях.
Функция ОписаниеМетодаПоискаINSR()
МетодПоиска = НовыйОписаниеМетодаПоиска("INSR");
МетодПоиска.ПоляПоискаЗапросом.Вставить("Номер", ОбщегоНазначения.ОписаниеТипаСтрока(100));
МетодПоиска.ТекстЗапросаСсылок =
"ВЫБРАТЬ
| ЗначенияПоискаЗапросом.Идентификатор КАК Идентификатор,
| ЗначенияПоискаЗапросом.Номер КАК Номер
|ПОМЕСТИТЬ ЗначенияПоискаЗапросом
|ИЗ
| &ЗначенияПоискаЗапросом КАК ЗначенияПоискаЗапросом
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ РАЗРЕШЕННЫЕ
| ПараметрыПоиска.Идентификатор КАК Идентификатор,
| ПараметрыПоиска.Номер КАК Номер,
| ТИПЗНАЧЕНИЯ(СчетаНаОплату.ДоговорКонтрагента) КАК Тип,
| СчетаНаОплату.ДоговорКонтрагента КАК Ссылка,
| ТИПЗНАЧЕНИЯ(СчетаНаОплату.Контрагент) КАК ТипВладельца,
| СчетаНаОплату.Контрагент КАК Владелец,
| СчетаНаОплату.Контрагент.ПометкаУдаления КАК ПометкаУдаления,
| СчетаНаОплату.Контрагент.ЮридическоеФизическоеЛицо КАК ЮридическоеФизическоеЛицо,
| СчетаНаОплату.Контрагент.ГосударственныйОрган КАК ГосударственныйОрган,
| СчетаНаОплату.Контрагент.ВидГосударственногоОргана КАК ВидГосударственногоОргана,
| СчетаНаОплату.ДоговорКонтрагента.ВидДоговора КАК ВидДоговора,
| СчетаНаОплату.ДоговорКонтрагента.Организация КАК Организация
|ИЗ
| ЗначенияПоискаЗапросом КАК ПараметрыПоиска
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.СчетНаОплатуПокупателю КАК СчетаНаОплату
| ПО ПараметрыПоиска.Номер = СчетаНаОплату.Номер
|
|ИТОГИ ПО
| Идентификатор,
| ТипВладельца,
| Тип";
Возврат МетодПоиска;
КонецФункции
Разницы между полями Ссылка и Владелец я не увидел: совершенно без разницы, куда Вы поместите Контрагента, а куда Договор. А вот реквзиты контрагента важны, т.к. далее к ним есть обращения. Ссылка и Владелец добавляются в список ссылок — каждый для своего типа объектов — с указанием схемы, по которой был произведен поиск.
И последнее действие, которое надо сделать, связано с особенностью алгоритма подбора договоров при добавлении ссылки на контрагента. В процедуре НайтиВИнформационнойБазе, которая запускает схемы поиска и аккумулирует найденные ссылки, в конце вызывается процедура НайтиДоговорыКонтрагентовВИнформационнойБазе, которая ничтоже сумняшеся добавляет в доступные для выбора ссылки все договора контрагента. Нам такого не надо, поэтому в первом же цикле надо установить отсечку
Если ОписаниеИдентификатора.Схема = "INSR" Тогда
Продолжить;
КонецЕсли;
Т.к. наша схема первая в списке поиска, предполагается, что договор и контрагента мы нашли, то в Клиент-банке мы увидим именно их. Если же не выполнить последнее действие, то договор будет последним при сортировке «по ссылке». И это необязательно договор из счета на оплату.
За рамками статьи осталась такая вещь, как Мера соответствия идентификатора, но т.к. моя схема точная, я этим не стал озадачиваться.
UPD Обнаружено, что в запросе поиска объектов функции ОписаниеМетодаПоискаINSR надо добавить поле УстановленОсновным равное Истина, вне зависимости от того является договор основным или нет. Этого требует функция ЗагрузкаВыпискиПоБанковскомуСчету.НайтиДоговорПоВидуОперации. См. также функцию ИдентификацияУчастниковБанковскихОпераций.СведенияОбОбъектеИнформационнойБазы на предмет списка полей выборки запроса поиска объектов.
Помогло допилить поиск под свои нужны. Thanks!
Я пошел другим путем. После распознавания выписки типовым механизмом, делаю распознавание уже своим алгоритмом, одновременно модифицируя распознанные данные, которые хранятся в хранилище значений. Обновлять — накатывать релизы легче.
(2)
уже не помню, почему так сделал, а не постобработкой. я статью написал, чтобы у прочитавших была возможность выбрать как действовать.
здесь где-то есть клиент-банк, который работает по пути постобработки, но он, кажется, для 2.0, так что не стесняйтесь, выкладывайте.
Автор, а подскажи пожалуйста по поводу признака платежа от физ.лица или юр.лица. Как их различить? Свои мысли?
На данный момент я использую:
— TXID — юр.лицо + ИП;
— PNNM — физ.
Может быть есть более надежный способ?
(4)
Не могу прокомментировать. К счастью или сожалению, я к этой теме с тех времен не возвращался. Многое могло измениться. Помню, что заполнение полей платежки разнится от банка к банку. В моем случае проблема была в том, что в качестве контрагента в платежке указывался сам банк.