gifts2017

Отмена проведения и проведение документов при переносе данных с использованием конвертации данных.

Опубликовал Владимир (ARL) в раздел Обмен - Перенос данных из 1C8 в 1C8

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

При переносе данных между базами часто возникает ситуация, когда движения документов переносить не требуется, а перенесенные документы следует проводить в базе-приёмнике. Например, в базе-источнике ведется управленческий учет, а в базе-приемнике  регламентированный.  Если при переносе не учитывать свойство «Проведен» документа, то можно получить в приемнике проведенные документы, у которых данные в движениях и в объекте не соответствуют друг другу.

 В правилах конвертации объектов (ПКО) в обработчике «Перед загрузкой» существуют параметры «РежимЗаписи» и «РежимПроведения», указание которых обеспечивает необходимый режим записи объекта, но в этом случае, запись происходит во время загрузки данных и если, по каким-то причинам, документ не запишется, загрузка данных будет прервана. Правильней записывать новые документы в конце загрузки, когда все перенесенные объекты уже будут в базе - приемнике.

Несколько основных моментов:

  1. Нам необходим параметр конвертации с типом «Таблица значений», куда можно будет записывать ссылки на документ и информацию о том, что с документом делать. Создать параметр на вкладке «Параметры» конвертации – не получится, но его спокойно можно создать программным способом. После использования наш параметр следует удалить, в противном случае при использовании управляемой формы обработки система будет выдавать сообщение об ошибке, т.к. управляемая форма не использует таблицу значений. Несмотря на сообщение об ошибке, обработка все действия выполнит, но нервировать пользователей подобными сообщениями не следует.
  2. Для анализа, новый это объект или существующий в обработке используется параметр ОбъектНайден.
  3. Для анализа состояния ранее записанного объекта в приемнике используем обращение к его ссылке (Объект.Ссылка).
  4. Для записи ссылки нового для приемника документа нам необходимо документ записать. Чтобы избежать повторной записи документа обработкой обмена следует выставить параметр ОбъектМодифицирован в значение Ложь.
  5. Обработка обмена данными при записи документа обнуляет перенесенную пометку удаления. Это необходимо учитывать.
  6.  Для решения стоящей задачи наиболее удобно использовать обработчики событий конвертации в целом. Но нам необходимо определить – объект  - это документ, и если документ – то проводится ли он. Для идентификации документа используем параметр обработчика ИмяТипаОбъекта.

 

I. Первый, более простой, случай: требуется оставлять в базе-приемнике документы непроведенными.

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

     Свойство «Проведен» необходимо исключить из переноса в каждом документе. Нам необходимо при выгрузке данных запоминать необходимые для отмены проведения документы и после загрузки данных записать их с режимом отмены проведения. Помимо ссылки на документ необходимо сохранять и информацию об его пометке удаления. Для получения информации о пометке удаления данное свойство каждого проводимого документа необходимо передавать в параметр, который назовем также, как и имя свойства - ПометкаУдаления. (Рис.1)

1. В обработчике «Перед загрузкой данных» конвертации создаем параметр с типом значений «Таблица значений».  В колонку "Действие" строкой будем записывать – что делать с документом: просто отменять проведение или еще проставлять пометку на удаление.

     ТаблицаДокументов = Новый ТаблицаЗначений;
     ТаблицаДокументов.Колонки.Добавить("Ссылка");
     ТаблицаДокументов.Колонки.Добавить("Действие");
     Параметры.Вставить("ТаблицаДокументов",ТаблицаДокументов);

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

    Если ОбъектНайден
        И ИмяТипаОбъекта = "Документ"
        И
Объект.Метаданные().Проведение = Метаданные.СвойстваОбъектов.Проведение.Разрешить
        И Объект.Ссылка.Проведен Тогда
        
НоваяСтрока = Параметры.ТаблицаДокументов.Добавить();
        
НоваяСтрока.Ссылка = Объект.Ссылка;
        Если
ПараметрыОбъекта.Получить("ПометкаУдаления") Тогда
            
НоваяСтрока.Действие = "Удаление";
        Иначе
            
НоваяСтрока.Действие = "Отмена";
        КонецЕсли;
    ИначеЕсли 
ПараметрыОбъекта <> Неопределено И Лев(Строка(ТипЗнч(Объект)),8) = "Документ"  Тогда
        
Объект.ПометкаУдаления = ПараметрыОбъекта.Получить("ПометкаУдаления"); //Пометка удаления у новых объектов и непроведенных старых
    КонецЕсли;

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

     ТекстСообщенияОтмены = "";
     
ТекстСообщенияОшибки = "";
     Для каждого
СтрокаТч Из Параметры.ТаблицаДокументов Цикл
         Попытка
             
ДокОбъект = СтрокаТч.Ссылка.ПолучитьОбъект();
             Если
СтрокаТч.Ссылка.Проведен Тогда
                 
ДокОбъект.Записать(РежимЗаписиДокумента.ОтменаПроведения);
             КонецЕсли;
             Если
СтрокаТч.Действие = "Удаление" Тогда
                 
ДокОбъект.ПометкаУдаления = Истина;
                 
ДокОбъект.Записать();
             КонецЕсли;
             
ТекстСообщенияОтмены = ТекстСообщенияОтмены + Строка(СтрокаТч.Ссылка) + Символы.ПС;
         Исключение
             ТекстСообщенияОшибки 
= ТекстСообщенияОшибки + Строка(СтрокаТч.Ссылка) + " : "+ ОписаниеОшибки() + Символы.ПС;
         КонецПопытки;
     КонецЦикла;

     Если Не
ПустаяСтрока(ТекстСообщенияОтмены) Тогда
         
Сообщить("Отменено проведение документов:" + Символы.ПС + ТекстСообщенияОтмены);
     КонецЕсли;
     Если Не
ПустаяСтрока(ТекстСообщенияОшибки) Тогда
         
Сообщить("Ошибки при отмене проведения: "+ Символы.ПС + ТекстСообщенияОшибки);
     КонецЕсли;
     
Параметры.Удалить("ТаблицаДокументов");

II. Требуется обеспечить проведение документов в базе-приемнике при переносе.

   В этом случае необходимо помимо пометки удаления передавать значение свойства «Проведен» в параметр «Проведен» и данный параметр анализировать в обработчике «После загрузки объекта» (Рис.2).

1. «Перед загрузкой данных» Повторяем создание параметра конвертации, как в первом примере

ТаблицаДокументов = Новый ТаблицаЗначений;
ТаблицаДокументов.Колонки.Добавить("Ссылка");
ТаблицаДокументов.Колонки.Добавить("Действие");
Параметры.Вставить("ТаблицаДокументов",ТаблицаДокументов);

2. «После загрузки объекта»  После загрузки мы должны уже работать с объектами, которые еще не записаны в базе. Документы можно выделить по типу значения, а новый объект, перед внесением в таблицу параметра, необходимо предварительно записать. Не забываем установить параметр «ОбъектМодифицирован» в «Ложь». 

Если ИмяТипаОбъекта = "Документ"
   
И Объект.Метаданные().Проведение = Метаданные.СвойстваОбъектов.Проведение.Разрешить Тогда

    Если Не
ОбъектНайден  Тогда
       
Объект.Записать();
       
ОбъектМодифицирован = Ложь;
    КонецЕсли;

   
НоваяСтрока Параметры.ТаблицаДокументов.Добавить();
   
НоваяСтрока.Ссылка = Объект.Ссылка;

    Если
ПараметрыОбъекта.Получить("Проведен")  Тогда
       
НоваяСтрока.Действие = "Проведение";
    ИначеЕсли
ПараметрыОбъекта.Получить("ПометкаУдаления")  Тогда
       
НоваяСтрока.Действие = "Удаление";
    Иначе
       
НоваяСтрока.Действие = "Отмена";
    КонецЕсли;
КонецЕсли;

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

ТекстСообщенияЗаписи = "";
ТекстСообщенияОшибки = "";

Для каждого СтрокаТч Из Параметры.ТаблицаДокументов Цикл


    Если
СтрокаТч.Действие = "Отмена"  И Не СтрокаТч.Ссылка.Проведен Тогда
        Если
СтрокаТч.Ссылка.ПометкаУдаления Тогда  //Для снятия пометки удаления
           
Попытка
               
ДокОбъект = СтрокаТч.Ссылка.ПолучитьОбъект();
               
ДокОбъект.ПометкаУдаления = Ложь;
               
ДокОбъект.Записать();
            Исключение
            КонецПопытки;
        КонецЕсли;

        Продолжить;

    КонецЕсли;

    Если
СтрокаТч.Действие = "Проведение" Тогда
       
РежимЗаписи = РежимЗаписиДокумента.Проведение;
    Иначе
       
РежимЗаписи = РежимЗаписиДокумента.ОтменаПроведения;
    КонецЕсли;

    Попытка
       
ДокОбъект = СтрокаТч.Ссылка.ПолучитьОбъект();
        Если (
СтрокаТч.Действие <> "Удаление" Или  СтрокаТч.Ссылка.Проведен) Тогда
           
ДокОбъект.Записать(РежимЗаписи);
           
ТекстСообщенияЗаписи = ТекстСообщенияЗаписи +?(РежимЗаписи = РежимЗаписиДокумента.Проведение,
           
"Проведен ","Отменено проведение ")
            +
Строка(СтрокаТч.Ссылка) + Символы.ПС;
        КонецЕсли;

        Если
СтрокаТч.Действие = "Удаление" Тогда
           
ДокОбъект.ПометкаУдаления = Истина;
           
ДокОбъект.Записать();
        ИначеЕсли
СтрокаТч.Ссылка.ПометкаУдаления Тогда
           
ДокОбъект.ПометкаУдаления = Ложь;
           
ДокОбъект.Записать();
        КонецЕсли;
    Исключение    

    ТекстСообщенияОшибки = ТекстСообщенияОшибки Строка(СтрокаТч.Ссылка)+ " : "+ОписаниеОшибки()+ Символы.ПС;

    КонецПопытки;
КонецЦикла;

Если Не
ПустаяСтрока(ТекстСообщенияЗаписи) Тогда
   
Сообщить(ТекстСообщенияЗаписи);
КонецЕсли;

Если Не
ПустаяСтрока(ТекстСообщенияОшибки) Тогда
   
Сообщить("Ошибки при отмене проведения: "+ Символы.ПС + ТекстСообщенияОшибки);
КонецЕсли;
Параметры.Удалить("ТаблицаДокументов");

 



См. также

Подписаться Добавить вознаграждение

Комментарии

1. Андрей Крутских (K_A_O) 24.12.12 10:55
Конечно же, такой подход имеет право на жизнь.
Однако в большинстве случаев достаточно параметра РежимЗаписи и установки флажка "Режим отладки" в обработке загрузки. В этом режиме загрузка прерываться не будет.
2. Александр Зубцов (iov) 24.12.12 12:07
(0) в КД проведен - в ложь.
Если перегружаем все подряд - то дополнительный реквизит - проводить = истина.
после загрузки - проводим все что нужно через попытку что не провелось - сообщаем пользователю.
Вариант?
3. Владимир (ARL) 24.12.12 12:46
(2)Вариантов всегда масса :) Показан один из них, реализованный у меня лично. У меня регулярный перенос по плану обмена. Проводить все подряд - в моем случае не допустимо.
4. Александр Зубцов (iov) 24.12.12 12:55
(3)тык у меня тоже не все подряд - а только то что проведено в основной ... Но именно через попытку - потому как даже режим записи= истина не гарантирует корректности проводок (а порой документ проведен/не проведен а движений есть/нет). Но не суть на больших объемах (много данных или много обменов или и то и другое) обмен приходится делать через такие хитрости и извраты.... Но как говорится ваше решение имеет право на жизнь. И оно пригодится в ряде решений других задач.
5. Владимир (ARL) 24.12.12 13:07
(4) В примерах все проводится через попытку. Только оператор открывается перед ПолучитьОбъект(), т.к. мы можем пытаться манипулировать с ранее записанным объектом, а он может быть кем-нибудь заблокирован.
6. Александр Зубцов (iov) 24.12.12 13:22
(5) дааа есть такие гады... дай ткнуть в документ ... :)
7. Fomix (fomix) 11.01.13 12:34
Возможно у автора описка в тексте публикации. Событие "После загрузки данных" выполняется самым последним после загрузки данных из файла обмена, когда файл уже закрыт и только один раз! А потому правильнее будет, если таблица значений создается в событии "Перед загрузкой данных", которое выполняется первым перед началом загрузки данных из файла и только один раз, после открытия файла для чтения. В данном обработчике как раз и могут быть инициализированы переменные, которые впоследствии предполагается использовать.
Fox-trot; trium@bk.ru; +2 Ответить 1
8. Владимир (ARL) 11.01.13 12:55
(7)Точно, описался. Несколько раз проверял, а такую очевидную ляпу пропустил. Благодарю за замечание, исправляю.
9. Fomix (fomix) 16.01.13 17:29
Еще ошибка в обоих фрагментах текста обработчика "После загрузки данных":
....
Попытка
.....
Исключение
ТекстОшибки = ТекстСообщенияОшибки + Строка(СтрокаТч.Ссылка) + " : "+ ОписаниеОшибки() + Символы.ПС;
КонецПопытки;

нужно исправить на:
ТекстСообщенияОшибки = ТекстСообщенияОшибки + Строка(СтрокаТч.Ссылка) + " : "+ ОписаниеОшибки() + Символы.ПС;
Designer1C; LexSeIch; +2 Ответить 1
10. Владимир (ARL) 17.01.13 00:15
11. Fomix (fomix) 17.01.13 10:05
Тут еще по теме всплыли мыслишки. Для проверки принадлежности загружаемого объекта к типу "Документ" заменить нижеприведенные конструкции в обработчиках «После загрузки объекта» конвертации:

>> Документы.ТипВсеСсылки().СодержитТип(ТипЗнч(Объект.Ссылка))
>> Лев(Строка(ТипЗнч(Объект)),8) = "Документ"

на более простую:
<< Если ИмяТипаОбъекта = "Документ" ...
12. Владимир (ARL) 17.01.13 15:25
Так будет и проще, и правильней. Не обратил внимание на данный параметр обработчика в свое время. В "своем" обмене уже поменял.
13. Иван Иванов (Manonegro) 15.03.13 16:28
У меня выдает ошибку:

Ошибка в глобальном обработчике события ПослеЗагрузкиОбъекта (конвертация)
Значение не является значением объектного типа (Получить)

Я, так понимаю, ПараметрыОбъекта = Неопределено.

Или свойства ПометкаУдаления и Проведен нужно передавать в параметр? Тогда для переноса из 7.7 не подходит, ибо в параметр переносить нельзя. Есть другой способ передать эти свойства? Например, через глобальные параметры?
14. Артём Шалнев (88wau24ru) 09.04.13 17:29
(12) ARL, Помогите разобраться новичку,
В обработчике «Перед загрузкой данных» конвертации
В обработчике «После загрузки объекта» конвертации
В обработчике «После загрузки данных» конвертации
Это глобальные обработчики, которые находятся на закладке "Основная" Конвертации, и они будут отрабатывать только для тех объектов у которых ПКС ПометкаУдаления и Проведен заменены на параметры??? А если не заменять на параметры то все будет как обычно(без параметров)?
,
В общем глупый вопрос, все написано в описании, невнимательно прочитал... спасибо за копипаст... работает
sv_mikh; knigina; +2 Ответить
15. Сергей Маслов (LexSeIch) 17.06.13 08:31
Мир этому дому!
Автору плюс, fomix - то же плюс. Статья интересная - пока бегло прочитал - позже разберусь внимательней. Спасибо!
16. Илья Васильев (swimdog) 07.11.13 12:03
Пригодилось. Я делал похожий механизм, но проводил сразу после загрузки.
17. Илья Васильев (swimdog) 07.11.13 12:11
А зачем надо Проведен и ПометкаУдаления передавать через параметр? Почему нельзя просто Объект.Проведен и Объект.ПометкаУдаления?
И ПометкаУдаления снимается обработкой, наверное, в том случае, когда в обработке по загрузке установлен флажок "Объекты, выгруженные по ссылке, загружать без пометки на удаление".
18. Владимир (ARL) 07.11.13 23:15
(17)
А зачем надо Проведен и ПометкаУдаления передавать через параметр? Почему нельзя просто Объект.Проведен

Через параметр передавать логичней, т.к. пометки появятся у документов только после проведения - отмены проведения в базе приемника.
Пример: вы передали свойство "Проведен" при обмене. Но при проведении - документ не провелся, а свойство - осталось. Получим проведенный документ без движений.
когда в обработке по загрузке установлен флажок "Объекты, выгруженные по ссылке, загружать без пометки на удаление"

Надо пробовать. Вроде как написано - для объектов по ссылке, а не напрямую.
Я заметил,к примеру, что при загрузке обработкой в управляемой форме - проблем с пометкой не возникало.
А к статье надо относиться как примеру методики работы с конвертацией, а использовать или нет - это уже в каждом конкретном случае надо определять.
19. Ирина Книгина (knigina) 15.11.13 23:25
Моя тема. Как новичок, которому приходилось довольствоваться штатным обменом УТ 10.3-БП 3.0, не знала как подступить к переносу без проведения документов. Спасибо автору. И отдельное спасибо от меня 88wau24ru за правильно заданный (для меня!) вопрос...и ответ. В результате что-то у меня даже получилось. Буду разбираться дальше.
20. Сергей Макаров (RSConsulting) 17.02.15 07:59
Ругается на строку "Если ПараметрыОбъекта.Получить("Проведен") Тогда".
Ошибка: "Значение не является значением объектного типа (Получить)"
Версия конвертации 2.1.8.1
21. Сергей Макаров (RSConsulting) 17.02.15 08:16
Заменил код в обработчике После загрузки объекта на

Если ИмяТипаОбъекта = "Документ"
    И Объект.Метаданные().Проведение = Метаданные.СвойстваОбъектов.Проведение.Разрешить Тогда

    Если Не ОбъектНайден  Тогда
        Объект.Записать();
        ОбъектМодифицирован = Ложь;
    КонецЕсли;

    НоваяСтрока =  Параметры.ТаблицаДокументов.Добавить();
    НоваяСтрока.Ссылка = Объект.Ссылка;

    Если Объект.Проведен  Тогда
        НоваяСтрока.Действие = "Проведение";
    ИначеЕсли Объект.ПометкаУдаления Тогда
        НоваяСтрока.Действие = "Удаление";
    Иначе
        НоваяСтрока.Действие = "Отмена";
	КонецЕсли;
КонецЕсли;
...Показать Скрыть


Заработало!
ДимокШ; Designer1C; eldarik; maksa2005; Dunda; +5 Ответить 1
22. Владимир (ARL) 18.02.15 10:34
(20) Вы пропустили момент
В этом случае необходимо помимо пометки удаления передавать значение свойства «Проведен» в параметр «Проведен» и данный параметр анализировать в обработчике «После загрузки объекта» (Рис.2).
(21) Заработало, но некорректно. Возможно, что в новой базе документ не проведется, а свойство "Проведен" останется. Получим проведенный документ без движений. Пользователи скажут "спасибо".
23. Дамир Хан (damirxan) 23.03.15 10:37
Все работает.
Спасибо за решение по проведению документов через Параметр.
24. Владимир Клименко (KliMich) 25.03.16 19:19
Спасибо! Переносил через КД из ПУБ 7.7 в БП 3.0.

Только при переносе из 1с 7.7 "передача данных в параметр" не работают....
Сделал как в посте 21. RSConsulting - все сработало!
25. Николай Чернышев (Nik777x) 16.08.16 09:42
Спасибо, пригодилось. Автору респект.
26. Kida Kida (kida1) 24.11.16 20:11
Автору Спасибо!
хорошо бы добавить снятие с проведения
(22) Добавьте в исключение в «После загрузки данных» не просто ТекстОшибки, а снятие с проведения

 Если СтрокаТч.Действие = "Проведение" Тогда
            ДокОбъект.Записать(РежимЗаписиДокумента.ОтменаПроведения);
    КонецЕсли;
    ТекстОшибки = ТекстСообщенияОшибки + Строка(СтрокаТч.Ссылка)+ " : "+ОписаниеОшибки()+ Символы.ПС;

Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа