[Обучаловка] Преимущества класса «Перехватчик» внешней компоненты «1С++»




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

70 Comments

  1. Утюг

    Отчего-то не исполняется в классе функция Событие_ПриЗаписи().

    Reply
  2. marsohod

    Во многих типовых есть глобальная функция глПроверкаРазрешенияРедактирования(Контекст), которая вызывается из ПриОткрытии()

    1С++ вещь хорошая, только приведенный пример использования кажется не очень удачным…

    Reply
  3. Утюг

    (1) Не работала на 1с++ 3.0.1.22. Скачал 3.2.1.0 — заработало.

    Reply
  4. artbear

    (2) Это не выход — 1) т.к данную функцию нужно вставлять в собственные документы

    2) не во всех типовых, если не ошибаюсь, она есть.

    А мой Перехватчик работает независимо от кода конфы 🙂

    (3) Странно, от версии 1С++ данный код не должен зависеть.

    Reply
  5. artbear

    (0) ИМХО небольшая неточность

    если штатный обработчик (в модуле формы документа) вернет СтатусВозврата(0), т.е. будет установлен запрет записи, то этот запрет не сработает 🙁

    Исправить нужно так:

    Функция Событие_ПриЗаписи() Экспорт

    Иначе

    Перехватчик = СоздатьОбъект(«Перехватчик»);

    Рез = Перехватчик.ВыполнитьОригинальноеСобытиеГК(КонтФормы,»ПриЗаписи»); // ДОБАВИЛ Рез =

    КонецЕсли;

    Возврат Рез;

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

    ЗЫ хотя, может быть, я уже и забыл собственную реализацию Перехватчика 🙂

    Reply
  6. Утюг

    (4) Попробовал 2.5.0.7 — тоже не работает.

    Reply
  7. venger

    (6) Лучше брать свежую сборку…..

    Reply
  8. venger

    (5) Все верно, поправил. Правда стоит в штатных предопределенных писать так:


    СтатусВозврата(0);

    Возврат;

    Так как код в штатной предопределенной после «СтатусВозврата(0);», если не будет команды выхода из процедуры «Возврат;», — выполнится.

    Но это уже к 1С++ отношения не имеет — это штатные вещи;-)

    Reply
  9. gucci76

    А как запретить проводить документ подобным способом? Допустим кадрам можно создавать документ, а проводить нельзя.

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

    Reply
  10. gucci76

    Я так понял это ответ на мой вопрос: «Исключение составляют только предопределенные процедуры модуля документа, такие как «ОбработкаПроведения» или «ОбработкаУдаленияПроведения». Их отличие только в том, что вызываются они системой, как при интерактивных действиях, так и при программной инициации этих событий. »

    т.е. никак!

    Reply
  11. venger

    (10) Нет — можно, счас напишу пример, немного терпения;-)

    Reply
  12. gucci76

    Жду!

    Держу мышку над плюсиком 🙂

    Reply
  13. venger

    (12) Я просто немного усложнил и отредактировал условие проверки авторства документов в статье (еще и раскрасить надо было), в связи с тем, что а вдруг пользователи в системе не определены совсем. Получилось громоздко, но прикольно;-)

    З.Ы. Чтобы увидеть изменения нужно жмакнуть «Очистить кеш публикации (beta)» справа в меню

    Reply
  14. gucci76

    что то не получается с перехватом ПриЗаписи, а про ОбработкаПроведения ваще не видно перехватчика.

    Reply
  15. venger

    (14) А вот как ловить «ОбработкуПроведения»:

    Сначала в глобальный модуль в процедуру «ПриНачалеРаботыСистемы()» после кода включения перехвата еще надо дописать код включения перехвата событий модуля документа для всех видов доков:

    Для Сч=1 По Метаданные.Документ() Цикл
    Перехватчик.СнятьПерехватСобытийПроведенияДокумента(СокрЛП(Метаданные.Документ(Сч).Идентификатор));
    Перехватчик.ПерехватитьСобытияПроведенияДокумента(СокрЛП(Метаданные.Документ(Сч).Идентификатор),ПерехватчикСобытийГМ);
    КонецЦикла;
    

    А потом в класс перехвата событий дописать такую функцию:

    Функция Событие_ОбработкаПроведения(КонтДока, ДопПарам) Экспорт
    Сообщить(«Ловим: ОбработкаПроведения»);
    Рез=1;
    Если КонтДока.ГрупповаяОбработка()<=0 Тогда
    Если (1=1) Тогда // Какое-то условие
    Рез=0;
    Предупреждение(«Проводить этот документ Вам запрещено»,5);
    КонецЕсли;
    КонецЕсли;
    Если Рез=1 Тогда
    Перехватчик = СоздатьОбъект(«Перехватчик»);
    Рез = Перехватчик.ВыполнитьОригинальноеСобытиеГК(КонтДока,»ОбработкаПроведения»,ДопПарам);
    КонецЕсли;
    Возврат Рез;
    КонецФункции
    

    Показать

    Reply
  16. venger

    (14) +15, Что-то плохо отобразился код включения перехвата проведения, повторю так:


    Для Сч=1 По Метаданные.Документ() Цикл

    Перехватчик.СнятьПерехватСобытийПроведенияДокумента(СокрЛП(Метаданные.Документ(Сч).Идентификатор));

    Перехватчик.ПерехватитьСобытияПроведенияДокумента(СокрЛП(Метаданные.Документ(Сч).Идентификатор),ПерехватчикСобытийГМ);

    КонецЦикла;
    Reply
  17. venger

    (14) +16, Тоже обрезается, а если просто текстом:

    Для Сч=1 По Метаданные.Документ() Цикл

    Перехватчик.СнятьПерехватСобытийПроведенияДокумента(СокрЛП(Метаданные.Документ(Сч).Идентификатор));

    Перехватчик.ПерехватитьСобытияПроведенияДокумента(СокрЛП(Метаданные.Документ(Сч).Идентификатор),ПерехватчикСобытийГМ);

    КонецЦикла;

    Reply
  18. venger

    (14) +17, Да что такое, хорошо, попробуем так:

    Для Сч=1 По Метаданные.Документ() Цикл
    Перехватчик.СнятьПерехватСобытийПроведенияДокумента(
    СокрЛП(Метаданные.Документ(Сч).Идентификатор));
    Перехватчик.ПерехватитьСобытияПроведенияДокумента(
    СокрЛП(Метаданные.Документ(Сч).Идентификатор),ПерехватчикСобытийГМ);
    КонецЦикла;
    
    Reply
  19. gucci76

    Перехватчик.СнятьПерехватСобытийПроведенияДокумента(СокрЛП(Метаданные.Документ(Сч).Идентификатор));

    {Глобальный модуль(1142)}: Поле агрегатного объекта не обнаружено (СнятьПерехватСобытийПроведенияДокумента)

    😥 😥 😥

    Reply
  20. venger

    (14) Итого, все по порядку, после действий проделанных в статье, чтобы включить перехват проведения, надо в глобальный модуль в процедуру «ПриНачалеРаботыСистемы()» после кода включения перехвата еще дописать код включения перехвата событий модуля документа для всех видов доков:

    Для Сч=1 По Метаданные.Документ() Цикл
    Перехватчик.СнятьПерехватСобытийПроведенияДокумента(
    СокрЛП(Метаданные.Документ(Сч).Идентификатор));
    Перехватчик.ПерехватитьСобытияПроведенияДокумента(
    СокрЛП(Метаданные.Документ(Сч).Идентификатор),ПерехватчикСобытийГМ);
    КонецЦикла;
    

    После чего, в классе-обработке перехвата событий дописать такую процедуру:

    Функция Событие_ОбработкаПроведения(КонтДока, ДопПарам) Экспорт
    Сообщить(«Ловим: ОбработкаПроведения»);
    Рез=1;
    Если КонтДока.ГрупповаяОбработка()<=0 Тогда
    Если (1=1) Тогда // Какое-то условие
    Рез=0;
    Предупреждение(«Проводить этот документ Вам запрещено»,5);
    КонецЕсли;
    КонецЕсли;
    Если Рез=1 Тогда
    Перехватчик = СоздатьОбъект(«Перехватчик»);
    Рез = Перехватчик.ВыполнитьОригинальноеСобытиеГК(КонтДока,»ОбработкаПроведения»,ДопПарам);
    КонецЕсли;
    Возврат Рез;
    КонецФункции
    

    Показать

    Соответственно, при проведении какого-либо документа Вы увидите сообщение «Ловим: ОбработкаПроведения». Если да, то все Ок.

    Только надо учесть, что проверка на авторство при проведении бессмысленна, так как автор сменился при записи, которое всегда перед проведением произойдет. И еще, при программном проведении документа (групповая обработка документов какая-нибудь) это событие тоже будет отлавливаться…

    Reply
  21. venger

    (19) Вы понимаете, что я в комментах привожу код который надо дописать, к коду в статье?

    Reply
  22. gucci76

    Вот что у меня в глобальнике:

    ЗагрузитьВнешнююКомпоненту(«1CPP.dll»);

    НастройкиВК = СоздатьОбъект(«УправлениеНастройками»);

    НастройкиВК.Установить(«ПерехватитьСобытияГК»,1);

    ПерехватчикСобытийГМ = СоздатьОбъект(«КлассПерехватСобытий»);

    Перехватчик = СоздатьОбъект(«Перехватчик»);

    Перехватчик.ПерехватитьСобытияГлобальногоМодуля(ПерехватчикСобытийГМ);

    Для Сч=1 По Метаданные.Документ() Цикл

    Перехватчик.СнятьПерехватСобытийПроведенияДокумента(

    СокрЛП(Метаданные.Документ(Сч).Идентификатор));

    Перехватчик.ПерехватитьСобытияПроведенияДокумента(

    СокрЛП(Метаданные.Документ(Сч).Идентификатор),ПерехватчикСобытийГМ);

    КонецЦикла;

    Reply
  23. gucci76

    Правильно?

    Reply
  24. venger

    (22) В глобальнике все верно

    Reply
  25. gucci76

    Перехватчик.СнятьПерехватСобытийПроведенияДокумента(СокрЛП(Метаданные.Документ(Сч).Идентификатор));

    {Глобальный модуль(1142)}: Поле агрегатного объекта не обнаружено (СнятьПерехватСобытийПроведенияДокумента)

    осталась ошибка в глобальнике

    Reply
  26. venger

    (23) Идем далее, в обработках (объявление классов и сам класс) что?

    Reply
  27. venger

    (25) У Вас версия ВК свежая?

    Reply
  28. gucci76

    ВК скачал по ссылке выше:

    http://www.1cpp.ru/images/3/32/Icpp-latest.rar

    Reply
  29. gucci76

    (26) в глобальнике выдает ошибку. до обрбаотки не доходил.

    Reply
  30. venger

    (28) А скиньте md’шку в почту, адрес скинул в личке…

    Reply
  31. gucci76

    ВРУ!

    Скачать скачал, но стояла старая. Ща проверю

    Reply
  32. venger

    (30) Там еще нюанс может быть при смене версий компонент, с какой-то версии изменен порядок чтения и хранения настроек ВК в реестре, если что, то говорите, будем разбираться…

    Reply
  33. gucci76

    Спасибо заработало.

    Плюсую!!!!!

    Reply
  34. venger

    (33) Пожалуста, кстати, если еще подождете (несколько дней, плюс-минус), то я как раз дописываю новую подсистему, в которой в том числе и отлов «ОбработкиПроведения» ловится и можно будет посмотреть на реальном примере, там еще кое-что интересное будет, но не буду все рассказывать, а то не интересно будет;-)

    Reply
  35. Ёпрст

    Я б всё же, для начала, все классы делал внешними.

    Гораздо проще изменять и тестить.

    А уж только потом, в мд встраивал.

    Reply
  36. venger

    (35) А внешние файлы чем предлагаешь редактировать — не блокнотом же?

    Reply
  37. Арчибальд

    (36) Ну ты сказал 😀

    В одноэсине меню файл-открыть

    А потом Текст-Текст модуля

    Reply
  38. venger

    (35), +36, Или имеется ввиду внешние отчеты/обработки?

    Reply
  39. venger

    (37) Н-да, туплю;-)

    Reply
  40. Ish_2

    Мда… «Всё равно 7.7 не брошу , потому что он хороший».

    Не стал ты нашим.

    За стойкость +1.

    Reply
  41. venger

    (40) Не, просто, как говорится:


    Пока гром не грянет – мужик не перекрестится.

    Вот и я, пока не приперло, откладываю углубленное изучение снеговика, тем более лето, жара, после работы на море и т.д. и т.п.;-)

    Reply
  42. SirYozha

    Спасибо за ликбез, классная вещь!

    Только пришлось добавить одну строку в глобальном модуле, чтобы заработало — необходимо сначала включить настройку ПерехватитьСобытияГК:

    НастройкиВК = СоздатьОбъект(«УправлениеНастройками»);

    НастройкиВК.Включить(«ПерехватитьСобытияГК»);

    НастройкиВК.Установить(«ПерехватитьСобытияГК»,1);

    ПерехватчикСобытийГМ = СоздатьОбъект(«КлассПерехватСобытий»);

    Перехватчик = СоздатьОбъект(«Перехватчик»);

    Перехватчик.ПерехватитьСобытияГлобальногоМодуля(ПерехватчикСобытийГМ);

    Reply
  43. SirYozha

    Reply
  44. Ish_2

    (41) Понял в чем дело. Слушай как надо :

    Утром — море , вечером — снеговик.

    Идеальный распорядок для взрослого мужчины.

    Reply
  45. venger

    (42) Установить в =1 и включить ведь одно и тоже…

    Reply
  46. venger

    (44) Я пробовал утром бегать на море, но не долго это продолжалось;-) А вечером, после обеда в квартиру солнце светит через окна и жара такая в квартире, что только после 8-ми вечера можно находится;-)

    Reply
  47. JohnyDeath

    ПолуОФФ

    По-хорошему, надо б еще ТурбоБЛ сразу включать:

    НастройкиВК.Установить(«EnableTurboBL»,1);
    Reply
  48. venger

    (47) Это для отлова событий FormEx, насколько я понимаю?

    Reply
  49. artbear

    (47) 1) ТурбоБЛ — реальное ускорение работы 1С

    2) с помощью ТурбоБЛ можно обращаться к методам группового контекста — типа КонтФормы.Печать()

    ЗЫ без ТурбоБЛ не мыслю работы с 1С++ 🙂

    Reply
  50. anton.fly7

    Скажите, а обработку defcls и обработки самих классов можно как то хранить не в самой конфиге, а внешними?

    Reply
  51. venger

    (50) Конечно, тут описание: http://www.script-coding.info/1cpp.html

    Reply
  52. anton.fly7

    (51) в мануале http://www.script-coding.info/1cpp.html не нашел, а есть ли перехват события ПослеОбработкиПроведения ?

    Reply
  53. venger

    (52)

    в мануале http://www.script-coding.info/1cpp.html не нашел

    Вы что — издеваетесь? Там черным по серому описывается как организовать все во внешних файлах;-)))

    Reply
  54. anton.fly7

    (53) я имел ввиду событие ПослеОбработкиПроведения

    Reply
  55. venger

    (54) После нет, есть до. Тут в предидущих комментах описано как или в мануале к перехватчику — ссылка в статье…

    Reply
  56. venger

    (33),(54) А вот, как и обещал в 34-м посте, новая подсистема, которая и событие «ОбработкаПроведения» ловит, в том числе:

    Универсальная подсистема «Подписи/согласования документов»

    http://infostart.ru/public/73774/

    Reply
  57. fastwriter

    Плюсанул. Статьи, подобные этой, кроме всего прочего, способствуют профессиональному росту широких масс 1ц-программистов. Спасибо авторам.

    Reply
  58. Борода

    (47) (49) я правильно понял, что по умолчанию ускорение модулей отключено ? 😮

    (0) растолкуйте параметры при перехвате ошибок исполнения и как его правильно подключить. Что-то не взлетает… 🙁

    Reply
  59. nicxxx

    Если грузится еще turbomd.dll, то ее надо грузить до 1С++, иначе — не отлавливается событие ПриЗаписи

    Reply
  60. artbear

    (59) Это ты откуда взял? какая версия turbomd.dll у тебя?

    Reply
  61. nicxxx

    версия turbomd — 1.0.1.1

    Reply
  62. artbear

    (61) это старая версия. Иди на форум 1cpp.ru, раздел 1С++, ТурбоМД и прочие, в верхних прикрепленных ветках есть спец.ветка.

    ЗЫ нужна версия 1.0.0.1 (обрати внимание на номер, это верно) от 2006 года.

    Reply
  63. nicxxx

    а, ну я уже обратил внимание 🙂 а почему он меньше в 4 раза стал?

    Reply
  64. nll.jojo

    Плюсанул

    Reply
  65. simply1

    Тем, кто до сих пор поддерживает 7.7 — описание очень актуально и доходчиво!

    Автору — спасибо!

    ИХМО, переменная «Док» — лишняя и зря занимает память.

    Если убедились, что это документ, то «КонтФормы.ТекущийДокумент()» будет достаточно.

    Reply
  66. vadimlp77

    не понял как при перехвате проведения отменить само проведение. Подскажите кто нить, плиз

    у меня вот такое

    Функция Событие_ОбработкаПроведения(Конт,ДопПараметр) Экспорт

    Сообщить(«ОбработкаПроведения»);

    Рез = ПолучитьПравоДоступаКОбъекту(Конт.ТекущийДокумент(), «ПроведениеДокумента»);

    Если Рез=1 Тогда

    Возврат Перехватчик.ВыполнитьОригинальноеСобытиеГК(Конт, «ОбработкаПроведения», ДопПараметр);

    КонецЕсли;

    КонецФункции // гл

    что дописать чтобы по условию можно было не проводить док ?

    Reply
  67. vadimlp77

    подскажите плиз

    как в обработке события «ПриОткрытии» определить какая конкретно форма открывается, я имею в виду, что у справочника может быть несколько форм. Мне нужно видеть какая форма открывается. Спасибо.

    Reply
  68. artbear

    (66) vadimlp77,

    Верни 0 в своей функции Событие_ОбработкаПроведения

    и документ не проведется.

    Reply
  69. vadimlp77

    (68) artbear, спасибо, уже разобрался по обоим вопросам

    Reply
  70. Alex_1066

    Спасибо за статью — понятно и доходчиво и отдельное спасибо всем за комменты…

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *