Проверка изменения реквизита при записи документа

Обычная задача — перед записью поймать изменение реквизита (пусть это будет реквизит ВремяНачала)и выполнить некоторое действие.
Раньше оно было совсем просто в процедуре ПередЗаписью

Если Ссылка.ВремяНачала <> Объект.ВремяНачала Тогда
// реквизит изменен - выполняем нужные действия
КонецЕсли

Сейчас такой фокус не пройдет — придется написать чуть побольше кода.

&НаСервере
Функция ИзменениеВРасписании(ВремяНачалаАктуальное)
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| ОказаниеУслуг.ВремяНачала
|ИЗ
| Документ.ОказаниеУслуг КАК ОказаниеУслуг
|ГДЕ
| ОказаниеУслуг.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("Ссылка", Объект.Ссылка);

Результат = Запрос.Выполнить();
Выборка = Результат.Выбрать();

Если Выборка.Следующий() Тогда
ВремяНачалаСохраненное = Выборка.ВремяНачала;
Если ВремяНачалаСохраненное <> ВремяНачалаАктуальное Тогда
Возврат Истина;
КонецЕсли;
КонецЕсли;
Возврат Ложь;
КонецФункции

Ну и используем новую функцию в процедуре ПередЗаписью

&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
Если ИзменениеВРасписании(Объект.ВремяНачала) Тогда
// реквизит изменен - выполняем нужные действия
КонецЕсли;
КонецПроцедуры

Как при записи элемента справочника определить, какие именно реквизиты изменены?

Я
   Михаил Анянов

17.05.12 — 10:01

Как при записи элемента справочника определить, какие именно реквизиты изменены?

Возможно ли это и как реализовать?

  

Партнерская программа EFSOL Oblako

   alextom81

1 — 17.05.12 — 10:02

Через объект метаданных и элемент формы

   Михаил Анянов

2 — 17.05.12 — 10:02

Суть задачи, при изменении только Родителя — никаких проверок при записи не делать, во всех остальных случаях осуществлять ряд проверок.

   Cube

3 — 17.05.12 — 10:03

Если Наименование <> Ссылка.Наименование Тогда

   Сообщить(«Наименование изменено»);

КонецЕсли;

   Reset

4 — 17.05.12 — 10:03

а) Хранить структуру реквизитов до измения

б) Взять предыдущие из БД ПередЗаписью (по ссылке)

   НЕА123

5 — 17.05.12 — 10:04

(3)+1

   Михаил Анянов

6 — 17.05.12 — 10:04

(3) а как пробежаться по всем реквизитам?

   Reset

7 — 17.05.12 — 10:05

(6)

а) Из метаданных

б) Выбрать *

   Cube

8 — 17.05.12 — 10:07

(6) А тебе нужно конкретно знать, что изменено или пофиг?

   Reset

9 — 17.05.12 — 10:09

Да, (8) прав, можно использовать модифицированность, при таковой сравнивать только Родителя (если (2))

   Михаил Анянов

10 — 17.05.12 — 10:10

Для Каждого текРеквизит из СписокРеквизитов Цикл

   Если // а вот как тут проверку написать? Тогда

       Сообщить(«Реквизит » + текРеквизит + » изменен!»);

   КонецЕсли;

КонецЦикла;

   Михаил Анянов

11 — 17.05.12 — 10:11

Забыл:

СписокРеквизитов = ЭтотОбъект.Метаданные().Реквизиты;

   Reset

12 — 17.05.12 — 10:11

(10) Что написать — зависит от того, что находится в СписокРеквизитов

   Михаил Анянов

13 — 17.05.12 — 10:11

Мне нужно определить, что не изменилось ничего кроме родителя

   Михаил Анянов

14 — 17.05.12 — 10:11

Т.е. перебрать все реквизиты надо

   Reset

15 — 17.05.12 — 10:12

(11)

Если Ссылка[текРеквизит.Имя]<>ЭтотОбъект[текРеквизит.Имя]

Хотя меня лично коробит множественное обращение по ссылке

   Reset

16 — 17.05.12 — 10:13

(13) и (14) — взаимоисключающие утверждения

   Maxus43

17 — 17.05.12 — 10:13

(15) запросом вытащить предварительно можно

   Cube

18 — 17.05.12 — 10:13

(13) Фигня какая-то… Информация может храниться в регистрах сведений и/или подчиненных справочниках… Как их проверять будешь?

   Reset

19 — 17.05.12 — 10:13

(16) Поторопился —

   Reset

20 — 17.05.12 — 10:14

(17) Я так и предлагаю :)

   Михаил Анянов

21 — 17.05.12 — 10:14

(16) как же они взаимоисключающие? Мне нужно получить список измененных реквизитов, если он будет состоять только из Родителя — тогда Возврат, иначе — проверки.

   Михаил Анянов

22 — 17.05.12 — 10:15

Интересуют только реквизиты! :)

   Михаил Анянов

23 — 17.05.12 — 10:15

(18) Интересуют только реквизиты самого объекта!

   Михаил Анянов

24 — 17.05.12 — 10:17

(15) ну а иначе никак… либо перед записью в таблицу все реквизиты текущего объекта просто выгружать… В результате обращение к объекту будет одно.

   Михаил Анянов

25 — 17.05.12 — 10:17

Спасибо за советы, сейчас буду мудрить :)

   Reset

26 — 17.05.12 — 10:20

(24) Можно оптимизировать

а) Получить запросом

б) Создать временный объект — копию:

ОбъектДоИзменения=Ссылка.ПолучитьОбъект()

//блабла

    Если ОбъектДоИзменения[текРеквизит.Имя]<>ЭтотОбъект[текРеквизит.Имя]

// Так читабельней и меня меньше коробит ;)

   hhhh

27 — 17.05.12 — 10:22

(26) не, там и так всё в порядке. По ссылке один раз получается объект и дальше уже он используется. То есть временный объект сам создается платформой. Не нужно заморачиваться.

   Maxus43

28 — 17.05.12 — 10:23

(27) некрасиво просто. я за запрос!

   Михаил Анянов

29 — 17.05.12 — 10:37

Всем спасибо большое! Сделал так в модуле ПередЗаписью()

   Если НЕ ЭтоНовый() Тогда

       Запрос = Новый Запрос;

       Запрос.Текст =

           «ВЫБРАТЬ *

           |ИЗ

           |    Справочник.Номенклатура КАК Номенклатура

           |ГДЕ

           |    Номенклатура.Ссылка = &Ссылка»;

       Запрос.УстановитьПараметр(«Ссылка», ЭтотОбъект.Ссылка);

       Результат = Запрос.Выполнить().Выбрать();

       Если Результат.Количество() > 0 Тогда

           Результат.Следующий();

           СписокРеквизитов = ЭтотОбъект.Метаданные().Реквизиты;

           Для Каждого текРеквизит из СписокРеквизитов Цикл

               Если Результат[текРеквизит.Имя] <> ЭтотОбъект[текРеквизит.Имя] Тогда

                   Сообщить(«Реквизит » + текРеквизит + » изменен!»);

               КонецЕсли;

           КонецЦикла;

       КонецЕсли;

   КонецЕсли;

   Михаил Анянов

30 — 17.05.12 — 10:44

Есть один косяк, СписокРеквизитов = ЭтотОбъект.Метаданные().Реквизиты — в список Родитель не попадает, и другие стандартные реквизиты

   Михаил Анянов

31 — 17.05.12 — 10:45

СписокРеквизитов = ЭтотОбъект.Метаданные().СтандартныеРеквизиты;

Вопрос снят :)

   Reset

32 — 17.05.12 — 10:46

(29)(31) Нормально вполне себе, молодца :)

   AAlexandra

33 — 17.05.12 — 10:48

(30) КолонкиИзЗапроса = Запрос.Выполнить().Колонки;

   Alex375

34 — 17.05.12 — 10:48

А тебе надо отследить изменения в объекте при редактировании через форму или при любых изменениях объекта? Просто если через форму, тогда можно проще — завести флаг и его выставлять при изменении реквизитов в форме.

   Михаил Анянов

35 — 17.05.12 — 10:52

(34) при любых, как обработкой, так и обменом

   hhhh

36 — 17.05.12 — 10:53

(31) а чего у вас там постоянно родителя туда-сюда меняют у элементов? Может не стоит такую офигенную проверку устраивать каждый раз, а сделать с родителем так же.

   Михаил Анянов

37 — 17.05.12 — 10:53

(34) тот флаг о котором ты говоришь итак есть стандартно, ЭтотОбъект.Модифицированность()

   Михаил Анянов

38 — 17.05.12 — 10:54

(36) справочник обрабатывается как ручками, так и обработками различными. Если подскажешь как мне определить, что происходит событие смены родителя, то буду благодарен :)

   hhhh

39 — 17.05.12 — 10:57

(38) ну легко:

ТабличноеПоле (TableBox)

ПриСменеТекущегоРодителя (OnCurrentParentChange)

Синтаксис:

ПриСменеТекущегоРодителя()

Описание:

Возникает при изменении текущего родителя в режиме иерархического списка.

   DrShad

40 — 17.05.12 — 11:02

(38) подписку на событие не предлагать?

   Михаил Анянов

41 — 17.05.12 — 11:57

Ага, только рассмотрите еще один момент, помимо родителя я одновременно могу например еще и наименование изменить, и т.п.

  

Михаил Анянов

42 — 17.05.12 — 12:00

(39) — собитие при записи все равно ведь выполнится с кучей проверок внутри?

Определяем модифицированность объекта на сервере.

Задача для примера:

При записи документа «Заказ клиента», если у него при редактировании изменилось значение реквизита «Пометка удаления», нужно выполнить какой-то программный алгоритм. Если значение не изменилось, то алгоритм выполнять не нужно. В общем, цель – определить, изменилось ли значение реквизита «Пометка удаления» перед тем, как документ будет записан.

У управляемой формы есть свойство Модифицированность. Но в данном случае оно вряд ли пригодится, так как пометка удаления может устанавливаться не из формы документа. Дальше приходит на ум использовать метод объекта метаданых «ДокументОбъект» Модифицированность(). Однако в отладчике видно, что даже если ничего не менять в документе, то при записи метод Модифицированность() всё равно принимает значение Истина.

Но выход есть. Отследить и обработать изменение реквизита «Пометка удаления» можно с помощью метода ДополнительныеСвойства. Для этого нам понадобится внести небольшие дополнения в процедуры модуля объекта документа.

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

В процедуре ПередЗаписью() мы сравниваем значение реквизита «Пометка удаления» редактируемого документа с значением, которое записано в базе. Если значения не равны, то записываем признак изменённости в дополнительные свойства, и далее используем его в процедуре ПриЗаписи():

Процедура ПриЗаписи(Отказ)
	
	Если ДополнительныеСвойства.Свойство("ПометкаУдаленияИзменена", Истина) Тогда
		// Произвольная обработка условия...
	КонецЕсли;
	
КонецПроцедуры
Информация о материале
Категория: Программирование 1С

Опубликовано: 12 сентября 2018

Перейти в раздел примеры кода 1С 8.3:

//by telegram t.me/yellow_pad (Жёлтая тетрадь Блог программиста 1C)

Проверить изменение поля регистра сведений ПередЗаписью. В отличие от объектов ссылочного типа, при изменении регистра платформа сперва записывает пустой набор записей, а затем набор записей с данными. Выходит, что в момент записи фиксируемых данных прежних данных в базе уже нет, и сверить новые значения полей не с чем.

Вариант решения — перед записью пустого набора получить запросом текущие данные регистра и закешировать их во временное хранилище, передав во вторую итерацию ссылку на это хранилище (например, через параметр сеанса). БСП: БуферОбмена — кеширование любых данных без передачи адреса хранилища

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

ОбщегоНазначения.СкопироватьВБуферОбмена(Данные);
БуферОбмена = ОбщегоНазначения.СтрокиИзБуфераОбмена();
Данные = БуферОбмена.Данные;

Пример использования механизма — отслеживание изменений полей регистра сведений ПередЗаписью:

Пример кода в 1С 8.3:

Процедура ПередЗаписью(Отказ, Замещение)

   Если ОбменДанными.Загрузка Тогда
       Возврат;
   КонецЕсли;

   ИмяИсточника = ОбщегоНазначения.КонтрольнаяСуммаСтрокой(Новый Структура(«Пользователь, Отборы», ИмяПользователя(), Отбор.Задача.Значение));

   Если ЭтотОбъект.Количество() = 0 Тогда
      ОбщегоНазначения.СкопироватьВБуферОбмена(ПолучитьНачальныеДанные(Отбор.Задача.Значение), ИмяИсточника);
  Иначе
      БуферОбмена = ОбщегоНазначения.СтрокиИзБуфераОбмена();
       Если БуферОбмена.Источник = ИмяИсточника Тогда // новая запись
           НачальныеДанные = БуферОбмена.Данные;
       Иначе
           НачальныеДанные = Неопределено;
       КонецЕсли;

       ТекущаяДата = ТекущаяДата();

       Для Каждого Запись Из ЭтотОбъект Цикл

           ТекНачальныеДанные = ?(НачальныеДанные = Неопределено, Неопределено, НачальныеДанные.Найти(Запись.Задача, «Задача»));

           Если ТекНачальныеДанные = Неопределено Тогда // запись создана
               Запись.ДатаСоздания = ТекущаяДата;
               Продолжить;
           КонецЕсли;

           Если ЗначениеЗаполнено(Запись.Ссылка)
               И НЕ Запись.Ссылка = ТекНачальныеДанные.Ссылка Тогда // получена новая ссылка
               Запись.ДатаПолученияСсылки = ТекущаяДата;
           КонецЕсли;


      КонецЦикла;

       // очистим буфер обмена
       ОбщегоНазначения.СкопироватьВБуферОбмена(Неопределено, ИмяИсточника);
  КонецЕсли;

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

Функция ПолучитьНачальныеДанные(Задачи)

   Запрос = Новый Запрос;
   Запрос.Текст =
    «ВЫБРАТЬ
   |    *
    |ИЗ
    |    РегистрСведений.ЗадачиДляОбмена КАК ЗадачиДляОбмена
   |ГДЕ
    |    ЗадачиДляОбмена.Задача В (&Задачи)»;

   Запрос.УстановитьПараметр(«Задачи», Отбор.Задача.Значение);

   Возврат Запрос.Выполнить().Выгрузить();

КонецФункции

Copyright©, «Программист 1С в г.Минске», 25.06.2021

Перепечатка текста и фотографий разрешена при наличии прямой ссылки на источник

Понравилась статья? Поделить с друзьями:
  • Продажа зелени как бизнес отзывы владельцев форум
  • Производство на дому с легким сбытом малый бизнес
  • Проблемы российской практики планирования бизнеса
  • Проверка компании по инн на сайте налоговой риски
  • Продажа интернет магазина готового бизнеса развод