Имя: Пароль:
1C
 
УТ 11.4 некорректное отображение программно созданного док."Установка цен номенклатуры"
,
0 Admin_Net_1C
 
13.05.20
13:45
Добрый день.
Вопрос к гуру УТ 11.4: создаю программно документ "Установка цен номенклатуры"


&НаКлиенте
Процедура Вып()
лФорма = ПолучитьФорму("Документ.УстановкаЦенНоменклатуры.ФормаОбъекта");
лДанныеФормы = лФорма.Объект;
...
ЗаполнитьДокументУстановкаЦенНоменклатурыНаСервере(лДанныеФормы);
...

КопироватьДанныеФормы(лДанныеФормы, лФорма.Объект);
    
лФорма.Открыть();

КонецПроцедуры


В самой процедуре ЗаполнитьДокументУстановкаЦенНоменклатурыНаСервере создаю ДокументОбъект.УстановкаЦенНоменрклатуры и заполняю его табличные части Товары и ВидыЦен. Сам документ НЕ записываю (т.к. нужно открыть заполненную форму нового документа).
После открытия получаю "пустую" форму документа.
Начал разбираться. Выяснил, что на форме документа отображается не сама ТЧ Товары, а реквизит формы ДеревоЦен, который заполняется/перезаполняется с помощью процедур/функций общего модуля УстановкаЦенСервер. И практически у всех экспортных процедур данного модуля первым параметром Форма (УправляемаяФорма), которая из модуля формы передается с помощью ключевого идентификатора ЭтаФорма.

Вопрос: как во внешней обработке "обойти" эту хрень? )) (для тех кто не понял - в обработке я не могу получить ЭтаФорма созданного документа)
1 yzimin
 
13.05.20
14:10
Нужно ещё таблицу НаборыЗначенийДоступа заполнить

Создай документ вручную и посмотри что и как заполняется
2 Admin_Net_1C
 
13.05.20
14:17
(1) заполнение этой табличной части никак не меняет ситуацию Суть проблемы в том, что у меня реквизит ДеревоЦен не заполняется программно, а заполняются только реквизиты и ТЧ объекта. А на форме отображается именно реквизит ДеревоЦен....
3 Admin_Net_1C
 
13.05.20
14:18
(0) неужели никто не заморачивался с программным созданием данного документа и последующим открытием формы вновь созданного (НО не сохраненного!) документа?
4 AAA
 
14.05.20
04:27
Насколько я помню, надо заполнить все зависимые цены. Года полтора назад делал, подзабыл. Могу выслать кусок обработки, но в той УТ были небольшие доработки в части обсуждаемого документа. 1С действительно везде заполняет это дерево, таскает по модулям форму,работает это медленно. Заполнять лучше данные документа и все потом нормально откроется )
5 Admin_Net_1C
 
14.05.20
06:20
(4) буду признателен, если вышлите на почту в профиле
6 AAA
 
14.05.20
08:08
выслал
7 Admin_Net_1C
 
14.05.20
08:25
(6) благодарю.
Еще раз обращаю внимание, что проблема в том, когда программно создаем документ !и не записывая его!, открываем его форму. (При открытии уже записанного документа проблем нет))
8 AAA
 
14.05.20
08:41
Значит надо программно построить дерево, которое строится при открытии документа
А в чем острая необходимость не записывать ?
9 Admin_Net_1C
 
14.05.20
09:26
(8) логично, только для этого нужно переписать практически весь общий модуль УстановкаЦенСервер ну или ваять свой велосипед)
Острая необходимость проистекает из заданного ТЗ )
10 NecroDog
 
14.05.20
10:02
Как вариант костыля - Сделать в этой форме какую-нибудь экспортную клиентскую функцию, которая вызовет сервер и оттуда уже вызовет общие модули и все остальное. Правда эту функцию кто угодно и откуда угодно сможет вызывать..
11 Admin_Net_1C
 
14.05.20
10:58
(10) да, тоже уже думал над этим вариантом. Но другое ограничение ТЗ - документ снимать с поддержки нельзя, про вариант с расширением знаю, но тоже в данном случае не подходит. Собственно сабж был создан для того чтобы помогли подтвердить или опровергнуть мои выводы. Всем спасибо за участие )
12 opus70
 
14.05.20
11:02
(3) вот рабочий код 2 дня назд преносил из 7.7 через OLE
    З = Новый Запрос("ВЫБРАТЬ
                     |    Номенклатура.Ссылка КАК Ссылка,
                     |  Номенклатура.Код Как КодТовара,
                     |  0 Как ЦенаЗакупочная,
                     |  0 Как ЦенаРозничная
                     |ИЗ
                     |    Справочник.Номенклатура КАК Номенклатура
                     |ГДЕ
                     |    Номенклатура.ЭтоГруппа = ЛОЖЬ");
    ТЗнЦены = З.Выполнить().Выгрузить();
    
    _ДатаЦены = ПолучитьРабочуюДату1();
    СпрИст = База77.EvalExpr("СоздатьОбъект(""Справочник.Номенклатура"")");
    СпрИстЦ= База77.EvalExpr("СоздатьОбъект(""Справочник.Цены"")");
    Для каждого СтрТЧ Из ТзнЦены Цикл
        если СпрИст.найтиПоКоду(Число(СтрТЧ.КодТовара))=0 Тогда
            Продолжить;
        конецесли;
        СпрИстЦ.ИспользоватьВладельца(СпрИст.ТекущийЭлемент());
        СпрИстЦ.выбратьЭлементы();
        СпрИстЦ.ИспользоватьДату(База77.EvalExpr("ТекущаяДата()"));
        Пока СпрИстЦ.ПолучитьЭлемент()=1 Цикл
            если СокрЛП(СпрИстЦ.ТипЦен.наименование) ="Закупочные" ТОгда
                СтрТЧ.ЦенаЗакупочная =СпрИстЦ.Цена;
            Иначе
                СтрТЧ.ЦенаРозничная =СпрИстЦ.Цена;
            Конецесли;
        Конеццикла;
    Конеццикла;
    
    _ВидЦены =Справочники.ВидыЦен.НайтиПоНаименованию("Закупочные");
    НовДок = Документы.УстановкаЦенНоменклатуры.СоздатьДокумент();
    НовДок.Дата = ПолучитьРабочуюДату1();
    НовДок.Статус = Перечисления.СтатусыУстановокЦенНоменклатуры.Согласован;
    НовДок.Согласован = Истина;
    НовСтр = НовДок.ВидыЦен.Добавить();
    НовСтр.ВидЦены = _ВидЦены;
    Для каждого СтрТЧ Из  ТзнЦены Цикл
        если СтрТч.ЦенаЗакупочная=0 ТОгда
            Продолжить;
        конецесли;
        НовСтр = НовДок.Товары.Добавить();
        НовСтр.Номенклатура = СтрТЧ.Ссылка;
        НовСтр.Цена = стрТЧ.ЦенаЗакупочная;
        НовСтр.ЦенаИзмененаВручную=Истина;
        НовСтр.ВидЦены = _ВидЦены;
    Конеццикла;
    НовДок.Записать(РежимЗаписиДокумента.Запись);
13 yzimin
 
14.05.20
11:55
(12) Надо без записи документа
14 GreyK
 
14.05.20
12:56
ДанныеФормы2 - это объект документа.

Если ДанныеФормы2.Товары.Количество() > 0 Тогда
    КопироватьДанныеФормы(ДанныеФормы2, Форма2.Объект);
    Отбор = Новый Структура;
    Отбор.Вставить("Ссылка",ДанныеФормы2.ВидыЦен[0].ВидЦены);
    НайденныеСтроки = Форма2.ВыбранныеЦены.НайтиСтроки(Отбор);
    Для Каждого СтрокаВыбранныхЦен Из НайденныеСтроки Цикл
        СтрокаВыбранныхЦен.Выбрана = Истина;
    КонецЦикла;
    //Форма2.ВыбранныеЦеныИзменены = Истина;
    ////НоваяСтрокаЦен = Форма2.Элементы.ДеревоЦен.Загрузить(ДанныеФормы2.Товары.Выгрузить());
    Форма2.Открыть();
    Форма2.ЗаполнитьДокумент();
КонецЕсли;
15 Admin_Net_1C
 
14.05.20
13:05
(15) в конфигурации без изменений процедура ЗаполнитьДокумент() документа УстановкаЦенНоменклатуры.ФормаДокумента не является экспортной...(
А так, да, как уже говорилось в (10),(11) - костыль рабочий )
16 GreyK
 
14.05.20
13:18
(15) Код из (14) работает в Управление торговлей, редакция 11 (11.4.11.55), без изменений конфигурации.
17 GreyK
 
14.05.20
13:20
+(14) Чтобы было понятно что и как.

Форма2 = ПолучитьФорму("Документ.УстановкаЦенНоменклатуры.ФормаОбъекта");
ДанныеФормы2 = Форма2.Объект;
18 Admin_Net_1C
 
14.05.20
13:25
(16) если не сложно посмотрите пожалуйста в УстановкаЦенНоменклатуры.ФормаДокумента модуле формы процедура ЗаполнитьДокумент() объявлена как экспортная?
19 Admin_Net_1C
 
14.05.20
13:30
20 GreyK
 
14.05.20
13:33
(18) Нет, не объявлена. Конфа на замке, расширения стоят только от 1с, в них документы не меняются.
21 Admin_Net_1C
 
14.05.20
13:43
(20) тогда не понятно, как в обработке Вы обращаетесь к этой процедуре:
Форма2.ЗаполнитьДокумент();

???
22 GreyK
 
14.05.20
13:58
(21) Команда выполняется на клиенте, данные заполняются на сервере, всё нормально отрабатывает. Я тоже долго с этим боролся, удачи!
23 Admin_Net_1C
 
14.05.20
14:05
(22) Работает !!!  +100500 тебе в карму добрый человек ))
24 Admin_Net_1C
 
14.05.20
14:16
Теперь вопрос к спецам по самому механизму: в модуле формы УстановкаЦенНоменклатуры.ФормаДокумента процедура ЗаполнитьДокумент() объявлена без ключевого слова Экспорт. Почему в таком случае во внешней обработке отрабатывает код:


лФорма = ПолучитьФорму("Документ.УстановкаЦенНоменклатуры.ФормаОбъекта");
лДанныеФормы = лФорма.Объект;
    
Если ЗаполнитьДокументУстановкаЦенНоменклатурыНаСервере(лДанныеФормы, пРезультат) Тогда
    лФорма.ВыбранныеЦеныИзменены = Истина;
        
    лПараметрыОтбора = Новый Структура;
    лПараметрыОтбора.Вставить("Ссылка", пРезультат);
        
    лМассивНайденных = лФорма.ВыбранныеЦены.НайтиСтроки(лПараметрыОтбора);
    Если лМассивНайденных.Количество() > 0 Тогда
        лМассивНайденных[0].Выбрана = Истина;
    КонецЕсли;
        
    КопироватьДанныеФормы(лДанныеФормы, лФорма.Объект);
    лФорма.Открыть();

    лФорма.ЗаполнитьДокумент();  //--- Почему отрабатывает ЭТОТ КОД ???
        
КонецЕсли;


Во внешней обработке мы находимся вне контекста самого модуля формы (УстановкаЦенНоменклатуры.ФормаДокумента), а не экспортная процедура вызывается. Или я что-то не правильно понимаю? Может кто нибудь объяснить на пальцах )
25 NecroDog
 
14.05.20
14:51
Вспомнил об упоминании такого на ИТС в рекомендациях по безопасности кода. Цитирую:
"Потенциальную угрозу безопасности представляют все серверные процедуры и функции, доступные для вызова из клиентского кода...[далее примеры]
Все процедуры и функции модулей форм объектов с директивами компиляции &НаСервере, &НаСервереБезКонтекста. Вызов таких процедур и функций доступен из контекста клиента после успешного получения формы, даже если эти процедуры и функции не экспортные. Это делает возможным вызов кода в контексте, который не предполагался разработчиком."
26 NecroDog
 
14.05.20
15:03
Еще инфа: похоже, что это баг платформы, который можно использовать, если для конфигурации установлен режим совместимости с 8.3.12.
27 GreyK
 
14.05.20
15:37
(24) Где здесь не соответствие? Для неоткрытых форм нужно объявление Экспорт, для открытых не нужно, иначе ни одна процедура или фукция общего модуля не сможет с открытой формой работать и вся БСП останется не удел :)
Так, что никакой ошибки здесь нет и режим совместимости не причём.
28 NecroDog
 
14.05.20
16:00
(27) Только что проверил. В режиме совместимости 8.3.12 работает вызов серверного метода, а в режиме совместимости 8.3.13 уже не работает. И не важно, открыта эта форма или нет.
29 GreyK
 
14.05.20
16:06
(28) Мы же не серверный метод используем, а клиентский.
30 NecroDog
 
14.05.20
16:21
(29) У ЗаполнитьДокумент() директива компиляции &НаСервере. По крайней мере, в КА2 это так.
31 Klesk
 
14.05.20
16:29
(0) сравнивай консолью админа созданный вручную док и программно
32 GreyK
 
14.05.20
16:42
(30) Лень конфигурацию с поддержки снимать, чтобы попробовать.
Поживем, увидим.
Чтобы обнаруживать ошибки, программист должен иметь ум, которому доставляет удовольствие находить изъяны там, где, казалось, царят красота и совершенство. Фредерик Брукс-младший