Имя: Пароль:
1C
1С v8
Вопрос по конвертации данных
0 belka4_4
 
07.11.18
12:06
Добрый день!

Конвертирую документ из базы УПП 1.3 с подсистемой ТОиР в ТОиР 2.0
Документ "ВЫявленные дефекты". У него есть табличная часть СписокДефектов. В ней в каждой строке есть 2 реквизита: РодительскийЭлемент и ДочернийЭлемент (названия другие, но суть не в этом), оба типа Справочник.ОбъектыРемонта.

Задача: надо перенести только те документы, объекты ремонта которых которые уже есть в ТОиР 2.0. В УПП 1.3 каждому объекту ремонта в специальный реквизит "КодВТоиР20" прописан код, если не прописан, значит этот объект не переносился. Переносить надо следующим образом:
1. Код проставлен для РодительскогоЭлемента и для ДочернегоЭлемента - переносим документ.
2. Код проставлен для РодительскогоЭлемента и не проставлен для ДочернегоЭлемента - переносим документ, но вместо ДочернегоЭлемента подставляем Родительский, т.е. дублируем в одной строке значение в двух реквизитах.
3. Код не проставлен для РодительскогоЭлемента и проставлен для ДочернегоЭлемента - переносим документ. При этом в базе-приемнике, запросом ищем родителя для этого дочернего элемента и подставляем найденный в РодительскийЭлемент. Если не нашли - документ не переносим
4. Код не проставлен для РодительскогоЭлемента и не проставлен для ДочернегоЭлемента - не переносим документ.

Логика выглядит примерно следующим образом:

Для Каждого ОР Из Источник.СписокДефектов Цикл

    Если НЕ ЗначениеЗаполнено(ОР.ОбъектРемонта.КодВТОиР20) Тогда //не заполнен родитель
        Если ЗначениеЗаполнено(ОР.ОтказавшийЭлемент.КодВТОиР20) Тогда // заполнен подчиненный
            ОР.ОтказавшийЭлемент = Справочники.торо_ОбъектыРемонта.НайтиПоРеквизиту("ТехНомер", ОР.ОтказавшийЭлемент.КодВТОиР20);
            Запрос = Новый Запрос;
            Запрос.Текст = "ВЫБРАТЬ
            |    торо_ИерархическиеСтруктурыОР.РодительИерархии КАК РодительОбъекта
            |ИЗ
            |    РегистрСведений.торо_ОбъектыРемонтаГруппы КАК торо_ОбъектыРемонтаГруппы
            |        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.торо_ИерархическиеСтруктурыОР КАК торо_ИерархическиеСтруктурыОР
            |        ПО торо_ОбъектыРемонтаГруппы.ОбъектИерархии = торо_ИерархическиеСтруктурыОР.РодительИерархии
            |            И торо_ОбъектыРемонтаГруппы.СтруктураИерархии = торо_ИерархическиеСтруктурыОР.СтруктураИерархии
            |ГДЕ
            |    торо_ИерархическиеСтруктурыОР.ОбъектИерархии = &ОбъектРемонта";
            
            Запрос.УстановитьПараметр("ОбъектРемонта", ОР.ОтказавшийЭлемент);

            Результат = Запрос.Выполнить();
            Выборка = Результат.Выбрать();
            Если Выборка.Следующий Тогда
                //ОбъектРемонта = Выборка.РодительОбъекта
                ОР.ОбъектРемонта = Выборка.РодительОбъекта;
            Иначе
                Отказ = Истина;
                Прервать;
            КонецЕсли;    
            //ОбъектРемонта = Родитель по запросу    
        Иначе
            Отказ = Истина; // ничего не заполнено, документ не грузим
            Прервать;
        КонецЕсли;    
    Иначе //заполнен родитель
        ОР.ОбъектРемонта = Справочники.торо_ОбъектыРемонта.НайтиПоРеквизиту("ТехНомер", ОР.ОбъектРемонта.КодВТОиР20);
        Если НЕ ЗначениеЗаполнено(ОР.ОтказавшийЭлемент.КодВТОиР20) Тогда // не заполнен подчинённый
            // ОтказавшийЭлемент = ОбъектРемонта
            ОР.ОтказавшийЭлемент = ОР.ОбъектРемонта;
        Иначе
            ОР.ОтказавшийЭлемент = Справочники.торо_ОбъектыРемонта.НайтиПоРеквизиту("ТехНомер", ОР.ОтказавшийЭлемент.КодВТОиР20);
        КонецЕсли;
    КонецЕсли;

КонецЦикла;

Да, сами объекты ремонта мы не грузим, т.к. они уже есть в базе, а ищем по реквизиту.

Код, написанный выше, разумеется не работает, это модель, т.к. вставить его некуда: ПередЗагрузкой и далее в ПКО мы не можем обратиться к Источнику по точке, а в событиях выгрузки нам не доступен приёмник, чтобы искать в нём. При конвертации свойств, мы не можем отказаться от записи объекта в целом при невыполнении каких-либо условий.

Как можно с наименьшей болью выйти из ситуации? Пока на ум приходит только в базе-источнике подгрузить в ещё один реквизит родителей и обработкой в документах поменять. А потом уже грузить готовые документы. С конвертацией знакома мало, к сожалению(
1 belka4_4
 
07.11.18
14:35
Не могу понять это форум вымирает или конвертацию не так много 1Сников знает?..
2 Йохохо
 
07.11.18
14:41
логику надо натянуть на предметную базу. Например местами поменять "не переносим" на "не записываем". Еще надо добавить "И" и "ИЛИ" чтобы понять, что делать с доком в ТЧ которого есть и 1, и 2, и 3, и 4, и закончили упражнение.
3 belka4_4
 
07.11.18
14:56
(2)
По поводу ситуации, когда есть все случаи, предполагалось не записывать документ вовсе, но я думаю стоит поговорить с заказчиком и предложить отказываться только от конкретной строки (вопрос ещё что это за собой потянет).

Я правильно поняла, что предлагаете использовать конвертацию свойств, а потом в ПередЗаписью ПКО проверять, если в ТЧ нет ни одной строки, то Отказ = Истина?
4 Йохохо
 
07.11.18
15:05
(3) в конвертации есть обработчики и на стороне источника и приемника. 1,2,4 решаются _для_строк_ТЧ_ в источнике, 3 в приемнике, просто обработайте док в приемнике после прочтения
После загрузки
Условия возникновения события
Только для платформы V8.
Событие выполняется после прочтения и установки атрибутов объекта из файла, но до его записи в информационную базу. Возможна модификация загруженного объекта.
5 Cyberhawk
 
07.11.18
15:10
Много букв
6 damas
 
07.11.18
15:14
мало когда отвечают(1)
в основном активность на выборе машин) или религиозность полета в космос))
7 Голубушка
 
07.11.18
15:33
"Переносить" это выгружать или загружать?
8 Голубушка
 
07.11.18
15:39
" т.к. вставить его некуда:" , почему вы не хотите вставить его в Алгоритм и вызывать его при выгрузке?
9 Ёпрст
 
07.11.18
15:43
(0)
в ПередВыгрузкой шаритесь по таб части дока на предмет пунктов 1,2,4 и делаем Отказ = Истина, если условие для любой строки тч не проходит

в ПКС переопределяем значение для 1,2

для 3 делаем в После загрузки и там уже Отказ = истина.
усё
10 VS-1976
 
07.11.18
15:45
(8) Да зачем, есть же в ПВД Произвольный алгоритм. Там запрос пишем ( определяемся с выгружаемым списком ), там же есть и указание какой ПКО вызывать. В ПКО прописываем поля и всё...
11 belka4_4
 
07.11.18
15:46
(4)
Получается алгоритм такой:
1.Для 1,2,4 на этапе выгрузки в ПКС подменяю элементы или отказываюсь от переноса строки
2.Для 3 на этапе загрузки нахожу родителя.
3.Перед записью проверять, есть ли строки в табличной части и если нет, то отказываться от записи.

Возможно 3 пункт будет выполняться до 2го.

(7)Повторюсь, что плохо знаю конвертацию, но зачем нам может понадобиться выгрузка без последующей загрузки? В моём понимании переносить = выгрузить из источника и загрузить в приёмник. События, которые между ними даны для удобства обработки данных по пути, нет?
12 Ёпрст
 
07.11.18
15:47
(11) неа.. зачем выгружать объект, если 1,2,4 не выполнено ?
13 Ёпрст
 
07.11.18
15:48
(10) либо так.
14 Голубушка
 
07.11.18
15:48
Я правильно понимаю, что в базе выгрузки все есть, а в базе загрузки нужна проверка на наличие родителя у загружаемого элемента?
15 Йохохо
 
07.11.18
15:51
(11) угу, например в ПКС РодительскогоЭлемента Если Пункт3() Тогда ИмяПКО = "ОбъектыРемонтаПустаяСсылка";
16 belka4_4
 
07.11.18
15:52
(12) У нас же может быть несколько строк. Если в строке ДочернийЭлемент с кодом, то мы грузим документ, просто потом заменяем в этой строке Родительский.

Я думаю, что в итоге решим с заказчиком грузить по принципу: если в строке можно понять ху из ху, то грузим строку и при необходимости меняем данные. Если в итоге в документе 0 строк - не грузим документ.
17 VS-1976
 
07.11.18
15:53
(11) Тебе нужно строки не все выгружать?
В общем в Произвольном алгоритме, можно создать ТаблицуЗначения. В эту таблицу значения можно запихнуть ещё таблицу значения с названием поля к примеру Товары. Это будет табличная часть. В ПКО описываются реквизиты и Табличная часть, в Табличной части так же описываешь какие реквизиты переносить и всё
18 Йохохо
 
07.11.18
15:54
(16) это надо было раньше сделать. И нет ничего страшного выгрузить и не загружать, если данных в источнике недостаточно для принятия решения
19 belka4_4
 
07.11.18
15:55
(14) В базе выгрузки много хлама, всё тащить не надо - только по тем объектам, которые есть в приемнике. Да, бОльшую часть проверок можно сделать в базе выгрузки. Но проверить, а можем ли мы в 3 пункте найти родителя, или его и в приёмнике нет, а это значит, что грузить смысла нет, мы можем только выполнив запрос в приёмнике.
20 VS-1976
 
07.11.18
15:57
(19) В моём варианте можно в источнике всё сразу отфильтровать, и грузить уже готовое...
21 Йохохо
 
07.11.18
15:58
(20) нельзя п3, не путай
22 Голубушка
 
07.11.18
15:59
В этих ПКО ставим галку не создавать если не найден. "Поля для поиска"  Код и КодРодителя , прописываем это  в поля поиска, посмотри в "информация по обработчикам", там хорошо объясняют.

Т.е. при загрузке получаем док с пустыми строками, проверяем это в обработчике "После загрузки" ПКО документа и устанавливаем Отказ= Истина. Документ не загрузится и лишние Дочерние и Родительские тоже.
23 VS-1976
 
07.11.18
16:00
(21) Это ещё с чего? запросом можно всё сопоставить. Ты же выборку делаешь, к примеру из плана обмена, всё сращиваешь и фильтруешь. Почему вдруг нельзя родителя сопоставить с дочерней таблицей?
24 belka4_4
 
07.11.18
16:00
(18) На самом деле документы в основном с одной строкой в табличной части (других по крайней мере не видела), но чисто теоретически могут быть с несколькими, а заказчик хочет быстрее и действовать по принципу "выгрузи что-нибудь", а потом посмотрим будут ли ошибки. Поэтому и появилось это "не грузить" вовсе, но я так не хочу =D.
25 Йохохо
 
07.11.18
16:01
(24) если тебя забесплатно засадят за сверку, что будешь делать? это риторический вопрос
26 Голубушка
 
07.11.18
16:08
1)Родители в базе выгрузки и базе загрузки одни? Но в базе загрузки они не полные так?
2)В базе выгрузки элементы все с родителями ?

Проверки можно организовать и на одной стороне и на другой.
Если у вас можно отсечь неверные документы в базе выгрузки, то напишите ПВД со способом "Произвольный алгоритм", определите выборку выгрузки.
27 belka4_4
 
07.11.18
16:25
(22) Я в принципе кроме документа ничего не создаю - везде стоит не создавать если не найден и не заменять свойства у существующих объектов. Надо только создать документ и подтянуть в него ссылки из уже существующих справочников.
Т.е. все нужные Родительские и Дочерние уже есть.

(25) Сверять будет заказчик. Но вот если что не так, то исправлять мне, а исправлять хуже, чем сразу сделать нормально.
28 belka4_4
 
07.11.18
16:28
(26)
В базе источнике нет информации о том, кто является родителем для элемента в базе приемнике, и в принципе структура справочников разная. В базе-приемнике иерархия зашита в двух регистрах. Поэтому я и думала в крайнем случае данные о родителях в приёмнике загрузить обработкой в источник и отсекать их сразу.
29 Йохохо
 
07.11.18
16:34
проблемточканет
30 belka4_4
 
13.11.18
11:37
Добрый день!
Решение в итоге такое:
В табличной части документа добавила 2 ПКС для родителя и подчинённого примерно следующего вида:

СтруктураПараметров = Новый Структура("ИД, КодРодителя");
СтруктураПараметров.ИД = ОбъектКоллекции.ID;
СтруктураПараметров.КодРодителя = ОбъектКоллекции.ОбъектРемонта.РАЦ_КодВТОиР20;

Значение = ЗначениеВСтрокуВнутр(СтруктураПараметров);


В ПКО в событии ПослеЗагрузки обрабатываю:


ТЧСписокДефектовПараметры = ПараметрыОбъекта["СписокДефектовТабличнаяЧасть"];

Если Не ТЧСписокДефектовПараметры = Неопределено Тогда
    МассивКУдалению = Новый Массив;
    
    //ИндексСтроки = 0;
    Для Каждого Стр Из ТЧСписокДефектовПараметры Цикл
        СтруктураПараметровРодителя = ЗначениеИзСтрокиВнутр(Стр.КодРодителяСтруктура);
        СтруктураПараметровПодчиненного = ЗначениеИзСтрокиВнутр(Стр.КодЭлементаСтруктура);
        
        //Найдем строку в загруженном документе
        СтрокаДефектов = Объект.СписокДефектов.Найти(СтруктураПараметровРодителя.ИД, "ID");
        //СтрокаДефектов = Объект.СписокДефектов[ИндексСтроки]; //Можно было отказаться от структуры и искать строку через индекс, т.к. обработчик перебирает их подряд
        Если СтрокаДефектов = Неопределено Тогда Отказ = Истина; Продолжить; КонецЕсли;
        //Если в строке условие удаления, то добавим строку в массив к удалению
        Если НЕ ЗначениеЗаполнено(СтруктураПараметровРодителя.КодРодителя) Тогда // родитель не заполнен
            Если ЗначениеЗаполнено(СтруктураПараметровПодчиненного.КодЭлемента) Тогда // заполнен подчиненный
                Запрос = Новый Запрос;
                Запрос.Текст = "ВЫБРАТЬ
                |    торо_ИерархическиеСтруктурыОР.РодительИерархии КАК РодительОбъекта
                |ИЗ
                |    РегистрСведений.торо_ОбъектыРемонтаГруппы КАК торо_ОбъектыРемонтаГруппы
                |        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.торо_ИерархическиеСтруктурыОР КАК торо_ИерархическиеСтруктурыОР
                |        ПО (торо_ОбъектыРемонтаГруппы.ОбъектИерархии = торо_ИерархическиеСтруктурыОР.РодительИерархии)
                |            И (торо_ОбъектыРемонтаГруппы.СтруктураИерархии = торо_ИерархическиеСтруктурыОР.СтруктураИерархии)
                |ГДЕ
                |    торо_ИерархическиеСтруктурыОР.ОбъектИерархии = &ОбъектРемонта";
                
                Запрос.УстановитьПараметр("ОбъектРемонта", СтрокаДефектов.ОтказавшийЭлемент);
                
                Результат = Запрос.Выполнить();
                Выборка = Результат.Выбрать();
                Если Выборка.Следующий() Тогда
                    СтрокаДефектов.ОбъектРемонта = Выборка.РодительОбъекта;
                    //Сообщить("Не заполнен родитель, найден по подчинённому");
                Иначе
                    //Сообщить("Не заполнен родитель, не найден по подчинённому");
                    МассивКУдалению.Добавить(СтрокаДефектов);
                КонецЕсли;    
            Иначе
                //Сообщить("Не заполнен родитель, не заполнен подчинённый");
                МассивКУдалению.Добавить(СтрокаДефектов);
            КонецЕсли;
        Иначе //заполнен родитель
            Если НЕ ЗначениеЗаполнено(СтруктураПараметровПодчиненного.КодЭлемента) Тогда // не заполнен подчинённый
                //Сообщить("Заполнен родитель, не заполнен подчинённый");
                СтрокаДефектов.ОтказавшийЭлемент = СтрокаДефектов.ОбъектРемонта;
            Иначе
                //Сообщить("Заполнен родитель, заполнен подчинённый");
            КонецЕсли;
        КонецЕсли;         
        //ИндексСтроки = ИндексСтроки + 1;
    КонецЦикла;
    
    Для Каждого Стр Из МассивКУдалению Цикл
        Объект.СписокДефектов.Удалить(Стр);
    КонецЦикла;
КонецЕсли;


Комментарии "Сообщить" оставила для себя.
31 belka4_4
 
13.11.18
11:38
И проверка там же в ПослеЗагрузки:

Если Объект.СписокДефектов.Количество() = 0 Тогда
    Сообщить("Не грузим документ");
    Отказ = Истина;
КонецЕсли;
Компьютеры — прекрасное средство для решения проблем, которых до их появления не было.