Книга знаний

1С:Предприятие

Кто открыл документ /v7/

Как определить кто блокировал конкретный документ /v7/ Автор статьи:
Последняя редакция №1 от 02.06.06
URL: http://kb.mista.ru/article.php?id=246

Ключевые слова: 1с++, mssql, блокировка документа,Кто открыл 1с документ


Пролог : Для больших 1с приложением когда пользователей больше 50 начинают очень
часто возникать проблемы как узнать кто открыл документ(справочник).
Обычно как всегда все происходит в самый неподходящий момент ( законы Мерфи) :
Клиент звонит менеджеру.Менеджер хочет внести небольшое изменение в счет( сделка
очень важная с хорошим клиентом на хорошую сумму) и обнаруживает что его счет
кто-то заблокировал. клиент висит на телефоне, домумент не открывается,
сделка под угрозой, менеджер в бешенстве
предлагается одно из решений для преодоления столь ужасной картины.

постановка задачи
1. Обеспечить пользователям 1с просто обнаруживать кто блокировал конкретный документ.
2. Сделать невозможным сохранение документа после нахождения в нем свыше
заданного числа минут.


поводом для написания статьи послужило : "ОФФ: Прототип статьи. Решение проблемы файловых блокировок в 1С 7.7"
http://abelov.com/forum/f.php?ak=29369&pg=-1


Решение основана на 1с++. При начале работе 1с программы необходимо загрузить 1с++.
(Кому не нравиться 1с++ можно переписать через ado ).

В глобальном модуле надо добавить :

Функция SQLКтоОткрыл( ТекущЗнач)     Экспорт
   Если ПустоеЗначение(ТекущЗнач) = 1 Тогда Сообщить("Не выбрано значение");return 1; КонецЕсли;
   meta1 = СоздатьОбъект("MetaDataWork");
   rc = СоздатьОбъект("ODBCRecordSet");
   Зн1 = "'" + meta1.ЗначениеВДлиннуюСтрокуБД(ТекущЗнач) + "'";
   Стр_0 = "SELECT who,comp, convert( char,date, 113)  from users_1c where id = " + Зн1;
   Табл_2 = СоздатьОбъект("ТаблицаЗначений");
   Табл_2.НоваяКолонка("Кто","Строка");
   Табл_2.НоваяКолонка("Комр","Строка");
   Табл_2.НоваяКолонка("ДатаВремя","Строка");

   rc.Открыть(Стр_0, 0,0);
   rc.УстТипыКолонок1С("Строка,Строка,Строка");
   Попытка
       rc.ПолучитьРезультатыВ_ТЗ(Табл_2,0 );
       
   Исключение
       Сообщить("не удалось обратиться к users_1c");
       return 0;
   КонецПопытки;
   rc.Закрыть();
   Если Табл_2.КоличествоСтрок() <= 0 Тогда
       Сообщить("Объект никем не занят !!!");
       return 1;
   КонецЕсли;
       
   Стр_1 = сокрЛП(Табл_2.ПолучитьЗначение(1,"Кто"));
   Стр_2 = сокрЛП(Табл_2.ПолучитьЗначение(1,"Комр"));
   Стр_3 = сокрЛП(Табл_2.ПолучитьЗначение(1,"ДатаВремя"));
   Сообщить("" + Стр_1 + " комп " + Стр_2 + " открыл " + Стр_3);
   return 1;
КонецФункции

Функция SQLОткрытьДокумент( Конт)  Экспорт
//create table users_1c
//(
//  id   char (13),
//  who  char (50),
//  comp char (50),
//  date datetime,
//  primary key (id)
//)
   Если Конт.Форма.ТолькоПросмотр() = 1 Тогда
       return 1;
   КонецЕсли;
   
   ТекДок = Конт.ТекущийДокумент();
   Если ПустоеЗначение(ТекДок) = 1 Тогда return 1; КонецЕсли;
   
   //Сообщить("ТекДок " + СокрЛП(ТекДок.НомерДок) + " от " + ТекДок.ДатаДок );
   meta1 = СоздатьОбъект("MetaDataWork");
   rc = СоздатьОбъект("ODBCRecordSet");
   Зн1 = "'" + meta1.ЗначениеВДлиннуюСтрокуБД(ТекДок) + "'";
   Зн2 = "'" + ИмяПользователя() + "'";
   Зн3 = "'" + ИмяКомпьютера() + "'";
   Стр_0 = "insert into users_1c ( id, who, comp, date) " +
   " values ( " + Зн1 + "," + Зн2 + "," + Зн3 + "," + "GETDATE() )";
   СделатьUpdate = 0;
   Попытка
       rc.Выполнить(Стр_0);
   Исключение
       СделатьUpdate = 1;
   КонецПопытки;    
   Если СделатьUpdate = 1 Тогда
       Стр_0 = "update users_1c  set  who = " + Зн2 + ", comp = " + Зн3 + " , date = GETDATE() " +  
       " where id = " + Зн1;
       Попытка
           rc.Выполнить(Стр_0);
       Исключение
           Сообщить("не смогли update ");
       КонецПопытки;    

   КонецЕсли;

   return 1;
КонецФункции    

Функция SQLЗакрытьДокумент( Конт)  Экспорт
   ТекДок = Конт.ТекущийДокумент();
   Если ПустоеЗначение(ТекДок) = 1 Тогда return 1; КонецЕсли;
   
   //Сообщить("ТекДок " + СокрЛП(ТекДок.НомерДок) + " от " + ТекДок.ДатаДок );
   meta1 = СоздатьОбъект("MetaDataWork");
   rc = СоздатьОбъект("ODBCRecordSet");
   Зн1 = "'" + meta1.ЗначениеВДлиннуюСтрокуБД(ТекДок) + "'";
   Стр_0 = "delete  from users_1c where  id = " + Зн1;
   Попытка
       rc.Выполнить(Стр_0);
   Исключение
   КонецПопытки;    
   return 1;

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



В каждом документе(спраовчнике) в модуле ПриОткрытии() необходимо добавить :
   SQLОткрытьДокумент( Контекст);
В каждом документе(спраовчнике) в модуле ПриЗакрытии() необходимо добавить :
   SQLЗакрытьДокумент( Контекст);
На кнопке в журнале документов кнопка. на кнопке функция
SQLКтоОткрыл( ТекущийДокумент)


Вроде все.
Таблица users_1c размещается в базе 1с ( можно разместить и в другой sql бд непринципиально)
параметры sql таблицы :
create table users_1c
(
 id   char (13),
 who  char (50),
 comp char (50),
 date datetime,
 primary key (id)
)
Если таблица будет удалена в результате реструктаризации бд то ее надо востановить в ручном,
полуавтоматическом или автоматическом режиме.

Дальнейшее развитие
1.Доработать ограничение по времени нахождение в документе.
2. Все вышеизложенное можно адаптировать для 1с dbf версии.
3.Решение задачи запретить сохранять док через n минут) после всего вышеизложенного достаточно
тривиальная задача и оставлена в качестве упражнения.
4. Если в этом есть необходимость решение легко адаптируется и для v8.

Эпилог
надеюсь статья была  полезной и Вы не зря потратили свое время дочитав до этих строк

Принимаются любые пожелания,коментарии, предложения, критика и.т.д.
02.06.2006 г.
с уважением Морев Андрей  aka Z1
   



Описание | Рубрикатор | Поиск | ТелепатБот | Захваченные статьи | Установки | Форум
© Станислав Митичкин (Волшебник), 2005-2025 | Mista.ru

Яндекс.Метрика