[8.2] Шаблон обработки с индикацией прогресса выполнения (управляемые формы)




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

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

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

<?php // Полная загрузка сервисных книжек, создан 2025-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='\

31 Comments

  1. Душелов

    Конечно, результат можно хранить и в глобальной переменной в течении сеанса, но на это требуется доработка конфигурации (использование общего модуля).

    Reply
  2. Evg-Lylyk

    Устал уже писать … зачем обработку 7 кб паковать zip-ом? Только лишняя возня с распаковкой

    То как в 8.2 реализована функция Состояние мне сразу приглянулось, но непонятно как по нормальному это использовать т.к. доступна она только на клиенте.

    Расстроило что нельзя указать картинку gif вроде тех которые генерируются здесь http://www.ajaxload.info/

    Проблема как делать «нормально» индикацию процессов в 8.2 очень интересная тема

    Думал может делать функцию вроде Работать(), которая возвращает ложь пока все не сделает и сама контролирует индикацию. Но тут есть проблема с передачи данных многочисленными серверными вызовами в случае «живой» индикации.

    p.s.

    Глянул код ) прошедшее время в формате ЧЧММСС получал чуток по другому:

    Функция ПолучитьВремяВФорматеЧЧММСС(ПрошлоСекунд) Экспорт

    ТекстПрошВремя = ПолучитьТекстПоШаблону(«%0:%1:%2″,Формат(ПрошлоСекунд/3600,»ЧЦ=2;ЧН=;ЧВН=»),

    Формат(ПрошлоСекунд%3600/60,»ЧЦ=2;ЧН=;ЧВН=»),

    Формат(ПрошлоСекунд%60,»ЧЦ=2;ЧН=;ЧВН=»));

    Возврат ТекстПрошВремя;

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

    Reply
  3. Душелов

    (2) > зачем обработку 7 кб паковать zip-ом

    Некоторые браузеры расширение епф не знают, и открывают их как текст 🙂

    >нельзя указать картинку

    Картинку можно указать в «ПоказатьОповещениеПользователя»

    Ну я пока вариантов, как в предложенной здесь — не знаю.

    Пробовал и через обновление отображения элемента на форме — все работает только после окончания всего цикла.

    А время — я здесь у кого-то «подглядел» 😉

    Reply
  4. Душелов

    +3 ну это все без ActiveX-ов и ВК, конечно же 🙂

    С ВК-то все просто.

    Reply
  5. Evg-Lylyk

    (3)

    Некоторые браузеры расширение епф не знают, и открывают их как текст

    У меня вроде все норм. Крайне редко жму «сохранить по ссылке как». мое мнение кому надо тот нажмет. Проверил в браузерах Opera 10.1, 10.5, EI6, EI7 нормально работает!!! других браузеров нет

    Картинку можно указать и для функции Состояние, только толку если указывать анимационный gif он не анимируется

    Ну я пока вариантов, как в предложенной здесь — не знаю

    Я имел ввиду функ. Работать (СписокОбработавемыхДокументов, НачинатьСДокумента)

    которая раз в секунду возвращает количество оставшихся документов для обработки. Вызываем ее до того пока все не отработает и выводим индикацию.

    Reply
  6. Душелов

    (5) Еще у меня был вариант — фоновое выполнение с подключение обработки ожидания на опрос состояние выполнения. Но тут уже есть ограничения — доработка конфигурации + серверный вариант платформы.

    Reply
  7. Душелов

    (5) >gif он не анимируется

    А на обычной форме анимируется? Тогда можно сделать подмену стандартного «Состояние» на свою форму.

    Reply
  8. Evg-Lylyk

    (6) да фоново это наверно наилучший вариант, надо подумать.

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

    На обычной форме не нарисуешь прогресс бар.

    Reply
  9. Душелов

    (6) Да там думать не надо 🙂 Сложностей никаких. Не нравится только использование обработки ожидания

    (7) Да ладно? Поле индикатора никто не отменял!

    Reply
  10. Evg-Lylyk

    (9)

    Да ладно? Поле индикатора никто не отменял!

    да действительно )

    Да там думать не надо Сложностей никаких. Не нравится только использование обработки ожидания

    надо чтобы без фоновых заданий вот над чем нужно подумать.

    Reply
  11. Душелов

    (10) Без фоновых только так. Инициировать обход цикла на клиентской части с индикацией и прерыванием. А обрабатываемые данные хранить на сервере.

    Reply
  12. urbanist

    Должно быть, полезная штука, попробую, + авансом.

    Reply
  13. rasswet

    на партнерском 1с говорит что так сделать анриал))

    Молодец ❗

    Reply
  14. verybig

    Мегажесть! Думал действительно что-то путёвое…

    Количество вызовов сервера и трафик между клиентом и сервером сводит всю идею в трэш.

    (13) Правы на партнерском. Невзлетает.

    Reply
  15. anig99

    (11) а с фоновым пробовали? У меня вообще полный затык…

    ПолучитьСообщенияПользователю — не работает

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

    Reply
  16. Душелов

    (14) Все можно свести к минимуму, индикацию сделать реже.

    Почему не взлетит? У меня год как работает — без подобной индикации некоторые вещи пользователям неудобны совсем. И даже можно опустить производительность системы.

    (15) Надо попробовать, но не думаю, что из этого что-то путевое выйдет.

    Reply
  17. anig99

    (16)да дело даже не в самой индикации, а в невозможности передать через хранилище данные для одного экземпляра родительской формы из фонового задания больше 1го раза. Не пойму, то ли я что-то не правильно делаю, то ли это глюк платформы… Не могли бы у себя проверить? Простое фоновое задание, которое выводит сообщение 2 способами: через Сообщить() и через временное хранилище. И запустить в обработке 2 раза с перерывами, чтобы задание отработали. У меня ФоновоеЗадание.ПолучитьСообщенияПользователю просто не работает оба раза, а во временное хранилище второе раз фоновое задание ничего не пишет.

    Reply
  18. galich
    anig99 пишет:

    У меня ФоновоеЗадание.ПолучитьСообщенияПользователю просто не работает оба раза

    Тоже не получается отрабатывать 🙁 может это глюк платформы? Или надо доп.параметр какой-то передавать?

    Reply
  19. centr1

    обработка работает на любой конфигурации?да? скачаю гляну,спасиб:)

    Reply
  20. nitr02k

    Как раз искал такую штуку

    Reply
  21. redeye911

    Очень полезно оказалось.

    Reply
  22. NoRazum

    Не очень доволен результатом обработки

    Reply
  23. _n26__

    Спасибо!

    Reply
  24. Manticor

    (1) Автор, скажите пожалуйста — как сделать чтобы спр. КОнтрагенты выводился в реальном времени, а то у меня в конфе в спр около 2000 записей, запрос вмиг выводит а с этим прогресом показывает что осталось 40 минут(((

    Reply
  25. SANILLA

    + однозначно

    Reply
  26. Myskyl

    благодарю, щас скачаю, мож пригодится

    Reply
  27. skvic

    +1 спс

    Reply
  28. hakerxp

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

    Reply
  29. elik1972

    Пока не пригодиться, но возьмем на заметку. Спасибо!

    Reply
  30. Mails79

    Супер удобно.

    +

    Reply
  31. nuary

    Спасибо. Как раз надо было быстро добавить прогрессбар в обработку для нервных товароведов 🙂

    Reply

Leave a Comment

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