Программа — всплывающий клиент для оповещения и работы с 1С без интерактивного запуска самого 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='\

40 Comments

  1. ekaruk

    Интересная штука.

    На чем написана?

    Можно ли самостоятельно расширять функционал?

    Reply
  2. Kis_s

    (1) ekaruk, Написана на С++ (Microfoft Visual Studio + MFC). Функционал можно расширять до бесконечности — всё содержимое окон формируется в виде html кода в глобальных функциях 1С. Клиент лишь компонует результат вызова функций 1С с шаблоном, следит, когда этот html изменился и нужно всплывать ….. ну и отслеживает клики по управляемым элементам html, чтобы перехватить командные и выполнить определенные действия … ;о) …. например, перейти на вызов другой функции …

    Reply
  3. Kis_s

    (1) ekaruk, Причем функции очень простые, вот, например, страница калькулятора (все они есть в демобазе):

    Функция PopUpКалькулятор(Параметр=»», ПредыдущаяСтрока=»», СтрокаРезультат = «») Экспорт
    Стр = «<img src=’IMGcalc.png’><br><br>»+Символы.ПС;
    
    Если СтрокаРезультат<>»» Тогда
    Стр = Стр + СтрокаРезультат+»<br><br>»;
    КонецЕсли;
    
    Стр = Стр + «Что посчитать: «;
    Стр = Стр + «<input name=’TextCalc’ type=’Text’ border=’3′ value='»+ПредыдущаяСтрока+»‘>»;
    
    //добавляем кнопку OK
    Стр = Стр + «<input id=’Function’ name=’PopUpCalc’ value=’OK’ type=’Button’>»+Символы.ПС;
    
    Стр = Стр + «<br><br><i>Введите любую формулу и нажмите ОК. 1С выполнит вычисление и вернет результат или ошибку.</i>»+Символы.ПС;
    
    Возврат Стр;
    КонецФункции
    
    Функция PopUpCalc(Параметр=»») Экспорт
    ТП = ПараметрВТаблицу(Параметр, 4);
    
    СтрТП = ТП.Найти(«TextCalc»,ТП.Колонки[0].Имя);
    ПредыдущаяСтрока = «»;
    Результат = «»;
    Если СтрТП<>Неопределено Тогда
    ПредыдущаяСтрока = СтрТП[3];
    Попытка
    Результат = Вычислить(СтрТП[3]);
    СтрокаРезультат = «<font color=’#4978af’><b>»+СокрЛП(СтрТП[3])+» = «+СокрЛП(Результат)+»</b></font>»;
    Исключение
    Результат = ОписаниеОшибки();
    СтрокаРезультат = «<font color=’#f97e7e’><b>»+СокрЛП(СтрТП[3])+» = «+СокрЛП(Результат)+»</b></font>»;
    КонецПопытки;
    КонецЕсли;
    
    Возврат PopUpКалькулятор(Параметр=»», ПредыдущаяСтрока, СтрокаРезультат);
    КонецФункции
    

    Показать

    Reply
  4. script

    Скажите, а чем не устраивает родной метод «ПоказатьОповещениеПользователя()» ?

    Reply
  5. kapustinag

    (4) script, Рискну ответить за автора.

    Посмотрите внимательнее приложенные картинки. То, что можно в (0) реализовать, в ПоказатьОповещениеПользователя() и не снилось.

    Reply
  6. Kis_s

    (4) script, Попробую объяснить …

    1. Не требуется интерактивного запуска 1С:Предприятия от пользователя. Все мы прекрасно знаем, что не будет начальство с открытой 1Ской сидеть … да и отмазка «У меня не была программа открыта» делает систему оповещения через «ПоказатьОповещениеПользователя()» не оптимальной идеей ….

    2. У данного клиента размер окна оповещения изменяется пользователем, так что влезает больше информации… и она может быть структурирована!

    3. У данного клиента есть возможность вставлять не одну ссылку, а любое количество полноценных DHTML объектов, включая кнопки, переключатели, поля ввода текста, ссылки, картинки и т.д. Вообщем, хоть полноценный веб-сайт рисуй в окне. Что, кстати, позволяет делать его окна гораздо более интересными с точки зрения эргономики и юзабилити ….

    4. У пользователя есть возможность изменять какие-то значения прямо в окне клиента не отвлекаясь на запуск основного окна 1Ски. Т.е. вносить изменения в базу!

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

    6. Т.к. окно клиента является потомком iExplorer, то прямо в нем можно организовать переход на контекстный поиск по Гуглю или на web-сервер 1С предприятия, если он есть …

    7. Сам по себе клиент, если честно, может работать не только с 1С, но и с любой другой системой, поддерживающей Com соединение ;о). Он полноценный Com-клиент. Может подключаться по стандартам Com, запрашивать у сервера перечень процедур, функций … вызывать их …. если нужно, то и на v7.7 — то он тоже будет работать…

    8. Если проект получит развитие, то вполне возможно держать соединение не с одной базой данных, а с любым их количеством ;о)

    Это навскидку ;о)

    Reply
  7. reddima

    Добрый день,

    интересное решение, но

    ОС Win 7

    попробовал, при запуске приложения вываливается ошибка «Не удалось запустить приложение поскольку его параллельная конфигурация неправильна…».

    Что бы это могло быть?

    Reply
  8. reddima

    И как увязать ее с базой на сервере 1С?

    Reply
  9. anig99

    ООО!!!! Это именно то, что я недавно искал и давно задумал!

    Reply
  10. ruslan0277
    Во время работы пользователь может переходить по ссылкам или выполнять какие-либо действия в окне клиента, но, если при очередном запросе к базе данных html код от текущей функции изменится — окно клиента будет полностью обновлено!

    А почему бы не спрашивать пользователя «Текущие данные формы изменились по таймауту. Обновить или где?». Имхо, принудительно прерывать работу пользователя не есть гуд.

    Очень хорошая и полезная идея.

    ЗЫ Жаль потестировать не могу

    Reply
  11. Kis_s

    (7) reddima, Проект скомпилирован в режиме «Use MFC in a Shared DLL», т.е. использует внешние dll системы, что позволяет существенно уменьшить его размер (исполняемый файл 87 Кб). Обычно этого хватает. Если же библиотек не хватает — выводит эту ошибку. Я бы посоветовал установить пакеты microsoft visual c++ 2008 redistributable * для вашей системы. Они бесплатны и гуглятся в два счета В дальнейшем попробую перекомпилировать проект в режиме «Use MFC in a Static Library» и проблема должна исчезнуть ….

    (8) reddima, В описании есть:

    Открыть блокнотом файл PopUp1C.ini и в нем прописать:

    ;Строка подключения к базе данных

    DB=»File=’F:c++PopUp1CDb’;usr=’Иванов’;pwd=»;»

    (10) ruslan0277, Возможно. Но очень трудно определить, начал ли пользователь менять что-то в окне клиента — придется вешать перехват на все DHTML элементы, а это напряжно. Да еще при учете, что в этом окне принудительно отключен JawaScript … Скорее всего, попробую повесить вопрос при активном и видимом окне клиента …

    (9) anig99, Так пользуйтесь ;о)))

    Reply
  12. ruslan0277

    (11) А если разделить на главная/не главная страница? И соответственно главную обновлять без вопроса, на второстепенных с вопросом.

    Reply
  13. reddima

    (11) Спасибо большое за ответы, по серверу я попробовал указать данные имени сервера и базы данных, но не получилось. Срока была DB=»srvr=’1c82′;Ref=’uat_prof’;usr=’Администратор’;pwd=’12345′;»

    Reply
  14. Kis_s

    (13) reddima, Если в окне клиента пишет «Error: GetIDsOfNames: PopUpIndex (Не найдена функция PopUpIndex) » — 1С говорит, что нет у неё такой, видимой извне, глобальной функции. Следует сделать вот что: В свойствах ОбщийМодуль.PopUp1C установить галочку «Клиент *»… на различных платформах и даже в рамках текущих 8.3 релизов 1С ведет себя по-разному ;о(((

    Если не помогает — скопируйте сюда ошибку из окна клиента. И не забудьте, что вызываемые функции должны быть, и должны быть рабочими!!! Попробуйте вызвать их из любой внешней обработки и посмотрите, что они возвращают.

    PS Правда, тогда могут возникнуть проблемы при другой компоновке ;о(. По-хорошему, функции нужно разделить по модулям НаСервере и НаКлиенте … сделаю попозже …

    Reply
  15. Kis_s

    (12) ruslan0277, Сейчас работа клиента проста и понятна — Есть Текущая глобальная функция 1С, которую он с завидной периодичностью вызывает и её результат выводит в окно …. она может быть изменена согласно логике управляющих команд …. текущей станет другая … как только возвращаемые данные будут отличаться от предыдущего вызова — перерисовываем окно клиента …. логично предположить, что пользователь уже что-то понатыкал в окне клиента … скорее всего, я сделаю так: перехватываем что-нибудь типа WM_LBUTTONDOWN и считаем, что данные окна изменились … тогда при обновлении можно и спросить …. но только не модально, т.к. таймер опроса базы повиснет, а многопоточность использовать не хочется …. Если же разделять на окна, то это уже SDI/MDI приложение получится. Там другие родители у классов и т.д и т.п. … все переписывать …. и нереально усложнять … в целом — нужно переспать с этой мыслью и сделать какое-то элегантное решение …

    Reply
  16. adva

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

    Reply
  17. Kis_s

    (16) adva, наверху ссылка Перейти к публикации

    Reply
  18. reddima

    (14) Спасибо, это помогло, на сервере тоже работает.

    1. И еще, пока ваше приложение заходит в базу, выдается сообщение «Действие не может быть завершено так как программа не отвечает на запросы…» «Переключиться, повторить..».

    2. И если устанавливаю, что каждый раз нужно подключаться к базе (не сохранять постоянным соединение), то на каждый раз запускается новый процесс 1сv8.exe, т.е. получается, что он старый не гасит при выходе из него?

    Reply
  19. Angry

    Идея супер. Реализация хорошо.

    А почему на COM а не на WEB сервисе?

    П.С, Может кто знает аналог на веб сервисах? Штука-то полезная.

    Reply
  20. Kis_s
    Reply
  21. Kis_s

    (19) Angry, Никогда не соединялся программно с Webом 1Са …. если есть примеры реализации с открытым кодом, да еще чтобы можно было вызвать глобальные функции (язык не важен) — с радостью посмотрю … возможно, реализую ….

    Reply
  22. BorovikSV

    (11) А нельзя скомпилировать так, чтобы не приходилось гуглить библиотеки? Борьба с размером исполняемого файла дело конечно благородное, но не за счет же приобретения дополнительных заморочек. Тем более с современным развитием интернета этот аспект почти неактуален.

    Reply
  23. Angry

    (21) Примеры работы с Web сервисами есть на инфостарте. Так же в 8.3 есть и Http сервисы.

    У COM соединения есть большие недостатки: ест память, долго грузится и не уверен на счет лицензий.

    Кроме способа подключения нашел проблемы:

    1) Возврат строкой прост, но мало практичен, не хватает например:

    а) Принудительно показать, даже если данные не изменились

    б) Изменить размер окна, варианты вроде: конкретный размер в px или avto, для того что бы всё убралось

    в) Флажок вроде особо важного, что бы посреди экрана показалось.

    г) Изменить периодичность обновлений

    д) Запрет перезаписи окна, тут может быть вариант, как с аськой, новое уведомление появляется в новом окне, например выше.

    2) Пользователь может утащить окно за край экрана и больше ему «не мешает».

    3) Ява скрипт в странице, вроде прочел отключен, но это удобный инструмент для интерактивных действий.

    4) Снова вспомню аську, если окно просто информационное, то удобней его прятать простым щелчком в любом свободном месте.

    5) Как себя ведет программа если на сервере его грубо выключат?

    6) Заметил, что при завершении программы COM клиент выкинул 1С-ное окно подтверждения.

    Reply
  24. AllexSoft

    классно! как раз подобное надо мне) думал писать уже, а тут вот подарок ))

    ПС: присоединяюсь к комментариям о веб-сервисах.. реально было бы удобнее и проще

    Reply
  25. Kis_s

    (22) BorovikSV, Уже … новая версия именно такая и будет …. получается в сумме около 500 Кб …..

    (23) Angry, Спасибо за идеи …. будем воплощать по мере возможности … Тем более (А ведь никто не сказал!), я лихо промахнулся, и, вместо ComConnector использовал полноценное Com-соединение …. ;о((( …. спать нужно больше ….

    На данный момент новый релиз «в процессе отладки» … есть проблемы с утечкой памяти …. отлавливаю …. как будет готово — выложу.

    Сделано:

    — Нормальный V8*.ComConnector. Без запуска процесса 1С, через нормальное внешнее соединение… V8*.Application пока оставил …

    — Нормальное поведение и отображение OnLine/OffLine без криков об ощибке соединения и т.д….

    — Часы работы, чтобы отцеплялась от базы …

    — 1С обработка для тестирования глобальных процедур с выводом их результата в html и возможностью прямо там покликать по ссылкам …

    — Включаемое самологирование для отладки проблем …

    — Команды Back/Forvard

    — Отслеживание изменений элементов пользователем и вопрос при обновлении…

    — Нормальная работа демобазы на клиент-серверном варианте..

    — Несколько управляющих команд от функций 1Са… (но вот уважаемый Angry набросал еще ;о))))

    — Многое по-мелочи …

    Reply
  26. Angry

    Ещё пожелание:

    Передать в 1С пользователя, домен и компьютер под которым запущен PopUp1C

    Предлагаю использовать для безопасности. Т.к. опознавать пользователя надо, а хранить пароль и логин в ини файле мягко сказать не безопасно, да и в настройке муторно, лучше определение пользователя перевесить на внутренности 1С. А входить в COM под пользователем, который интерактивно запустить 1С не сможет.

    Reply
  27. kns77

    Давно в заявках висит подобное от клиента, никак руки не доходили, надо будет попробовать посмотреть

    Reply
  28. Angry

    Хорошо, клиент сервер теперь работает, по скорости по тестируем.

    Теперь есть проблемы:

    1) Не у всех COM Connector работает, лечится длинными манипуляциями (пока разбираюсь)

    2) Не работает от имени ограниченного пользователя, под админом работает.

    Reply
  29. dj_serega

    Когда будет реализовано через http-сервисы обязательно скачаю =))). COM, имхо, не подходит под данный функционал.

    Особенности http можно найти на инфостарте.

    + скорость работы быстрее

    + можно передать через httpответ HTML страничку

    + вроде как не требует лицензии

    — нужно публиковать базу

    Reply
  30. apxi

    (29) Вот реализованная как сервер, запускается там где лежит база 1С, по http обрабатывает команды и жрет только одну лицензию http://infostart.ru/public/297399/

    Reply
  31. dj_serega

    (30) apxi, Так там окно браузера нужно. А тут программка в трее (что очень удобно). Уже знаю где можно использовать данный функционал.

    Окно в браузере я могу сделать. Сформировать html-страничку не вопрос. А вот что-то похожее на эту публикацию я сделать не смогу, вот и прошу автора.

    Reply
  32. chmv

    Это то о чем я постоянно думаю

    Reply
  33. ruslan0277

    (31)dj_serega, а чем данная форточка не браузер? 🙂

    Reply
  34. dj_serega

    (33) ruslan0277, Ну так браузер это отдельная прога, где «случайно» можно перейти в одноклассники 🙂 А тут не получится если не напрограмить 🙂

    Reply
  35. Asmody

    От этой штуки один шаг до стандартного виндового гаджета (которые как виджеты). Или плитки.

    Reply
  36. StalkerAkella

    (2) Доброго времени. Предвидится ли использование данной программы на Андроиде?

    Reply
  37. dj_serega

    мне чет кажется что разработчик забил на это приложение 🙁

    Reply
  38. Kis_s

    Ребят, сорри, не было в стране …. в ближайшие дни всем отвечу ….

    Reply
  39. dj_serega

    (38) Привет 🙂

    Ну как там? Очень жду продолжения данной разработки 🙂

    Reply
  40. v3rter

    Очень смущает пароль в открытом виде в текстовом файле.

    Reply

Leave a Comment

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