1С регистр сведений основной отбор по периоду

Содержание

К слову, в БСП 2.3 уже реализован универсальный обмен данными через Веб-сервис, но для его внедрения необходимо включение в конфигурацию всех сопутствующих подсистем БСП, что не всегда представляется возможным. Особенно, если текущая конфигурация на обычных формах (БСП 2.3 ориентировано на управляемые формы).

В представленных алгоритмах были проработаны следующие вопросы:

1. Запуск синхронизации производится в реальном режиме времени при записи (удалении) объекта (документа, справочника), но только если запись выполняется интерактивно. То есть, при пакетном перепроведении документов при восстановлении последовательности или из обработки «Групповая обработка справочников и документов» синхронизация не требуется (предполагается, что движения документов не переносятся, а формируются при проведении).

2. Предусмотрен механизм гарантированной доставки данных в базу приемник. Для этих целей, при запуске синхронизации, объект предварительно регистрируется в плане обмена. В случае сбоя синхронизации по ежеминутному регламентному заданию выполняется проверка наличия зарегистрированных объектов в плане обмена и производится повторная попытка передачи данных в базу приемник. Далее, в случае успешности передачи данных, регистрация объекта в плане обмена удаляется.

3. Для исключения задержек при записи объектов, синхронизация запускается асинхронно в фоновом задании. Если же требуется организовать отказ от проведения документа в текущей базе в зависимости от успешности проведения этого документа в базе приемнике, имеется возможность предусмотреть запуск синхронизации в основном потоке (по опыту, документ реализация товаров в УПП имеющий в табличной части до 10 строчек синхронизируется за 1-2 сек), в этом случае производится ожидание завершения синхронизации и в зависимости от успешности проведения выставляется отказ и дублируется сообщение о причине неуспешности, переданное из базы приемника.

4. Для универсальности данные передаются в базу приемник в формате XML, сформированными программно с помощью обработки «Универсальный обмен данными XML» по правилам обмена, подготовленными в конфигурации «Конвертация данных». Соответственно, на стороне приемника производится загрузка этой же обработкой. Как правило, во всех типовых конфигурациях данная обработка присутствует, а для самописных можно загрузить из состава .cf данной публикации.

5. Пакет передаваемых данных должен иметь минимальный объем данных, Чтобы не загружать сетевые службы и Веб-сервер. Для этих целей, предусмотрено:

— за один раз производится выгрузка только одного объекта (с подчиненными объектами, выгруженными по ссылкам, если это справочник);

— при разработке правил обмена для всех документов устанавливается режим «Не выгружать объекты свойств источника по ссылкам». В этом случае исключается избыточность передаваемых данных. Если же в реквизите встречается ссылка на элемент объекта, который не включен в состав регистрируемых объектов плана обмена (то есть данный вид объектов самостоятельно не синхронизируется) и эта ссылка не была найдена в базе приемнике (в терминах обработки это фиктивная ссылка), то формируется список фиктивных ссылок, который возвращается в базу источник и рекурсивно инициируется синхронизация для этих объектов.

6. Как следствие из предыдущего пункта, проведение документа в базе приемнике реализовано отдельным запросом после полной передачи всего пакета вместе с рекурсивной синхронизацией фиктивных ссылок по предыдущему пункту. Так как для документов отключена выгрузка объектов свойств источника по ссылкам, то на момент первичной записи документа в нем могут присутствовать фиктивные ссылки, из за которых нормальное проведение документа в этот момент невозможно.

Реализация

1. Для всех синхронизируемых объектов в форме элемента справочника (форме документа) в обработчике «При открытии» необходимо добавить следующий код: Процедура ПриОткрытии() ДополнительныеСвойства.Вставить(«СинхронизироватьПриЗаписи»); КонецПроцедуры 2. Добавляем подписки на события

3. Общий модуль «ЛУ_СинхронизацияКлиентСервер» (Сервер, Клиент Обычное приложение) — обработчики подписок Процедура ОбъектПриЗаписиСинхронизировать(Источник, Отказ) Экспорт ПланОбменаРегистрацияИзменений(ПланыОбмена.ЛУ_WebСервис, Источник, Отказ); КонецПроцедуры Процедура ОбъектПередУдалениемСинхронизировать(Источник, Отказ) Экспорт ПланОбменаРегистрацияИзменений(ПланыОбмена.ЛУ_WebСервис, Источник, Отказ, Истина); КонецПроцедуры Процедура ПланОбменаРегистрацияИзменений(ПланОбмена, Источник, Отказ, Удаление=Ложь) Экспорт #Если НЕ ТолстыйКлиентОбычноеПриложение Тогда Возврат; #КонецЕсли Если Отказ или Источник.ОбменДанными.Загрузка Тогда Возврат; КонецЕсли; Если НЕ (Источник.ДополнительныеСвойства.Свойство(«СинхронизироватьПриЗаписи») или Удаление) Тогда Возврат; КонецЕсли; ПланОбменаМетаданные = ПланОбмена.ПустаяСсылка().Метаданные(); Если НЕ ПланОбменаМетаданные.Состав.Содержит(Источник.Метаданные()) Тогда Возврат; КонецЕсли; // Регистрация изменениий в плане обмена ВыборкаУзлов = ПланОбмена.Выбрать(); Пока ВыборкаУзлов.Следующий() Цикл ТекущийУзел = ВыборкаУзлов.Ссылка; Если ТекущийУзел = ПланОбмена.ЭтотУзел() Тогда Продолжить; КонецЕсли; Если НЕ ТекущийУзел.Синхронизировать Тогда Продолжить; КонецЕсли; ОбъектРегистрации = ?(Удаление, Новый УдалениеОбъекта(Источник.Ссылка), Источник.Ссылка); ПланыОбмена.ЗарегистрироватьИзменения(ТекущийУзел, ОбъектРегистрации); КонецЦикла; ЛУ_СинхронизацияВызовСервера.ПланОбменаСинхронизироватьАсинхронно(ПланОбменаМетаданные.Имя); КонецПроцедуры 4. План обмена ЛУ_WebСервис

Здесь:

  • Синхронизировать — булево,
  • Сервер, База, Пользователь, Пароль — Строка, 100, переменная
  • ПравилаКонвертации — ХранилищеЗначения (в форме узла реализована загрузка в этот реквизит правил обмена из файла XML)

5. Общий модуль «ЛУ_СинхронизацияВызовСервера» (Сервер, Вызов сервера) (для наглядности из листингов исключены все конструкции связанные с обработкой исключений, вывода ошибок, и вспомогательные методы) Процедура ПланОбменаСинхронизировать(ИмяПланаОбмена) Экспорт ПланОбмена = ПланыОбмена; ВыборкаУзлов = ПланОбмена.Выбрать(); Пока ВыборкаУзлов.Следующий() Цикл ТекущийУзел = ВыборкаУзлов.Ссылка; Если ТекущийУзел = ПланОбмена.ЭтотУзел() Тогда Продолжить; КонецЕсли; Если НЕ ТекущийУзел.Синхронизировать Тогда Продолжить; КонецЕсли; ИмяСобытияДляЖурнала = «ПланОбмена.» + ИмяПланаОбмена + » » + ПланОбмена.ЭтотУзел().Код + » -> » + ТекущийУзел.Код; ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения(); ЗаписьСообщенияXML = Новый ЗаписьXML; ЗаписьСообщенияXML.УстановитьСтроку(); Попытка ЗаписьСообщения.НачатьЗапись(ЗаписьСообщенияXML, ТекущийУзел); Исключение // ТекущийУзел заблокирован, пока пропустим, следующая попытка будет по регламентному заданию через 60 сек Продолжить; КонецПопытки; НомерСообщения = ЗаписьСообщения.НомерСообщения; МетаданныеДокументы = Метаданные.Документы; МассивУдаляемыхОбъектов = Новый Массив; МассивОбъектов = Новый Массив; Выборка = ПланыОбмена.ВыбратьИзменения(ТекущийУзел, НомерСообщения); Пока Выборка.Следующий() Цикл // В этом цикле только подготовим массив объектов, содержащихся в сообщении плана обмена // Чтобы побыстрее освободить ЗаписьСообщения // (до вызова метода ЗакончитьЗапись() в плане обмена устанавливается исключительная блокировка) Объект = Выборка.Получить(); Если ТипЗнч(Объект) = Тип(«УдалениеОбъекта») Тогда МассивУдаляемыхОбъектов.Добавить(Объект); ИначеЕсли НЕ МетаданныеДокументы.Содержит(Объект.Ссылка.Метаданные()) Тогда МассивОбъектов.Вставить(0, Объект.Ссылка); // Документы сдвигаем в конец массива Иначе МассивОбъектов.Добавить(Объект.Ссылка); КонецЕсли; КонецЦикла; Если МассивОбъектов.Количество() = 0 и МассивУдаляемыхОбъектов.Количество() = 0 Тогда ЗаписьСообщения.ПрерватьЗапись(); // Освобождаем номер сообщения плана обмена Продолжить; КонецЕсли; ЗаписьСообщения.ЗакончитьЗапись(); // Фиксируем исходящее сообщение плана обмена данных // Полученный XML сообщения игнорируем. // Так как в базе приемнике фиксация номеров входящих сообщений плана обмена не предусмотрена // (В приемнике вообще может не быть корреспондирующего плана обмена при одностороннем обмене). ЗаписьСообщенияXML.Закрыть(); // Передача измененных объектов в базу приемник Отказ = Ложь; ОбработкаОбмена = ИнициализироватьОбработкуОбмена(ТекущийУзел, ИмяСобытияДляЖурнала, Отказ); ФайлОбмена = Новый Файл(ОбработкаОбмена.ИмяФайлаОбмена); // Подключение LuExchange = ПолучитьWSПрокси(ТекущийУзел, «LuExchange.1cws», «http://www.LuExchange.ru», «LuExchange»); // Удаляемые объекты // Поиск удаляемого объекта выполняется только по ссылке ВыгрузитьУдаляемыеОбъектыВБазуПриемник(ТекущийУзел, МассивУдаляемыхОбъектов, LuExchange, ОбработкаОбмена, ФайлОбмена, ИмяСобытияДляЖурнала, Отказ); // Измененные объекты Для каждого ОбъектСсылка Из МассивОбъектов Цикл ОшибкаВыгрузкиОбъекта = Ложь; СтрокаЗагруженныеДокументы = «»; // Массив загруженных документов в базе приемнике (строка внутренняя) для инициации последующего проведения ВыгрузитьОбъектВБазуПриемник(ОбъектСсылка, LuExchange, ОбработкаОбмена, ФайлОбмена, ИмяСобытияДляЖурнала, СтрокаЗагруженныеДокументы, ОшибкаВыгрузкиОбъекта); Если ОшибкаВыгрузкиОбъекта Тогда Отказ = Истина; Продолжить; КонецЕсли; // Для выгруженных документов необходимо выполнить команду проведения или, если документ был распроведен, удалить движения ОшибкаПроведенияДокумента = Ложь; ОбработкаПризнакаПроведенияДокумента(СтрокаЗагруженныеДокументы, LuExchange, ИмяСобытияДляЖурнала, ОшибкаПроведенияДокумента); // Фиксируем успешную синхронизацию в плане обмена для объекта ПланыОбмена.УдалитьРегистрациюИзменений(ТекущийУзел, ОбъектСсылка); КонецЦикла; УдалитьФайлы(ОбработкаОбмена.ИмяФайлаОбмена); Если НЕ Отказ Тогда // Фиксируем успешную синхронизацию в плане обмена для всего сообщения ПланыОбмена.УдалитьРегистрациюИзменений(ТекущийУзел, НомерСообщения); КонецЕсли; КонецЦикла; КонецПроцедуры Процедура ВыгрузитьОбъектВБазуПриемник(ОбъектСсылка, LuExchange, ОбработкаОбмена, ФайлОбмена, ИмяСобытияДляЖурнала, СтрокаЗагруженныеДокументы=»», Отказ) // Получаем ДанныеXML ВыгруженоОбъектов = 0; ДанныеXML = ПолучитьДанныеXMLПоПравиламКонвертации(ОбработкаОбмена, ОбъектСсылка, ВыгруженоОбъектов, ИмяСобытияДляЖурнала); // ExecuteExchange ТекстОшибки = «»; ОшибкаВыгрузки = Ложь; СтрокаФиктивныеСсылки = «»; Данные = Новый ХранилищеЗначения(ДанныеXML, Новый СжатиеДанных(9)); ЗагруженоОбъектов = LuExchange.ExecuteExchange(Данные, ИмяСобытияДляЖурнала, СтрокаФиктивныеСсылки, СтрокаЗагруженныеДокументы, ТекстОшибки); // Фиктивные ссылки (выгружаем объекты по ссылкам) ОбработкаФиктивныхСсылок(СтрокаФиктивныеСсылки, LuExchange, ОбработкаОбмена, ФайлОбмена, ИмяСобытияДляЖурнала, ОшибкаВыгрузки); КонецПроцедуры Процедура ОбработкаФиктивныхСсылок(СтрокаФиктивныеСсылки, LuExchange, ОбработкаОбмена, ФайлОбмена, ИмяСобытияДляЖурнала, Отказ) Если ПустаяСтрока(СтрокаФиктивныеСсылки) Тогда Возврат; КонецЕсли; ФиктивныеСсылки = ЗначениеИзСтрокиВнутр(СтрокаФиктивныеСсылки); Для каждого ФиктивнаяСсылка Из ФиктивныеСсылки Цикл ФиктивнаяСсылка = СтрЗаменить(ФиктивнаяСсылка, «.», Символы.ПС); ВидПриемника = СтрПолучитьСтроку(ФиктивнаяСсылка, 1); ТипПриемника = СтрПолучитьСтроку(ФиктивнаяСсылка, 2); УИД = СтрПолучитьСтроку(ФиктивнаяСсылка, 3); // Здесь тип объекта соответствует метаданным базы приемника, // для обработки необходимо привести к соответствующему типу текущей базы // Найдем корреспондирующий тип по правилам обмена ПравилоКонвертации = ОбработкаОбмена.ТаблицаПравилКонвертации.Найти(ВидПриемника+»Ссылка.»+ТипПриемника, «Приемник»); Если ПравилоКонвертации = Неопределено Тогда Продолжить; КонецЕсли; TypeOf = СтрЗаменить(ПравилоКонвертации.ТипИсточника, «.», Символы.ПС); ВидИсточника = СтрПолучитьСтроку(TypeOf, 1); ТипИсточника = СтрПолучитьСтроку(TypeOf, 2); Если ВидИсточника = «ДокументСсылка» Тогда МенеджерОбъекта = Документы; ИначеЕсли ВидИсточника = «СправочникСсылка» Тогда МенеджерОбъекта = Справочники; Иначе Отказ = Истина; Продолжить; КонецЕсли; ОбъектСсылка = МенеджерОбъекта.ПолучитьСсылку(Новый УникальныйИдентификатор(УИД)); НайденныйОбъект = ОбъектСсылка.ПолучитьОбъект(); Если НайденныйОбъект = Неопределено Тогда Отказ = Истина; Продолжить; КонецЕсли; ВыгрузитьОбъектВБазуПриемник(ОбъектСсылка, LuExchange, ОбработкаОбмена, ФайлОбмена, ИмяСобытияДляЖурнала,, Отказ); КонецЦикла; КонецПроцедуры Процедура ОбработкаПризнакаПроведенияДокумента(СтрокаЗагруженныеДокументы, LuExchange, ИмяСобытияДляЖурнала, Отказ) Если ПустаяСтрока(СтрокаЗагруженныеДокументы) Тогда Возврат; КонецЕсли; // PostingDocuments ТекстОшибки = «»; Отказ = LuExchange.PostingDocuments(СтрокаЗагруженныеДокументы, ТекстОшибки); КонецПроцедуры Функция ИнициализироватьОбработкуОбмена(ТекущийУзел, ИмяСобытияДляЖурнала, Отказ) // Инициализация ОбработкаОбмена = Обработки.УниверсальныйОбменДаннымиXML.Создать(); ОбработкаОбмена.РежимОбмена = «Выгрузка»; ОбработкаОбмена.ПостроительОтчета = Новый ПостроительОтчета; ОбработкаОбмена.НеВыводитьНикакихИнформационныхСообщенийПользователю = Истина; // Загрузка правил ПравилаОбмена = ТекущийУзел.ПравилаКонвертации.Получить(); ОбработкаОбмена.ЗагрузитьПравилаОбмена(ПравилаОбмена, «Строка»); ОбработкаОбмена.ИмяФайлаПравилОбмена = «Неопределено»; // Обходим глюк обработки, иначе она считает, что правила не загружены // ИмяФайлаОбмена ОбработкаОбмена.ИмяФайлаОбмена = ПолучитьИмяВременногоФайла(«xml»); // Для всех правил конвертации справочников и документов рекомендуется по возможности устанавливать в ИСТИНА следующие свойства: // — Искать объект приемника по внутреннему идентификатору объекта источника; // — При переносе объкта по ссылке НЕ создавать новый объект, а только переносить ссылку; // Для правил конвертации документов дополнительно рекомендуется устанавливать в ИСТИНА следующее свойство: // — Не выгружать объекты свойств источника по ссылкам; // В этом случае файл данных XML для выгружаемого объекта не будет содержать объекты выгружаемые по ссылкам. // Это существенно уменьшит размер передаваемого файла и ускорит процесс синхронизации. // Выгрузка этих объектов при необходимости будет инициироваться автоматически. Возврат ОбработкаОбмена; КонецФункции Функция ПолучитьДанныеXMLПоПравиламКонвертации(ОбработкаОбмена, ОбъектСсылка, ВыгруженоОбъектов, ИмяСобытияДляЖурнала) МетаИмя = ОбъектСсылка.Метаданные().Имя; // Сначала все отключаем Для Каждого Строка из ОбработкаОбмена.ТаблицаПравилВыгрузки.Строки Цикл Строка.Включить = 0; ОбработкаОбмена.УстановитьПометкиПодчиненных(Строка, «Включить»); КонецЦикла; // Включаем нужное правило СтрПравил = ОбработкаОбмена.ТаблицаПравилВыгрузки.Строки.Найти(МетаИмя, «Имя», Истина); Если СтрПравил = Неопределено Тогда Возврат Неопределено; КонецЕсли; Если НЕ ЗначениеЗаполнено(СтрПравил.ИмяОбъектаДляЗапроса) Тогда Возврат Неопределено; КонецЕсли; СтрПравил.Включить = 1; ОбработкаОбмена.УстановитьПометкиРодителей(СтрПравил, «Включить»); // Отбор ИмяОтбора = СтрЗаменить(СтрПравил.ИмяОбъектаДляЗапроса, «.», «_»); ПостроительОтчета = Новый ПостроительОтчета(«ВЫБРАТЬ ПЕРВЫЕ 1 _.* ИЗ » + СтрПравил.ИмяОбъектаДляЗапроса + » КАК _ {ГДЕ _.Ссылка.* КАК » + ИмяОтбора + «}»); Отбор = ПостроительОтчета.Отбор.Добавить(ИмяОтбора); Отбор.ВидСравнения = ВидСравнения.Равно; Отбор.Установить(ОбъектСсылка); СтрПравил.ИспользоватьОтбор = Истина; СтрПравил.НастройкиПостроителя = ПостроительОтчета.ПолучитьНастройки(); // Выгрузка ОбработкаОбмена.ВыполнитьВыгрузку(); ВыгруженоОбъектов = ОбработкаОбмена.мСчетчикВыгруженныхОбъектов; ЧтениеТекста = Новый ЧтениеТекста; ЧтениеТекста.Открыть(ОбработкаОбмена.ИмяФайлаОбмена, КодировкаТекста.UTF8); СтрокаXML = ЧтениеТекста.Прочитать(); ЧтениеТекста.Закрыть(); Возврат СтрокаXML; КонецФункции // ПолучитьДанныеXMLПоПравиламКонвертации() Функция ПолучитьWSПрокси(Параметры, ИмяФайлаПубликации, URIПространстваИменСервиса, ИмяСервиса) Определения = Новый WSОпределения(«http://»+Параметры.Сервер+»/»+Параметры.База+»/ws/»+ИмяФайлаПубликации+»?wsdl», Параметры.Пользователь, Параметры.Пароль); WSПрокси = Новый WSПрокси(Определения, URIПространстваИменСервиса, ИмяСервиса, ИмяСервиса+»Soap»); WSПрокси.Пользователь = Параметры.Пользователь; WSПрокси.Пароль = Параметры.Пароль; Возврат WSПрокси; КонецФункции 6. Настройка Веб-сервиса для базы приемника

7. Модуль Веб-сервиса Функция ExecuteExchange(DataXML, NameOfEvent, FictitiousObjects, UploadedDocuments, ErrorMessage) УстановитьПривилегированныйРежим(Истина); Попытка ОбработкаОбмена = Обработки.УниверсальныйОбменДаннымиXML.Создать(); ОбработкаОбмена.РежимОбмена = «Загрузка»; ОбработкаОбмена.НеВыводитьНикакихИнформационныхСообщенийПользователю = Истина; ОбработкаОбмена.ЗагружатьДанныеВРежимеОбмена = Истина; ОбработкаОбмена.ЗаписыватьВИнформационнуюБазуТолькоИзмененныеОбъекты = Истина; ОбработкаОбмена.ОптимизированнаяЗаписьОбъектов = Истина; ОбработкаОбмена.ЗаписыватьРегистрыНаборамиЗаписей = Истина; РаботаВозможна = ОбработкаОбмена.ВыполнитьДействияПередЧтениемДанных(DataXML.Получить()); Если НЕ РаботаВозможна Тогда ErrorMessage = «ExecuteExchange(1). ОбработкаОбмена.ВыполнитьДействияПередЧтениемДанных — работа не возможна»; Возврат 0; КонецЕсли; ОбработкаОбмена.ПроизвестиЧтениеДанных(ErrorMessage); Если НЕ ПустаяСтрока(ErrorMessage) Тогда Возврат 0; КонецЕсли; ОбработкаОбмена.ВыполнитьДействияПослеЗавершенияЧтенияДанных(); // Подготовим для возврата в базу источник массивы Фиктивных ссылок и массив выгруженных документов МассивФиктивныхСсылок = Новый Массив; МассивЗагруженныхДокументов = Новый Массив; МетаданныеДокументы = Метаданные.Документы; Для каждого КлючИЗначение Из ОбработкаОбмена.ЗагруженныеОбъекты Цикл ОбъектСсылка = КлючИЗначение.Значение.СсылкаНаОбъект; ОбъектМетаданные = ОбъектСсылка.Метаданные(); Если КлючИЗначение.Значение.СсылкаФиктивная Тогда // Фиктивная ссылка — объект не найденный в базе приемнике и не выгруженный по ссылкам МассивФиктивныхСсылок.Добавить(ОбъектМетаданные.ПолноеИмя() + «.» + XMLСтрока(ОбъектСсылка.Ссылка)); ИначеЕсли МетаданныеДокументы.Содержит(ОбъектМетаданные) Тогда МассивЗагруженныхДокументов.Добавить(ОбъектСсылка.Ссылка); КонецЕсли; КонецЦикла; Если МассивФиктивныхСсылок.Количество() > 0 Тогда FictitiousObjects = ЗначениеВСтрокуВнутр(МассивФиктивныхСсылок); КонецЕсли; Если МассивЗагруженныхДокументов.Количество() > 0 Тогда UploadedDocuments = ЗначениеВСтрокуВнутр(МассивЗагруженныхДокументов); КонецЕсли; Исключение ErrorMessage = «ExecuteExchange(2). » + ОписаниеОшибки(); Возврат 0; КонецПопытки; Возврат ОбработкаОбмена.мСчетчикЗагруженныхОбъектов; КонецФункции Функция DeleteObject(TypeOf, UUID, ErrorMessage) УстановитьПривилегированныйРежим(Истина); Попытка TypeOf = СтрЗаменить(TypeOf, «.», Символы.ПС); ВидОбъекта = СтрПолучитьСтроку(TypeOf, 1); ТипОбъекта = СтрПолучитьСтроку(TypeOf, 2); Если ВидОбъекта = «ДокументСсылка» Тогда МенеджерОбъекта = Документы; ИначеЕсли ВидОбъекта = «СправочникСсылка» Тогда МенеджерОбъекта = Справочники; Иначе ErrorMessage = «DeleteObject(1). Ошибка получения менеджера объекта » + ВидОбъекта + «.» + ТипОбъекта + «!»; Возврат Истина; КонецЕсли; ОбъектСсылка = МенеджерОбъекта.ПолучитьСсылку(Новый УникальныйИдентификатор(UUID)); НайденныйОбъект = ОбъектСсылка.ПолучитьОбъект(); Если НЕ НайденныйОбъект = Неопределено Тогда НайденныйОбъект.Удалить(); // В базе приемнике удаление происходит без проверки ссылочной целостности // В некоторых схемах целесообразнее отключать данный функционал // а удаление выполнять соответствующей обработкой // («ПометкаУдаления» синхронизируется обычным образом в ExecuteExchange) КонецЕсли; Исключение ErrorMessage = «DeleteObject(2). » + ОписаниеОшибки(); Возврат Истина; КонецПопытки; Возврат Ложь; КонецФункции Функция PostingDocuments(UploadedDocuments, ErrorMessage) УстановитьПривилегированныйРежим(Истина); Отказ = Ложь; Попытка МассивВыгруженныхДокументов = ЗначениеИзСтрокиВнутр(UploadedDocuments); Для каждого ДокументСсылка Из МассивВыгруженныхДокументов Цикл ДокументОбъект = ДокументСсылка.ПолучитьОбъект(); Если ДокументОбъект = Неопределено Тогда Отказ = Истина; ErrorMessage = ErrorMessage + Символы.ПС + «PostingDocuments(1). Объект не найден: » + ДокументСсылка; Продолжить; КонецЕсли; // Проведение Если ДокументОбъект.Проведен Тогда Попытка ПолучитьСообщенияПользователю(Истина); // Очистим все предыдущие сообщения на момент проведения ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение); Исключение Сообщения = ПолучитьСообщенияПользователю(Истина); // Вернем в базу источник ошибки проведения ТекстСообщения = «»; Для каждого Сообщение Из Сообщения Цикл ТекстСообщения = ТекстСообщения + Символы.ПС + Сообщение.Текст; КонецЦикла; ErrorMessage = ErrorMessage + Символы.ПС + «PostingDocuments(2). » + ДокументСсылка + Символы.ПС + ОписаниеОшибки() + ТекстСообщения; Отказ = Истина; // Сбросим признак проведения ДокументОбъект.Проведен = Ложь; ДокументОбъект.ОбменДанными.Загрузка = Истина; ДокументОбъект.Записать(РежимЗаписиДокумента.Запись); КонецПопытки; КонецЕсли; // Если снят с проведения, очистим движения Если НЕ ДокументОбъект.Проведен Тогда Для каждого НаборДвижений Из ДокументОбъект.Движения Цикл НаборДвижений.Прочитать(); Если НаборДвижений.Количество() > 0 Тогда НаборДвижений.Очистить(); НаборДвижений.Записать(); КонецЕсли; КонецЦикла; КонецЕсли; КонецЦикла; Исключение ErrorMessage = «PostingDocuments(3). » + ОписаниеОшибки(); Отказ = Истина; КонецПопытки; Возврат Отказ; КонецФункции 8. Рекомендации При разработке правил конвертации очень сложно отлаживать правила в боевой схеме, поэтому для сложных конвертаций рекомендую сначало воспользоваться средствами отладки встроенными в обработку «Универсальный обмен данными XML», в этом случае имеется возможность подключить алгоритмы из правил в виде модулей внешней обработки как при выгрузке, так и при загрузке данных. И только после успешной выгрузки — загрузки в интерактивном режиме через промежуточный файл — пробовать синхронизацию через Веб. 9. Опыт внедрения

Данная схема успешно реализована в реальных действующих системах:

  • связка УТ 10.3 и УПП 1.3. (УТ нетиповая, доработана под производство с вводом данных через тач-панели на конвейерной линии)
  • связка Самописная конфигурация и БП 3.0 (В самописной конфигурации ведется учет технологических операций на фабрике птицы)

10. Состав вложенных файлов

  • ОбменДаннымиОнлайнЧерезВебСервис.cf — содержит все описанные объекты для синхронизации (Источник + Приемник). Обычные формы. Клиент-серверный вариант. В файловом варианте тоже все будет работать, кроме регламентного задания. В этом случае необходимо предусмотреть периодический запуск синхронизации с помощью метода ПодключитьОбработчикОжидания(). При сравнении, объединении необходимо отметить по подсистемам файла: подсистема «ЛУ_СинхронизацияЧерезВебСервис».
  • ДемоБазы.zip — содержит выгрузки из двух баз (PR1.dt и PR2.dt) для демонстрации готовой настроенной схемы синхронизации. Базы содержат простенькие документы и справочники. Имена метаданных синхронизируемых объектов различаются. Правила конвертации загружены в базу. Необходимо восстановить базы из .dt. Выполнить публикацию на Веб-сервере под именами PR1 и PR2 с установленной галочкой Публиковать Веб-сервисы и LuExchange. В режиме Предприятия в настройках соответствующих узлов планов обмена необходимо прописать имя Веб-сервера на котором была выполнена публикация баз.
  • ОбменДаннымиОнлайнЧерезВебСервис.cfe — вариант доработки в виде расширения конфигурации для баз находящихся на поддержке без возможности редактирования. Ввиду ограниченного функционала расширений, не содержит объекты: План обмена и Регламентное задание. То есть синхронизация здесь реализована без квитирования успешности доставки данных, но полностью совместима с протоколом обмена основного .cf

11. Инструкция по внедрению (ОбменДаннымиОнлайнЧерезВебСервис.cf)

Скачиваем файл ОбменДаннымиОнлайнЧерезВебСервис.cf

Выполняем команду: Конфигурация — Сравнить, объединить с конфигурацией из файла… После вывода результатов сравнения конфигураций выполняем команду: Действия — Отметить по подсистемам файла — отмечаем подсистему «ЛУ_СинхронизацияЧерезВебСервис». Далее — Выполнить. Обновляем конфигурацию базы данных. То же повторяем для корреспондирующей базы. Публикуем обе базы на Веб-сервере (Как? — это отдельная тема, поиск в помощь)
При публикации отмечаем галочками Публиковать Веб-сервисы и LuExchange. Настраиваем соответствующие узлы Планов обменов обеих баз В первой базе создаем узел с настройками подключения ко второй базе и наоборот. Здесь:

  • Сервер — имя веб-сервера, на котором выполнена публикация баз
  • База — имя, под которым выполнена публикация корреспондирующей базы на веб-сервере, как правило совпадает с именем базы на сервере 1С Предприятие
  • Логин — имя пользователя, которого необходимо создать в обеих базах с ролью WebСервисLuExchange (подключение веб-сервиса будет происходить под этим пользователем)
  • Пароль
  • Правила конвертации — сюда необходимо загрузить правила конвертации, созданные в конфигурации «Конвертация данных»

Создание правил конвертации — тоже отдельная большая тема. (Если не в курсе, можно поштудировать инет) Если Вы владеете этим мощным и универсальным инструментом, то для идентичных корреспондирующих баз, правила конвертации сможете создать полностью автоматически за несколько минут. Открываем состав плана обмена ЛУ_WebСервис и добавляем все объекты, для которых в правилах конвертации прописали ПВД (Правила выгрузки данных). Для всех объектов состава запрещаем авторегистрацию. При разработке правил конвертации придерживаемся следующих рекомендаций:

  • Для ПВД поддерживается только способ выборки: «Стандартная выборка»
  • Для всех ПКО справочников и документов рекомендуется устанавливать в ИСТИНА следующие свойства:
    • Искать объект приемника по внутреннему идентификатору объекта источника;
    • При переносе объкта по ссылке НЕ создавать новый объект, а только переносить ссылку;
  • Для ПКО документов дополнительно рекомендуется устанавливать в ИСТИНА следующее свойство:
    • Не выгружать объекты свойств источника по ссылкам;

В этом случае файл данных XML для выгружаемого объекта не будет содержать объекты выгружаемые по ссылкам. Это существенно уменьшит размер передаваемых данных и ускорит процесс синхронизации. Выгрузка этих объектов при необходимости будет инициироваться автоматически.

Если возникнут затруднения в настройке планов обменов
можно скачать вложение «ДемоБазы.zip» и посмотреть как это выполнено в них. Если понравилось и желаешь порекомендовать другим коллегам, ставь плюс!

Объект 1С «Регистры сведений» — это прикладные объекты конфигурации, которые позволяют хранить в прикладном решении произвольные данные в разрезе нескольких измерений.

Например, в регистре сведений можно хранить курсы валют в разрезе валют, или цены предприятия в разрезе номенклатуры и типа цен.

Функциональные возможности регистра сведений

Основными функциональными возможностями, которые предоставляет регистр сведений разработчику, являются:

  • создание, изменение и удаление записей;
  • выбор записей в заданном интервале по заданным критериям;
  • выбор записей по регистратору;
  • получение значений ресурсов записей, соответствующих указанному периоду и значениям измерений;
  • получение значений ресурсов наиболее ранних и наиболее поздних записей регистра, соответствующих указанному периоду и значениям измерений.

Структура объекта 1С «Регистры сведений»

Информация в регистре сведений хранится в виде записей, каждая из которых содержит:

  1. значения измерений регистра (описывают разрезы, в которых хранится информация);
  2. соответствующие им значения ресурсов (непосредственно содержат хранимую информацию).

Рисунок «Измерения и ресурсы»

Рисунок «1С Регистры сведений»

Например, регистр сведений цены товаров может иметь следующую структуру:

где «Вид цен» может иметь значения «Оптовая», «Розничная», и т.д.

Вместе с каждой записью, находящейся в регистре сведений, в его реквизитах можно хранить дополнительную произвольную информацию.

Периодичность регистра сведений 1С

Одной из возможностей регистра сведений является хранение данных не только в разрезе указанных измерений, но и в разрезе времени.

Данное свойство позволяет добавить к списку измерений регистра дополнительное измерение — «Период».

Использование периодичности регистра сведений позволяет не просто хранить статические данные, но и отслеживать их актуальность на определенную дату или изменение во времени.

Разработчик может указать минимальную периодичность, с которой записи будут заноситься в регистр:

Периодичность может принимать следующие значения:

  • Непериодический;
  • В пределах секунды;
  • В пределах дня;
  • В пределах месяца;
  • В пределах квартала;
  • В пределах года.

В этом случае к каждой записи регистра будет добавляться поле «Период», хранящее дату, которой были внесены записи в регистр.

При выборе периодичности, отличной от варианта «Непериодический», система будет контролировать уникальность записей в пределах заданного промежутка времени. Если запись не уникальна, система 1C выдаст сообщение «Запись с такими ключевыми полями существует!» и не даст произвести запись в базу данных.

Например, периодический регистр сведений «Цены товаров» может не только хранить информацию о том, какова цена на определенную номенклатуру сейчас, но и о том, как она изменялась в прошлом (или будет изменяться в будущем).

Особенность периодического регистра сведений:

  • Возможность получать готовые значения «Срез первых» и «Срез последних». Эта информация позволяет очень быстро получить из базы данных информацию о последнем (первом) установленном значении на определенную дату.

Рисунок

Подчинение регистратору

Внесение изменений в регистр сведений может выполняться:

  1. вручную;
  2. при помощи документов.

В случае, когда изменения в регистр сведений вносятся с помощью документов, к каждой записи регистра добавляется специальное поле, в котором хранится информация о регистраторе — документе, с которым связана эта запись.

Какой именно режим записи будет использоваться данным регистром сведений указывается разработчиком в процессе создания прикладного решения:

Свойство «Режим записи»может быть в значении:

  1. «Независимый» — записи можно произвести как программно, так и из формы списка регистра сведений;
  2. «Подчинение регистратору» — обязательно указание документа-регистратора записи.

Использование режима записи «Подчинение регистратору» необходимо в случае, когда логика работы прикладного решения требует того, чтобы изменения, выполняемые в регистре сведений, были жестко связаны с документами, фиксирующими факты хозяйственной деятельности.

Например, изменение цен компании может производиться только определенным кругом лиц, и каждое такое изменение должно сопровождаться «бумажным» документом. В этом случае можно использовать режим подчинения регистратору, при котором изменение цен может быть выполнено только специальным документом — «Изменение цен товаров».

Уникальность записей регистра сведений

Система обеспечивает контроль уникальности записей, хранящихся в регистре сведений. Таким образом, в регистре сведений не может находиться двух одинаковых записей (с одинаковым ключом записи). Ключ записи формируется системой автоматически, на основании значений, содержащихся в полях записи, и зависит от вида регистра сведений.

В общем случае в формировании ключа записи будут участвовать значения регистратора, периода и значения измерений.

Таким образом, например, в непериодическом регистре сведений «Цены товаров» с независимым режимом записи не может существовать двух записей о розничной цене конфет ассорти. Точно так же, как в периодическом регистре сведений «Цены товаров», подчиненном регистратору, не может существовать двух записей о розничной цене конфет ассорти, внесенных одной и той же датой, одним и тем же документом «Изменение цен товаров».

Свойства измерения регистра сведений

Особое внимание следует обратить на флаги «Ведущее» и «Основной отбор» палитры свойств измерений регистра сведений.

Рисунок

  • Ведущее — свойство измерения, указывающее на то, что без значения этого измерения запись регистра не имеет смысл. Установка флага означает что система при удалении значения из измерения удаляет еще и запись регистра с «Ведущим» измерением. Может быть установлено только одно измерение.
  • Основной отбор — если регистр независимый, то по этим измерениям будет устанавливаться регистрация изменений для плана обмена. Аналогично использование «Основной отбор» по периоду включает основной отбор для периода периодических регистров.

Программная запись в регистр сведений 1С

Добавить новые записи в регистр сведений можно двумя способами:

  1. с помощью менеджера записи (для одиночной записи);
  2. с помощью набора записей (для двух и и более записей).

Примеры :

Использование менеджера записи: 1С (Код) Использование набора записей регистра сведений 1С: 1С (Код)

для полной программной очистки всех записей регистра сведений.

Формы объекта 1С «Регистры сведений»

Для того чтобы пользователь мог просматривать и изменять данные, содержащиеся в регистре сведений, система поддерживает несколько форм представления регистра. Система может автоматически генерировать все нужные формы регистра. Наряду с этим разработчик имеет возможность создать собственные формы, которые система будет использовать вместо форм по умолчанию.

Форма записи регистра сведений 1С

Для просмотра и изменения отдельных записей регистра сведений используется форма записи. Как правило, она представляет данные в удобном для восприятия и редактирования виде.

Форма списка регистра сведений 1С

Для просмотра данных, содержащихся в регистре сведений, используется форма списка. Она позволяет:

  • выполнять навигацию по регистру;
  • добавлять, помечать на удаление и удалять записи регистра;
  • выполнять сортировку и отбор отображаемой информации по нескольким критериям.

Как в периодическом независимом регистре сведений удалить все записи через запрос?

Запрос = Новый Запрос; Запрос.Текст = «ВЫБРАТЬ | * |ИЗ | РегистрСведений.КурсыВалют КАК КурсыВалют |ГДЕ | (КурсыВалют.Период >= ДАТАВРЕМЯ(2005, 1, 1) | ИЛИ | НЕ(КурсыВалют.Валюта.Наименование ПОДОБНО «»USD»») | И | НЕ(КурсыВалют.Валюта.Наименование ПОДОБНО «»EUR»»))»; ТаблицаОставляемыхЗаписей = Запрос.Выполнить().Выгрузить(); НаборЗаписей = РегистрыСведений.КурсыВалют.СоздатьНаборЗаписей(); НаборЗаписей.Загрузить(ТаблицаОставляемыхЗаписей); НаборЗаписей.Записать();

Как перебрать записи непериодического независимого регистра сведений в цикле?

НаборЗаписей = РегистрыСведений.СобственныеКонтрагенты.СоздатьНаборЗаписей(); НаборЗаписей.Прочитать(); // Перебрать записи в цикле… Для Каждого Запись из НаборЗаписей Цикл РегистрКонтрагент = Запись.Контрагент; РегистрВидСвязи = Запись.ВидСвязи; РегистрОбъект = Запись.Объект; КонецЦикла;

Как выгрузить записи непериодического независимого регистра в таблицу значений

НаборЗаписей = РегистрыСведений.СобственныеКонтрагенты.СоздатьНаборЗаписей(); НаборЗаписей.Прочитать(); // … выгрузить записи в таблицу значений. ТаблицаЗаписей = НаборЗаписей.Выгрузить();

Как прочитать (изменить) записи в периодическом независимом регистре сведений?

НаборЗаписей = РегистрыСведений.Валюты.СоздатьНаборЗаписей(); НаборЗаписей.Отбор.Период.Установить(ДатаЗаписи); НаборЗаписей.Прочитать(); Для Каждого Запись Из НаборЗаписей Цикл // Чтение и сообщение данных полей записи. Сообщить(Строка(Запись.Период) + » » + Строка(Запись.Валюта) + » » + Строка(Запись.Курс)); // Изменение данных полей записи. Запись.Курс = 0; КонецЦикла; НаборЗаписей.Записать();

Как прочитать данные, актуальные на определенную дату, из регистра сведений «Курсы валют» с отбором по нескольким валютам (отбор по измерениям)?

Запрос = Новый Запрос; МассивВалют = Новый Массив; МассивВалют.Добавить(Валюта1); МассивВалют.Добавить(Валюта2); Запрос.УстановитьПараметр(«МассивВалют», МассивВалют); Запрос.УстановитьПараметр(«ДатаПолучения», ДатаПолучения); Запрос.Текст = » |ВЫБРАТЬ | ВалютыСрезПоследних.Валюта, | ВалютыСрезПоследних.Курс |ИЗ | РегистрСведений.КурсыВалют.СрезПоследних(&ДатаПолучения, Валюта В (&МассивВалют)) КАК ВалютыСрезПоследних»; ТаблицаКурсов = Запрос.Выполнить().Выгрузить();

Как поменять период у записей периодического независимого регистра, соответствующих ряду условий?

Процедура ЗаменаПериода() Запрос = Новый Запрос; Запрос.Текст = «ВЫБРАТЬ | ОтветственныеЛицаОрганизации.Период, | ОтветственныеЛицаОрганизации.СтруктурнаяЕдиница, | ОтветственныеЛицаОрганизации.ОтветственноеЛицо |ИЗ | РегистрСведений.ОтветственныеЛицаОрганизации КАК ОтветственныеЛицаОрганизации |ГДЕ | ОтветственныеЛицаОрганизации.Период <= ДАТАВРЕМЯ(2005, 1, 1) | И | ОтветственныеЛицаОрганизации.СтруктурнаяЕдиница.Наименование | ПОДОБНО «Групп-Трейдинг» | И | (ОтветственныеЛицаОрганизации.Должность.Наименование ЕСТЬ NULL | ИЛИ | НЕ(ОтветственныеЛицаОрганизации.Должность.Наименование | ПОДОБНО «Продавец» | ИЛИ | ОтветственныеЛицаОрганизации.Должность.Наименование | ПОДОБНО «Кладовщик»))»; Результат = Запрос.Выполнить(); Выборка = Результат.Выбрать(); Запись = РегистрыСведений.ОтветственныеЛицаОрганизации.СоздатьМенеджерЗаписи(); Пока Выборка.Следующий() Цикл Запись.Период = Выборка.Период; Запись.СтруктурнаяЕдиница = Выборка.СтруктурнаяЕдиница; Запись.ОтветственноеЛицо = Выборка.ОтветственноеЛицо; Запись.Прочитать(); Если Запись.Выбран() Тогда Запись.Период = Дата(2004, 1, 1); Запись.Записать(); КонецЕсли; КонецЦикла; КонецПроцедуры;

Как «сделать периодическим» реквизит уже заполненного справочника?

Запрос = Новый Запрос; Запрос.Текст = «ВЫБРАТЬ | &ДатаУстановки КАК Период, | Проекты.Ссылка КАК Проект, | Проекты.Ответственный |ИЗ | Справочник.Проекты КАК Проекты |ГДЕ | (НЕ(Проекты.ЭтоГруппа)) И (НЕ(Проекты.Ответственный = &Ответственный))»; Запрос.УстановитьПараметр(«Ответственный», Справочники.Пользователи.ПустаяСсылка()); Запрос.УстановитьПараметр(«ДатаУстановки», Дата(2000,1,1)); ТаблицаРезультат = Запрос.Выполнить().Выгрузить(); НаборЗаписей = РегистрыСведений.ЗакреплениеПроектов.СоздатьНаборЗаписей(); НаборЗаписей.Загрузить(ТаблицаРезультат); НаборЗаписей.Записать();

Как прочитать (изменить) записи в регистре сведений, подчиненном регистратору?

НаборЗаписей = РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей(); НаборЗаписей.Отбор.Регистратор.Установить(ВыбранныйРегистратор); НаборЗаписей.Прочитать(); Для Каждого Запись Из НаборЗаписей Цикл // Чтение и сообщение данных полей записи. Сообщить(Строка(Запись.Период) + » » + Строка(Запись.ТипЦен) +» «+ Строка(Запись.Номенклатура) + » » + Строка(Запись.Цена) + » » + Строка(Запись.ПроцентСкидкиНаценки)); // Изменение данных полей записи. Запись.ПроцентСкидкиНаценки = 0; КонецЦикла; НаборЗаписей.Записать();

Получить массив типов Регистратора

НаборЗаписей = РегистрыСведений.ЦеныНоменклатурыКонтрагентов.СоздатьНаборЗаписей(); Мас = НаборЗаписей.Отбор.Регистратор.ТипЗначения.Типы();

Как вывести в запросе данные по определенному виду (типу) документа. 1С:Предприятие 8.2?
Можно использовать слово .
Для 1С:Предприятие 8.2 предусмотрена еще одна конструкция: ТИПЗНАЧЕНИЯ и ТИП.

ГДЕ ТИПЗНАЧЕНИЯ(Регистратор) = ТИП(Документ.ПоступлениеТоваровУслуг)

ПоступлениеТоваровУслуг — это объект (документ), созданный в конфигураторе.
Пример: вывод суммы оборотов по всем счетам для документа вида Поступление товаров и услуг за определенный период.

ВЫБРАТЬ ХозрасчетныйОборотыДтКт.СчетДт, ХозрасчетныйОборотыДтКт.СчетКт, ХозрасчетныйОборотыДтКт.СуммаОборот, ХозрасчетныйОборотыДтКт.Регистратор ИЗ РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(&НачалоПериода, &КонецПериода, Регистратор, , , , , ) КАК ХозрасчетныйОборотыДтКт ГДЕ ТИПЗНАЧЕНИЯ(Регистратор) = ТИП(Документ.ПоступлениеТоваровУслуг)

Возможно вам будет интересно узнать: Как в табличной части документа в 1С:Предприятие 8.2 добавить новую колонку?

Режим записи документов в 1С
Результаты запроса в таблицу значений 1С.
Функция Вычислить (Выражение) в 1С.
Функция СтрЗаменить (ТекСтрока, ТекПодстрокаПоиска, ТекПодстрокаЗамены) в 1С.
Оператор ВЫБОР в запросе 1С.
Оператор ПОДОБНО в запросе 1С.
Meizu m3 Note установленные программы
Meizu M3s Как скопировать файл со смартфона на компьютер?
Описание ноутбука Acer Aspire ES1 731G P15K.
Рассмотрим функции для работы со строкой: Найти(), Сред(), СтрДлина(). 1С:Предприятие.
Как загрузить информацию из Excel в 1С:Предприятие? При помощи COMObject. Вариант 1.
Таблица значений в 1С:Предприятии 8.0, 8.1, 8.2.
Горячие клавиши в 1С:Предприятие 8.2.
Как в табличной части документа в 1С:Предприятие 8.2 добавить новую колонку?
Обзор Meizu M3s 16Gb.
Как сделать журнальный столик своими руками?
Обзор Meizu M3 note.
Как работает 3D принтер? Демонстрация 3D печати.
Перевернулся экран на мониторе компьютера или ноутбука, Windows. Как вернуть исходное положение?
Смартфон Moto X4 в воде.
Как установить розетку?