Универсальное регламентное задание




Принцип обмена данными из 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='\

15 Comments

  1. Ёпрст

    Хреново, что на 8.1 работать не будет, там внешние обработки не создать на сервере..

    Reply
  2. nixel

    (1) Ёпрст, тут еще формы управляемые. в любом случае работать не будет =)

    Вопрос к автору: от чего отталкивались? от БСПшной подсистемы с вырезанием лишнего? или своя разработка?

    Reply
  3. Ilyabaykov

    (2) nixel, разработка своя, собственно задача была — повесить на регламент внешнюю обработку, в БСП, честно говоря, даже не посмотрел, только после Вашего комментария заглянул туда.

    Reply
  4. ZhokhovM

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

    Reply
  5. DoctorRoza

    Туманное описание, зато звучит очень интригующе! Опишите детально, что в сф-нике, пример обработки, как будет работать в серверном и файловом варианте.

    Reply
  6. Ilyabaykov

    (4) Maxim2012, Обновил, добавил простейшую обработку. Так-же добавил ее текст в картинки

    Reply
  7. Ilyabaykov

    (5) DoctorRoza, эм… что именно туманно? добавил скрины

    Reply
  8. aspirator23

    Очень знакомо. Делал подобное, но правда дальше управления внешними обработками не дошел.

    Здесь конечно более универсально.

    Reply
  9. fuxic

    Заставить решать эту задачу с помощью этого функционала для меня было легче и проще, чем экспортировать из БСП дополнительные отчеты и обработки.

    Err:

    1. выполнить задание в форме — выдавать сообщение о необходимости записать объект, поскольку метод работает по ссылке

    2. Залания <> Задания — везде бяка

    3. при настройке периода обновление строки представления не происходит

    тестирую дальше

    Reply
  10. fuxic

    1. АТ_ПоследнееУспешноеВыполениеРеглЗаданий — Выполение?

    2. регистр АТ_РезультатВыполненияРегламентныхЗаданий — заменить основную форму

    Reply
  11. fuxic

    Отбор = НаборЗаписей.Отбор.Найти(«РегламентноеЗадание»);

    Отбор.Использование = ИСТИНА;

    Отбор.ВидСравнения = ВидСравнения.Равно;

    Отбор.Значение = Задание;

    Зачем «найти»? я перфекционист походу 🙁

    Отбор.РегламентноеЗадание.Установить(Задание);

    Reply
  12. Ilyabaykov

    (11) fuxic, так автоподстановка работает :D, по остальным — спасибо, поправлю обновлю. Ещё в форме элемента справочника «НоваяСтрока.ИмяПараметра = Реквизит.Синоним;» на «НоваяСтрока.ИмяПараметра = Реквизит.Имя;» поменять надо, тоже сделаю.

    Reply
  13. MK

    На тестовой базе все ок было (правда переделал под себя многое), а вот на рабочей сразу пара багов вылезла:

    1. Неправильно работает отбор заданий к выполнению — если задание ни разу не выполнялось, в отбор оно не попадает. Вместо

                           |ГДЕ
    | РегламентныеЗадания.Активное
    | И НЕ ПоследнееУспешноеВыполнение.Выполняется
    

    нужно использовать что-то вроде

                           |ГДЕ
    | РегламентныеЗадания.Активное
    | И НЕ ЕСТЬNULL(ПоследнееУспешноеВыполнение.Выполняется,ЛОЖЬ)
    

    2. Определение необходимости выполнения задания — тоже не так работает, назначил задание на однократное выполнение каждый день (каждый день; с 7:00:00 один раз в день) — выполняется с 7:00 ежеминутно. Причина — в этой строке:

     НеобходимоВыполнитьЗадание = Расписание.ТребуетсяВыполнение(,,ВыборкаЗапроса.ДатаПоследнегоВыполнения);

    Не используется второй параметр — ДатаНачалаПоследнегоЗапуска, а при такой настройке расписания как у меня, он нужен. Я обошелся изменением этой строки на такую:

     НеобходимоВыполнитьЗадание = Расписание.ТребуетсяВыполнение(,ВыборкаЗапроса.ДатаПоследнегоВыполнения,ВыборкаЗапроса.ДатаПоследнегоВыполнения);

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

    А вообще идея и реализация мне нравится!

    Reply
  14. Ilyabaykov

    (13) MK, Спасибо, действительно, признак выполнения добавил в последний момент и как следует не оттестировал. Исправил, выложил исправленную версию.

    Reply
  15. TeMochkiN

    Удобная вещь. У самого всё руки не доходили это сделать xD

    Reply

Leave a Comment

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