Кто открыл документ /v7/ Ключевые слова: 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
|