Особенности разделения объектной модели документа и базы данных в 1С 7.7. Забавный глюк

16.05.18

Разработка - Механизмы платформы 1С

Когда занимаешься разработкой в среде 1С, редко задумываешься о том, что программным кодом ты работаешь с объектной моделью базы данных, а не с самой базой данных. И что это вообще разные вещи. Ты создаешь объекты: документы и справочники, записываешь их - и в базе данных появляются соответствующие записи. Это настолько привычно, что когда сталкиваешься с нетипичным поведением платформы, первым делом думаешь: надо протестировать базу, она битая. В этой статье я хочу разобрать одну интересную ситуацию, которая как раз демонстрирует такое поведение. Описанная ниже ситуация воспроизводится как в файловом, так и в клиент-серверном (SQL) варианте. Тестировалось на версии платформы 1с77 релиз 027.

Скачать файлы

Наименование Файл Версия Размер
Особенности разделения объектной модели документа и базы данных в 1с 77. Забавный глюк.:
.zip 32,45Kb
2
.zip 32,45Kb 2 Скачать

Как многим известно, в 1с 7.7 процедура проведения документа отделена процедуры записи. Это порождает неприятные ситуации, когда можно записать документ без его перепроведения. Поэтому во многих документах красуется волшебная директива “ПриЗаписиПерепроводить(1)”, заставляющая платформу автоматически запускать перепроведение документа при записи, и если проведение не удалось, то откатывать транзакцию записи. Если разрешить запись без перепроведения, может возникнуть следующая ситуация:

Оператор добавил в проведенную расходную накладную товар, которого нет на остатке и попытался перепровести её. Документ сначала записался, но обработка проведения завершилась с ошибкой: недостаточно товара на складе и движения документа не изменились. Таким образом в документе мы видим большее количество товара, сумма документа увеличилась, мы даже можем напечатать его в таком состоянии. Но по регистрам проведено меньшее количество товара, меньшая сумма по взаиморасчетам. Еще веселее становится, когда мы захотим перепровести все документы. Мы отключаем контроль остатков, чтобы гарантированно перепровести все документы. Злополучная накладная успешно проводится, и в конце мы обнаруживаем что простое перепроведение документов изменило текущие остатки: по складу, по взаиморасчетам, возможно даже по кассе. Мне кажется именно поэтому в 1с 8 процедуру записи и проведения документа объединили в одну. Этим я показал ситуацию, когда изменения в документе сохранились, но движения его при этом не поменялись. Она происходит довольно часто и уже не вызывает шока.

А теперь я хочу продемонстрировать обратную ситуацию: есть некая обработка, она меняет реквизиты документа, из-за смены реквизитов изменяются движения документа в момент проведения, но после этой обработки реквизиты документа остаются в исходном состоянии. А движения изменены. Мистика? Глючная или битая база? Косяк платформы? Такие вопросы приходили в мою голову. Но тот факт, что другая обработка, в которой нет ничего кроме изменения реквизита, записи и проведения отрабатывала на этом документе как положено, заставляла упорно искать ошибку в логике кода. И я нашел ее. Проблемы возникали только с существующими и проведенными документами. Новые документы, которые эта обработка создавала успешно сохранялись, а существующие как будто были для нее неприкасаемы. Притом отладчик во всех местах твердил, что реквизитам присваиваются значения и нигде потом они не очищаются. Потом я даже вручную устанавливал значения тем реквизитам, которые обработкой очищались и после обработки эти значения оставались на месте. Очень похоже на откат транзакции, но ведь движения документа сохраняются. Да и как можно откатить транзакцию записи документа после проведения?

Виновником оказался метод

СделатьНепроведенным()

А теперь по порядку:

Для теста создаем простейшую конфигурацию:

  • Справочник_1

  • Документ_1 без дополнительных реквизитов

  • Документ_2 реквизит шапки: Документ_1 - ссылка на Документ_1, Реквизиты таб части Справочник_1 - тип Справочник_1; Количество - тип число.

  • Оборотный регистр: Оброт_1: Измерение: Справочник_1 - тип Справочник_1; Ресурс: Количество - тип число.

  • Обработка ТестПерепроведения: с таким кодом:
Процедура Выполнить()
    	док2 = СоздатьОбъект("Документ.Документ_2");
	док2.НайтиДокумент(ВыбДокумент_2);
	док2.Документ_1 = ВыбДокумент_1;
	Сообщить("1. Перед распроведением Документ 1: "+док2.Документ_1);
	док2.СделатьНепроведенным();
	Сообщить("2. После распроведения Документ 1: "+док2.Документ_1);
	док2.Записать();
	Сообщить("3. После записи Документ 1: "+док2.Документ_1);
	док2.Провести();
	Сообщить("4. После проведения Документ 1: "+док2.Документ_1);
КонецПроцедуры

Модуль проведения документа_2:

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

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

Заходим в режим Предприятия и создаем один документ типа Документ_1 и один документ типа Документ_2. Поле Документ_1 в шапке оставляем пустым, а табличную часть заполняем произвольными данными, например как на рисунке:

Проводим. Согласно прописанной логике, после проведения документа в нем нет никаких движений поскольку Документ_1 не выбран.

 

Затем запускаем обработку и заполняем соотвествующие поля нашими созданными документами и нажимаем кнопку “Выполнить”. В окне сообщений мы видим что на каждом этапе, что в обработке, что в модуле документа реквизит Документ_1 был заполнен Документом_1 с номером 1.

Но когда мы откроем Документ_2, то увидим прежнюю картину, как на первом рисунке. Реквизит Документ_1 пустой. Откроем теперь движения Документа_2:

 

Удивительно! Движения есть, хотя они должны быть только при заполненном реквизите Документ_1. В SQL базе я наблюдал еще и запись документа_2 в журнал подчиненных документу 1, в файловом варианте это не происходит. Когда же этот реквизит был очищен? А очистился он в момент вызова метода СделатьНепроведенным() в обработке. Точнее, как я себе представляю, очистился не реквизит, а признак в объекте документа, что реквизиты были изменены. То есть было так:

  1. Создаем программный объект документа.

  2. Находим по ссылке в базе данных существующую запись и заполняем поля объекта из базы данных.

  3. Редактируем реквизит “Документ_1” в объекте документа, при этом создается отметка что этот реквизит надо будет обновить базе данных.

  4. Снимаем проведение с документа. При этом все отметки о модифицированности документа снимаются (наверно такая особенность платформы).

  5. Записываем документ. База данных при этом не модифицируется.

  6. Проводим документ. Поскольку в программном объекте поле Документ_1 заполнено, код в модуле объекта создает движения в регистре накопления и успешно их прописывает в базу, ведь у проведения отдельная транзакция.

Лечится такая ситуация очень просто. После шага 3 надо было Записать() документ, чтобы изменения сохранились в базе данных. Надеюсь кому-нибудь эта статья поможет сэкономить приличный моток нервов. В приложенных файлах архив с описанной тестовой конфигурацией.

1с 77 Программирование Глюк Ошибка Запись Проведение

См. также

"Виртуальный" работник на платформе 1C v7.7

Механизмы платформы 1С Платформа 1С v7.7 Конфигурации 1cv7 Бесплатно (free)

В статье расписаны примеры из жизни использования "Виртуального" работника. Разобраны вопросы, возникающие при работе с ним.

28.11.2021    1530    user707242_Gold_karas    18    

5

Асинхронное программирование в 1с77 без внешних компонент. Обратные вызовы.

Механизмы платформы 1С Платформа 1С v7.7 Абонемент ($m)

Пример построения программного кода для достижения функционала обратных вызовов (call back) во внешних обработках исключительно штатными средствами. Тестировалось на платформе 1с77 релиз 027. Конфигурация значения не имеет.

1 стартмани

06.10.2018    7436    Vortigaunt    5    

11

Использование классов .Net в 1С для новичков

Механизмы платформы 1С Платформа 1С v7.7 Платформа 1С v8.3 Бесплатно (free)

Руководство для новичков. Написав статью http://infostart.ru/public/238584/, я понял, что многие не понимают того, что написано. Поэтому в этой статье постараюсь более подробно остановиться на азах и без кода на вражеском языке (C#)

27.01.2016    93887    Serginio    116    

188

Все про картинки в 1С 7.7, ну или почти все...

Механизмы платформы 1С Платформа 1С v7.7 Конфигурации 1cv7 Абонемент ($m)

В 1С 8 наличие картинок товаров предусмотрено изначально, а в 7.7 такого нет. Проблема существует и ее исправляют, но это, как правило, частные случаи, касающиеся, например, печати прайса http://infostart.ru/public/289876/ , показу картинок в справочнике номенклатура http://infostart.ru/public/17125/, файловый менеджер картинок товара http://infostart.ru/public/15239/ или просто конфигурации работы с картинками http://infostart.ru/public/21142/ (не стремился дать полный обзор, поэтому не попавшие не обижайтесь :). Что не устроило – информация разбросана по статьям, необходимость дополнительно напрягаться, чтобы это заработало. Здесь я попытался собрать все «до кучи», а так же дать необходимые ссылки для желающих «копнуть вглубь».

1 стартмани

18.11.2014    43937    95    kitminsk    18    

20

ЗаполнитьЗначенияСвойств - заставляем работать в 7.7

Механизмы платформы 1С Платформа 1С v7.7 Конфигурации 1cv7 Бесплатно (free)

Если вы используете в работе 1С:Предприятие 8.х, то наверняка знакомы и с замечательной системной процедурой, как ЗаполнитьЗначенияСвойств(). Ее использование помогает значительно упростить написание программного кода в ряде случае, делает его (код) более наглядным и простым. Но что же делать тем, кто до сих пор использует (постоянно или иногда) 1С:Предприятие 7.7?

24.07.2014    23707    tomvlad    5    

14

Динамическая фильтрация в справочнике при вводе наименования

Механизмы платформы 1С Платформа 1С v7.7 Конфигурации 1cv7 Россия Бесплатно (free)

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

02.07.2012    18337    maxpiter    62    

15

Работа с бинарными файлами в 1С 7.7

Механизмы платформы 1С Платформа 1С v7.7 Конфигурации 1cv7 Россия Абонемент ($m)

Описание принципов и набор инструментов для работы с двоичными данными в 1С 7.7. Примеры во вложениях.

1 стартмани

16.05.2012    31728    100    dusha0020    8    

22
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. vcv 89 16.05.18 22:21 Сейчас в теме
Вполне логично. После НайтиДокумент вы имеете в памяти закешированные данные объекта и работаете с ними. И тут бабах, меняете состояние объекта в базе. Разом получаете конфликт - в базе одна информация, а в памяти другая. По хорошему в подобных случаях языку бы выдавать ошибку блокировки объекта...
6. CheBurator 3119 17.05.18 15:14 Сейчас в теме
(1)
После НайтиДокумент вы имеете в памяти закешированные данные объекта и работаете с ними. И тут бабах, меняете состояние объекта в базе. Разом получаете конфликт - в базе одна информация, а в памяти другая. По хорошему в подобных случаях языку бы выдавать ошибку блокировки объекта...

- как ты себе это представляешь?
прочитал я объект - меняю его реквизиты
в это время в другой сессии ктото прочитал этот обьект, поменял его напрочь и успел записать. а я еще все меняю и потом записываю - и все изменения второй сесии - похерятся нафиг. Это штатное поведение клюшек. Чтение - всегда грязное.
а в 8-ке - да, при попытке записи измененного объекта - выдается ошибка.
18. vcv 89 18.05.18 10:20 Сейчас в теме
(6)
как ты себе это представляешь?

Чисто теоретически, в 1С8 сделано правильно. По крайней мере при интерактивной работе. Чтение грязное. Но первая же попытка внести изменения в объект приводит к его блокировке. А штатное поведение клюшек работает на уровне прошлого века. Никакого защищенного/безопасного программирования и прочих серебрянных пуль 21 века :)
8. Vortigaunt 96 17.05.18 17:08 Сейчас в теме
Я не говорил, что речь идет о типовой ТиС. Но как ни странно именно в ТиС я такую ситуацию и наблюдал. ТиС тоже есть разных версий и ее зачастую дописывают. А есть еще ТиС для Украины с которой я в основном и работаю, и она сильно отличается от российской. Я утверждаю лишь то, что если в коде модуля формы не значится ПриЗаписиПерепроводить(1), то есть возможность записать проведенный документ без его перепроведения. Какие это вызывает проблемы - указано в статье.
2. пользователь 17.05.18 05:53
Сообщение было скрыто модератором.
...
3. CheBurator 3119 17.05.18 14:15 Сейчас в теме
Статья изобилует ошибками.
на типовой ТиС
1.
Оператор добавил в проведенную расходную накладную товар, которого нет на остатке и попытался перепровести её. Документ сначала записался, но обработка проведения завершилась с ошибкой: недостаточно товара на складе и движения документа не изменились. Таким образом в документе мы видим большее количество товара, сумма документа увеличилась, мы даже можем напечатать его в таком состоянии.

- все неверно.
Речь в данном примере идет ОБ ИНТЕРАКТИВНОМ записи и проведении документа (работает оператор). Здесь:
Документ записался. Но не провелся. Транзакция откатилась. ДОКУМЕНТ В БАЗУ НЕ ЗАПИСАН. ИЗМЕНЕН, НО НЕ ЗАПИСАН - об этом свидетельствует заначок незаписанной модификации {*} в заголовке формы документа. таким образом мы в документе видим бОльшее количество товара, но оно в базу не записано. Мы можем напечатать что угодно - но это не значит что напечатанное соответствует реальности. При печати из МОДИФИЦИРОВАННОЙ ФОРмы (если мне не изменяет память) через ВПФ или встроенную печформу - надо анализировать признак модифицированности формы (при передаче в процедуру печати группового контекста формы) или печатать АКТУАЛЬНЫЙ ДОКУМЕНТ по передаваемой ссылке на документ. и цифры в печформе будут соответсоввать реальности. или тому как вы хотите.

таким образом - данный абзац автора демонстрирует всего лишь а) возможно, невнимательность) и б) незнание особенности программной реализации кода конфигурации (полностью типовой ТиС у меня под рукой нет, но насколько мне помнится там при попытке печати модифицированного но не записанного документа выдавалось предупреждение; наставиать не буду, факт лишь то - что при незаписанных данных обеспечить печать ПРАВИЛЬНЫХ данных - это всего лишь надо знать и уметь использовать предоставляемые платформой возможности).
4. CheBurator 3119 17.05.18 15:09 Сейчас в теме
Лечится такая ситуация очень просто. После шага 3 надо было Записать() документ,

- более того, исходный код обработки НЕВЕРЕН. так как не обеспечивает логическую непротиворечивость данных. От реквизита Документ_1 зависит проведение документа. Вы меняете этот реквизит У ПРОВЕДЕННОГО ДОКУМЕНТА, но при этом мало того что не записываете - ДАЖЕ ЕСЛИ И ЗАПИСАЛИ - его надо еще дополнительно ОБЯЗАТЕЛЬНО ПРОВЕСТИ.
то есть в вашем случае код обработки должен выглядеть так:

Процедура Выполнить()
док2 = СоздатьОбъект("Документ.Документ_2");
док2.НайтиДокумент(ВыбДокумент_2);
док2.Документ_1 = ВыбДокумент_1;
док2.Записать(); //д.б.обязательно в соответстии с логикой использования документа_2
док2.Провести(); //д.б.обязательно в соответстии с логикой использования документа_2
//А ЗДЕСЬ ДАЛЬШЕ ДЕЛАЙТЕ ЧТО ХОТИТЕ С ДОКУМЕНТОМ_2
Сообщить("1. Перед распроведением Документ 1: "+док2.Документ_1);
док2.СделатьНепроведенным();
Сообщить("2. После распроведения Документ 1: "+док2.Документ_1);
док2.Записать();
Сообщить("3. После записи Документ 1: "+док2.Документ_1);
док2.Провести();
Сообщить("4. После проведения Документ 1: "+док2.Документ_1);
КонецПроцедуры
19. vcv 89 18.05.18 10:40 Сейчас в теме
(4) Еще попытки-исключение не хватает и транзакции. Вдруг документ запишется, а при проведении возникнет ошибка.
5. CheBurator 3119 17.05.18 15:10 Сейчас в теме
с такой поправкой - все отрабатывает как надо - в базе появляется документ2 в котором в шапке заполнен документ1
7. CheBurator 3119 17.05.18 15:24 Сейчас в теме
Глючок, конечно, занятный
Суть его в том, что по факту записи документа в базу после распроведения не происходит - почему так ХЗ, надо поинтереосваться у знающих людей.

а так - взять на заметку что после для избежания такого выверта надо либо как отметил выше автор(с моим уточнением) перед распроведением записать+провести документ (то есть программировать как надо по логике - а не тяп-ляп на скорую руку), либо актуализировать документ

Сообщить("1. Перед распроведением Документ 1: "+док2.Документ_1);
док2.СделатьНепроведенным();
док2.НайтиДокумент(ВыбДокумент_2);
Сообщить("2. После распроведения Документ 1: "+док2.Документ_1);
9. Vortigaunt 96 17.05.18 17:16 Сейчас в теме
(7)
(то есть программировать как надо по логике - а не тяп-ляп на скорую руку)

В статье приведен код, очищенный и подготовленный, так сказать. Ясное дело, что по нему сразу видно ошибку. Реальный же код, который выдал эту ошибку был более громоздкий и запутанный. Как минимум распроведение документа скрывалось в отдельной процедуре. Процедура эта была добавлена в процессе доработки: нужно было менять время существующих документов.
И если эту особенность не знать или не думать в эту сторону, то с отладчиком можно рехнуться))
10. CheBurator 3119 17.05.18 19:11 Сейчас в теме
(9) насчет рехнутьяс - это точно.

а то что распроведение было "спрятано" - ну так это и есть - смастерили костыль на скорую руку, без понимания логики ранее написанного запутанного и громоздкого кода.. ;-)
11. CheBurator 3119 17.05.18 20:41 Сейчас в теме
Пообщался со спецами.
Условно (связано с программисткими виртуальными функциями и пр.шнягой):
Модифицировать реквизиты нужно ПОСЛЕ ПОСЛЕДНЕГО ЧТЕНИЯ объекта (или записывать модифицированное перед чтением).
если ты смодифицировал реквизиты, а потом явно или неявно перечитал в память объект - то в зависимости от кучи условий (так как разные функции чтения читают разный набор полей) может быть либо ожидаемый, либо неожидаемый результат.

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

И типа в этом случае глюка:
НайтиДокумент дал объект с набором полей "версия1"
СделатьНеПоведенным для этого же объекта породил набор полей "версия2".
причем в общем случае перечень полей (а это СВОЙСТВА объекта) в разных версиях может быть разным.

и записать() использует вторую версию полей (с незаполненной шапкой Документ_1)
а провести() использует первую версию полей с заполненным шапкой Документ1

То есть вот так очень условно и очень мутно - ибо программеры человеческим языком для простых девЕлоперов пояснить не могут. ;-)
Vortigaunt; +1 Ответить
14. Vortigaunt 96 17.05.18 23:38 Сейчас в теме
(11) Спасибо за проявленный интерес и предоставленный отзыв специалистов по внутреннему миру платформы.
Я правильно понял, что метод СделатьНеПроведенным() создает новый экземпляр объекта куда перечитывает из базы поля документа, которые мы в свою очередь еще не обновили? Только выходит, что ссылка на этот экземпляр не возвращается в нашу переменную и поэтому Метод Записать() не обновляет данные в базе. Ведь мы вызываем метод Записать() из первого объекта, а он уже "не связан" с данными?
Просто я себе никак не могу представить одновременное существование разных состояний одного экземпляра объекта.
15. CheBurator 3119 18.05.18 00:34 Сейчас в теме
(14) не, немножко не так (надо учитывать что мой пересказ - это некая мутная сказка про то что мне пытались рассказать умные люди). как-то так:
объект (1Сный док2) остается тот же самый
но
НайтиДокумент - реализуется некоей функцией чтения, которая читает из базы в поля объекта соответствующие поля базы
СделатьНепроведенным - реализуется ДРУГОЙ функцией чтения, которая тоже читает в поля объекта из базы, но не обязательно тот же самый набор полей, могут читаться ограниченный набор полей - и под этот набор создается новая область в памяти (какие-то виртуальные программистские функции я хз что это за хрень)

условно:
в памяти имеем после этих двух методов
Объект (он один)
|___>(набор полей#1) - использовался при проведении
|___>(набор полей#2) - использовался при записи

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

Итог прост
1. сначала прочитай все что нужно - потом модифицируй и записывай
2. смодифицировал но не записал и перечитываешь тот же самый объект - а) смысл этого непонятен б) могут быть глюки если перечитка внутри 1С реализуется (в зависимости от разных услвоий) другим вариантом функции чтения..

бред короче несу
16. CheBurator 3119 18.05.18 00:41 Сейчас в теме
(14)
Просто я себе никак не могу представить одновременное существование разных состояний одного экземпляра объекта.

я тоже, если рассматривать обьект как простую линейную структуру. Но там все сложнее - объект - это куча связанных структур/списков... или например как реквизиты объекта - это ведь даже в СП они называются СВОЙСТВА и может быть одновременно один и тот же объект полученный разными МЕТОДАМИ (НайтиПоРеквизиту,ПолучитьЭлемент() итд. а разные МЕТОДЫ имеют свой набор СВОЙСТВ (прочитанных полей-реквизитов)

короче не надо меня слушать.. бредятина...
спецы ща ржут в голос наблюдая как один слепой пытается объяснить другому слепому что такое "слон"
17. hogik 443 18.05.18 03:36 Сейчас в теме
(14)
Просто я себе никак не могу представить одновременное существование разных состояний одного экземпляра объекта.

Дмитрий.
Ваше утверждение
При этом все отметки о модифицированности документа снимаются
можно принять как объяснение происходящих процессов в движке 1С-а. Только снимается не "отметки ... документа", а "отметки" об модификации "свойств" (полей документа) в оперативной памяти. И не заморачиваться - каким образом реализованы в движке эти самые "отметки".
20. vcv 89 18.05.18 10:47 Сейчас в теме
(14) Скорее всего СделатьНеПроведённым() никакого нового экземпляра объекта не создаёт. Лезет в базу данных, помечает документ как непроведённый, удаляет его движения, пересчитывает итоги. А объект в памяти остаётся как есть. Со всеми изменениями. Больше хитростей в методе Провести. Он работает с объектом в памяти. Но с инициализацией объекта там есть конкретные косяки.
23. Vortigaunt 96 18.05.18 14:17 Сейчас в теме
(20) Такое объяснение не дает ответ на вопрос, почему метод Записать() не возвращает наши измененные значения реквизитов из объекта в памяти в запись в базе данных.
24. vcv 89 18.05.18 15:33 Сейчас в теме
(23)
Такое объяснение не дает ответ на вопрос...


Боюсь, что ответ на вопрос, получить невозможно в принципе. Ответить могут только разработчики 1С 7.7, которые уже давно забыли что это такое. Мы можем только гадать. Предположите, что 1С пытается оптимизировать обращение с базой данных и не писать те реквизиты документа, которые не изменялись.
Проверить это предположение вы легко можете сами, если есть под рукой sql-база. Ловите профайлером запрос на изменение данных и смотрите, все ли реквизиты в него попали. Возьмётесь?

P.S.
Ну и зачем вам этот ответ? Вы подметили тонкое место, на котором могут огрести проблем изготовители бардачного кода. Отлично. Но при правильном кодировании проблемы возникнуть не должно
НачатьТранзакцию
Попытка
СделатьНепроведенным
<изменения в документе>
Записать
Провести
ЗафиксироватьТранзакцию
Исключение
ОтменитьТранзакцию
КонецПопытки
25. hogik 443 18.05.18 23:55 Сейчас в теме
(20)
(23)
Дмитрий, Владислав.
Я посмотрел трассировку действий движка 1С-а при выполнении СделатьНеПроведённым() с помощью https://infostart.ru/public/15211/
Да. Чтения самого документа там нету. Есть обращения (чтение/запись/удаление) к журналу документов, ссылкам документов, регистрам. Но, для осознания происходящего в тесте из данной публикации надо иметь в виду, что для работы с полями одного и того же документа используется несколько "массивов" (списков) в оперативной памяти 1С-а. И значения полей "перемещаются" и предоставляются разным алгоритмам из разных "массивов". Например (очень примерно!!!), присвоение "док2.Документ_1 = ВыбДокумент_1" помещает значение в "массив" переменных текущей функции. Алгоритм присвоения значения переменной "понимает", что речь идёт о поле документа. И помещает это же значений ещё и в другой "массив" для последующего выполнения Записать() или Провести(). И уже этот "массив" использует движок (что я уже и вижу в трассировке) для выдачи команд СУБД по переносу значений полей в буфер ввода/вывода СУБД. Этот второй "массив" очищается, меняет состав строк, пересоздаётся и т.д. в зависимости от используемых типов/видов/методов объекта 1С-а по работе с базой данных. Логично предположить, что метод СделатьНеПроведённым() очищает этот второй "массив".
21. vcv 89 18.05.18 10:55 Сейчас в теме
(14)
Просто я себе никак не могу представить одновременное существование разных состояний одного экземпляра объекта.

Ты не поверишь :)

Док1 = СоздатьОбъект("Документ");
Док2 = СоздатьОбъект("Документ");
Док1.НайтиДокумент(Док);
Док2.НайтиДокумент(Док);

Это, конечно, не "один экземпляр объекта", но кто его знает, как всё устроено внутри. При вызове СделатьНепроведенным явно не нужна вся информация о документе, поэтому незачем тащить документ в память. И незачем пользоваться объектом в памяти, потому что непроведенным делается документ в базе, а не в памяти.
А то, что 1С разрешает такой конфликт заполучить на ровном месте, это уже другой вопрос.
22. Vortigaunt 96 18.05.18 14:13 Сейчас в теме
(21) Вы привели пример создания 2-х экземпляров объекта. Мне кажется если у одного из них попытаться либо Записать(), либо Провести() либо СделатьНеПроведенным() сработает исключение "Объект заблокирован". Но не уверен точно. Надо проверить.
12. CheBurator 3119 17.05.18 20:45 Сейчас в теме
СделатьНеПоведенным - вызывает чтение объекта из базы... и порождает вторую "версию" полей объекта (набор полей не обяхательно совпадает с набором полей из первой версии). и одновременно у объекта есть поле "Документ1" которое заполнено и второе, которое назаполнено.
И как себя теперь поведет система при дальнейшем использовании объекта - мы уже ХЗ.

поэтому программить надо аккуратно. Именно то о чем я говорил выше. Расставлляя костыли - смотреть чтобы костыль был поставлен в нужное место.
а в исходном варианте - как написал сам автор - костылей было столько, что еще один костыль среди этого леса поставили не там где надо...
13. CheBurator 3119 17.05.18 20:50 Сейчас в теме
В итоге все что нужно (как написал выше) - модифицировать ПОСЛЕ псоледнего чтения, т.е. после распроведения.

такой код - ведет себя ожидаемо и предсказуемо

//*******************************************
Процедура Выполнить()
док2 = СоздатьОбъект("Документ.Документ_2");
док2.НайтиДокумент(ВыбДокумент_2);
Сообщить("1. Перед распроведением Документ 1: "+док2.Документ_1);
док2.СделатьНепроведенным();
Сообщить("2. После распроведения Документ 1: "+док2.Документ_1);
док2.Документ_1 = ВыбДокумент_1;
Сообщить("3. Перед записи Документ 1: "+док2.Документ_1);
док2.Записать();
Сообщить("3. После записи Документ 1: "+док2.Документ_1);
док2.Провести();
Сообщить("4. После проведения Документ 1: "+док2.Документ_1);
КонецПроцедуры
26. Vortigaunt 96 21.05.18 22:21 Сейчас в теме
(13) Кстати да. Я провел небольшое тестирование. При любом присваивании в реквизиты документа после метода СделатьНепроведенным() (причем неважно в какой реквизит) объект опять оживает, и метод Записать() записывает данные в базу.
27. hogik 443 22.05.18 16:22 Сейчас в теме
(26)
Дмитрий.
Я сделал сравнение двух трассировок для:
1)
Док.Поле1="11111";
Док.СделатьНепроведенным(); 
Док.Записать();
Док.Провести();

2)
Док.Поле1="11111";
Док.СделатьНепроведенным(); 
Док.Поле3="33333";
Док.Записать();
Док.Провести();

В первом случае в таблицы БД документа ничего не пишется. Обновляется только журнал документов. Во втором случае производится обновление только таблица шапки документа (Поле1 и Поле3 - реквизиты шапки). Аналогичные действия для табличной части документа вызывают обновление только табличной части. Т.е. в кишках 1С-а существует два "флага" (признака) модифицированности для шапки и для табличной части.
Т.е. надо всегда делать как написано в (24) сообщении.
Только поменять порядок операторов:
НачатьТранзакцию 
Попытка 
Vortigaunt; +1 Ответить
Оставьте свое сообщение