Имя: Пароль:
1C
 
Как поступить если объект на форме изменен "извне" программно?
0 toypaul
 
гуру
25.08.16
09:12
По логике работы некоторая информация в документе может измениться программно извне - регламентным заданием или еще как. Если попытаться записать такой объект, выдается ошибка, что запись изменена. По правильному если делать, то нужно все это вынести в отдельные регистры/объекты, но это придется лопатить половину конфы.

Возможен ли такой вариант - мы сохраняем данные реквизитов формы, читаем объект из базы в форму (возможно такое?), заменяем сохраненные поля, кроме тех, которые (мы определяем какие) могут меняться программно. Если это проделать, можно будет далее записать объект?
1 Stepa86
 
25.08.16
09:19
Вынести изменяемые поля в отдельные таблицы выглядит попроще, чем предложенный вариант.
2 Cyberhawk
 
25.08.16
09:21
Почему бы просто не обновить данные формы или перечитать объект в форме?
3 toypaul
 
гуру
25.08.16
09:26
(1) вот поверь. нифига не проще. там куча логики на эти поля завязана и отчетов. умрешь переделывать

(2) ну перечитать каждый дурак сможет :) надо еще сохранить то, что пользователь в документе поменял
4 Stepa86
 
25.08.16
09:27
(2) Если изменения произошли через регл. задание, то на какое событие завязаться? Ну и перечитывание сбросит пользовательские изменения.

(0) В этом "извне" на изменяемые объекты вешается блокировка? По идее регл. задание должно посмотреть, что этот объект не используется, залочить его, поменять и разлочить, а клиент просто не сможет открыть форму залоченного объекта
5 toypaul
 
гуру
25.08.16
09:28
(4) при попытке записи. или вообще вручную (по кнопке) если документ не записывается.
6 Cyberhawk
 
25.08.16
09:29
(3) Тогда сохраняй то, что навводил пользователь, в доп. свойства объекта, перечитывай объект чтобы не было оптимистической блокировки при его записи, а в модуле объекта уже возвращай сохраненные в доп. свойствах значения реквизитов
7 toypaul
 
гуру
25.08.16
09:29
(4) скажем так. в регл задании можно проверять. но есть другие места, где ну никак не проверишь - то есть надо менять поле сразу.
8 Cyberhawk
 
25.08.16
09:30
(4) "на какое событие завязаться?" // На то, при котором у него вылезает оптимистическая объектная блокировкка
9 toypaul
 
гуру
25.08.16
09:30
(6) примерно так и хочу сделать
10 Cyberhawk
 
25.08.16
09:31
(9) Затык будет в том, если данные, введенные в форме, преобразуются алгоритмами самой формы и в объект идет уже что-то пережеванное. Тогда придется и в модуле объекта этот алгоритм повторять
11 toypaul
 
гуру
25.08.16
09:32
только вот вопрос ... в каком месте программно поймать эту ошибку
12 toypaul
 
гуру
25.08.16
09:33
можно ли будет сравнить перед записью в форме версию объекта на форму и версию объекта в базе?
13 Cyberhawk
 
25.08.16
09:35
(12) Не лучший вариант - версия объекта (подгруженного в память) кэшируется и не обновляется даже при его изменении
14 Cyberhawk
 
25.08.16
09:37
Хотя вот тут пишут, что можно сравнивать версию данных в памяти и версию данных в БД: https://its.1c.ru/db/pubessence#content:149:hdoc
15 Cyberhawk
 
25.08.16
09:41
По (13) не совсем точно выразился: кэш не обновляется при вызове метода "Прочитать()", а метод "ПолучитьОбъект()" получает данные из объектного кэша, а не из БД
16 toypaul
 
гуру
25.08.16
09:47
"Теперь перед записью разработчик может самостоятельно сравнить версию редактируемых данных и версию данных, хранящихся в базе данных, и реализовать программный алгоритм их объединения и записи."

вроде как раз то, что мне надо
17 Cyberhawk
 
25.08.16
10:00
(16) Только получай версию данных запросом, а не через точку
18 Serg_1960
 
25.08.16
10:04
Имхо: в "общем виде" задача сложно решаемая, а для конкретного документа - легко реализуемая.

Поясню: при интерактивном изменении пользователем элементов формы, связанных с данными, могут быть вызваны действия, которые изменяют другие элементы формы (как связанные с данными так и нет). При программном изменении данных, вышеуказанные действия, потребуется инициализировать программно. Сложно сказал? Тогда короче: программные изменения не равны интерактивным изменениям. Так понятнее?
19 toypaul
 
гуру
25.08.16
10:07
(18) причем тут это? у нас есть объект в форме (перед записью) со всеми своими реквизитам и отработанной логикой и есть объект в базе со своими реквизитами и отработанной программной логикой. я знаю какие реквизиты я беру из объекта базы, а какие из формы. объединяю. перед записью перечитываю объект, объект записывается в базу.

причем тут интерактивные изменения?
20 toypaul
 
гуру
25.08.16
10:09
другой вопрос ... зайду ли я в обработчики перед записью, если версии отличаются.
21 Cyberhawk
 
25.08.16
10:09
(18) Я про это в (10) тоже говорил
22 zak555
 
25.08.16
10:12
пользователь забивает данные в реквизиты формы (не связанные с основным реквизитом)
перечитываем основной реквизит
23 toypaul
 
гуру
25.08.16
10:13
вот опа ... в перед записью не заходит до выдачи сообщения об ошибки. как быть?
24 EugeniaK
 
25.08.16
10:13
(0) Логичнее в фоновом задании проверять, не заблокирован ли объект формой.
И если заблокирован, то программно не менять.
25 toypaul
 
гуру
25.08.16
10:13
(24) уже писал про это
26 Cyberhawk
 
25.08.16
10:17
(23) Попробуй перед записью вызвать метод формы ОбновитьОтображениеДанных
27 Serg_1960
 
25.08.16
10:17
(19) Причем, причем... при том :( Ты почему-то только один вариант обдумал: "микшируем" объект, записываем и закрываем форму. А если пользователь нажал кнопку "Записать" и не собирается закрывать форму, а желает продолжить редактирование? Придётся или "переоткрывать" форму... или то,  о чём я предупреждал.
28 Cyberhawk
 
25.08.16
10:17
(ну или Обновить, если форма обычная, а не управляемая)
29 toypaul
 
гуру
25.08.16
10:17
(23) так не заходит в обработчик. сразу ошибку выдает
30 toypaul
 
гуру
25.08.16
10:18
(27) а в чем проблема-то? ну вызову я обработчики у измененных полей. я же не писал что мне универсальный механизм нужен.
31 Serg_1960
 
25.08.16
10:20
(29) Это на уровне платформы. Обработчики (как и подписки на события) вызываются позднее.
32 Cyberhawk
 
25.08.16
10:30
(29) Блокировка срабатывает до вызова события "ПередЗаписью" _формы_? Тогда тормозной костыль: в обработчике ожидания получать версию объекта в БД. Если отличается от версии, что на клиенте, то вызывать обновление данных формы...
33 Cyberhawk
 
25.08.16
10:31
+(32) Вместо последнего действия можно просто блокировать кнопку записи с подсказкой, чтобы пользователь сам обновил данные формы
34 Serg_1960
 
25.08.16
10:35
"Будь проще и к тебе потянутся люди" :) Сделай кнопку на форме "Обновить" и пусть юзверь жмёт её после получения ошибки.
35 Serg_1960
 
25.08.16
11:01
(уже уходя)

"Возможен ли такой вариант - мы сохраняем данные реквизитов формы[1], читаем объект из базы в форму (возможно такое?)[2], заменяем сохраненные поля, кроме тех, которые (мы определяем какие) могут меняться программно[3]. Если это проделать, можно будет далее записать объект?[4]"

1. Да, можно. Или Скопировать() в переменную, или сохранить в хранилище данных (можно подсмотреть алгоритмы работы версионирования).
2. Да, возможно. Например, в обычных формах достаточно изменить значение ДокументОбъект на объект из базы.
3. Цикл по метаданным объекта и сравнение значений.
4. Да. По сути дела, объект, считанный из базы в форму, изменён программно (модифицирован) и может быть записан как обычно.
36 Cyberhawk
 
25.08.16
13:02
(35) Думаю, в 4 он именно про записью объекта из формы, отсюда и вся боль
37 toypaul
 
гуру
25.08.16
14:16
(35) 1. блин надеялся что простой способ получить копию текущего объекта РеквизитФормыВЗначение будет работать. зараза. не работает если версии отличаются.
38 Torquader
 
25.08.16
14:31
А в чём проблема - создать отдельный объект, и сверить его свойства с теми, которые есть на форме.
Проблема только в том, что мы не знаем, что поменяли мы, а что поменяли из-вне - то есть нужно ещё и версию документа на момент начала изменения хранить.
39 toypaul
 
гуру
25.08.16
15:10
вот такое извращение получилось
40 toypaul
 
гуру
25.08.16
15:10
Процедура ПроверитьВерсиюОбъекта()

    Если ЗначениеЗаполнено(Объект.Ссылка) Тогда
    
        
        Если Объект.ВерсияДанных <> Объект.Ссылка.ПолучитьОбъект().ВерсияДанных Тогда
            
            КопироватьДанныеФормы(Объект,КопияОбъекта);
            
            Прочитать();
            КопияОбъекта.Состояние = Объект.Состояние;
            
            КопироватьДанныеФормы(КопияОбъекта,Объект);
            
        
        КонецЕсли;
    
    КонецЕсли;
    

КонецПроцедуры
41 toypaul
 
гуру
25.08.16
15:10
вызывается по обработчику ожидания, чтобы не жмакать кнопку обновления
42 Cyberhawk
 
25.08.16
21:27
(40) "Если Объект.ВерсияДанных <> Объект.Ссылка.ПолучитьОбъект().ВерсияДанных Тогда"

// Напиши обработку, которая программно перезаписывает объект.
Запусти ее в другом сеансе - твой обработчик ожидания в первом сеансе сработает (ветка Если выполнится).
Сразу после этого запусти обработку из другого сеанса еще раз - в ветку Если уже не попадешь, правильно?
43 Serg_1960
 
25.08.16
21:47
(40) Поставь точку останова и посмотри значения "ВерсияДанных". Увидишь пустую строку в обоих объектах - сделай заключение "Вот опа... как быть?"(цы) - оно не пригодно для твоих целей.
44 Либерал
 
25.08.16
21:52
(38) +1, а проблем никаких и нет - ТС говорит, есть пара реквизитов служебных, которые программно меняются регламентами - их исключить из сравнения, и всё.. (0) - так?
45 Лефмихалыч
 
25.08.16
22:06
(0) блокируй объект перед открытием, чтобы ни кто не мог изменить
46 toypaul
 
гуру
26.08.16
07:49
(43) откуда пустое-то. ничо не пустое. все работает как надо.
47 toypaul
 
гуру
26.08.16
07:58
(42) с чего бы это?

тут проблема вылезла КопироватьДанныеФормы копирует целиком объект. включая версию данных. придется думаю как копировать без версии данных.
48 smartu
 
26.08.16
07:59
нужно убрать изменяемые реквизиты за объект, например в регистры сведений ... объект должен менять пользователь лично и интерактивно.
Регламентное задание и тому подобные действия снимают ответственность за правильность данных в объекте.
49 toypaul
 
гуру
26.08.16
08:01
(48) читаем всю ветку
50 toypaul
 
гуру
26.08.16
08:26
(42) все проверил. все работает. хоть сколько раз в обработке меняй объект. хоть записывай в форме, хоть не записывай.
51 toypaul
 
гуру
26.08.16
08:41
ошизеть. обнаружил глюк обработчика ожидания.

итак.
1. есть пустой обработчик ожидания, который вызывается все время
2. в форме редактируем поле, но никуда с него не уходим. то есть документ пока не отмечается модифицированным.
3. вызывается обработчик и текст, который был введен в поле заменяется старым значением (до изменения)
4. если текст изменить и успеть перейти на другое поле - все нормально. при этом документ становится модифицированным
52 toypaul
 
гуру
26.08.16
08:42
(52) важное замечание - обработчик вызывает серверную процедуру (с контекстом)
53 Cyberhawk
 
26.08.16
10:31
(52) Размести серверную процедуру в общем модуле
54 toypaul
 
гуру
26.08.16
14:23
(53) точно будет работать? или просто попробовать? извращение какое-то. почему такой вариант будет работать?
55 Cyberhawk
 
26.08.16
14:24
(54) Потому что не будет дергаться форма при уходе на сервер
56 Cyberhawk
 
26.08.16
14:25
+(55) в СП почти у каждого обработчика формы в примечании написано "В обработчике данного события нельзя использовать серверные методы формы с директивой компиляции &НаСервере. "
57 Cyberhawk
 
26.08.16
14:25
Вместо общего модуля конечно покатит и модуль формы, но неконтекстный
58 toypaul
 
гуру
26.08.16
14:27
так мне надо чтобы форма дергалась. как иначе-то?
59 Cyberhawk
 
26.08.16
14:34
(58) Так у тебя там в (40) код, который может работать и на клиенте
60 Cyberhawk
 
26.08.16
14:35
+(59) на клиенте + на сервере без контекста формы
61 toypaul
 
гуру
26.08.16
14:43
так как форму не дергать, если главный объект формы меняется?
62 toypaul
 
гуру
26.08.16
14:44
хотя ... щяс уже лень в удаленку лезть. Прочитать и КопироватьДанныеФормы разве клиентские методы?
63 toypaul
 
гуру
26.08.16
14:44
если так, надо попробовать переделать на клиенте
64 Cyberhawk
 
26.08.16
15:16
(62) И клиентские, и серверные. Другое дело, что для изменения объекта формы может потребоваться серверный вызов, но это ты сам проверишь уже
65 hitodom
 
26.08.16
15:23
проще всего добавить кнопочку "Обновить". если пользователь не смог, то назимает ее и может
66 Cyberhawk
 
26.08.16
15:24
(65) Мы тут ищем вариант для самых "взыскательных" пользователей ))
67 toypaul
 
гуру
31.08.16
08:04
переделал обработчик полностью на клиенте. все методы или на клиенте или на сервере без контекста. работает.
68 Cyberhawk
 
31.08.16
09:58
Аминь!
Оптимист верит, что мы живем в лучшем из миров. Пессимист боится, что так оно и есть.