Про запросы в СКД




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

9 Comments

  1. TMV

    Суть статьи сводится к строке

    СхемаКомпоновкиДанных.НаборыДанных[0].Запрос = ТекстЗапроса;

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

    Reply
  2. Synoecium

    а какая проблема преодолевалась, написание текста запроса в консоли запросов? По-моему копипастом и заменами текст запроса строится без особых сложностей, а так как в вашем варианте на выполнение отправляется такой же текст запроса, то без какого либо выигрыша в скорости выполнения имеем еще сложности в редактировании текста запроса в конструкторе.

    Reply
  3. alex_bitti

    (2) именно, преодолевалась проблема стационарного запроса в источнике данных, вы в конструкторе делали 70 джоинов? мне сказали коллеги если приходится делать столько джинов значит проблема с архитектурой, да в большинстве случаев это так, но в примере гостовая конфа где с архитектурой работают заслуженные архитекторы всея

    Reply
  4. Synoecium

    (3) так вы программно строите такой же текст запроса, я об этом и написал 🙂 т.е. спрятали косяки под половичок, и все хорошо?)

    Reply
  5. alex_bitti

    (1) именно так, причем я этого не скрывал, скд не считал супер системой никогда, и работаю в ней только при крайней необходимости, еще удивительно что стоимость скачивания 1 sm ставил не я, я сделал просто заметку от части для себя с примером

    Reply
  6. alex_bitti

    (4) ну как бы да в то же время так оказалось значительно проще его стоить, согласитесь, суть каждого запроса сводится к первой сточке, дальше повторение одного и того же 31 раз, редактирование таких запросов просто жесть, и еще не будет очень неприятно, пропустить или копипастом не отредактировать какую нибудь из колонок, просто именно этот отчет уже редактировал 3 раз, поверьте так легче)) ps и не ясно почему в управляемых формах не предусмотрена печать этого документа, думаю многим будет полезен именно этот отчет кто использует суммированый учет рабочего времени

    Reply
  7. Synoecium

    (6) у меня есть опыт построения таких запросов, у нас мы решили эту проблему построением таблицы значений с данными из документа, которая помещается в набор данных-объект СКД (таблица имеет плоскую структуру, т.е. номер дня развернут вниз). Такую таблицу можно кэшировать и строить 1 раз при первом построении.

    Reply
  8. alex_bitti

    (7) отличный вариант, но он сложнее и в реализации и в исполнении при всем уважении, кстати можете поправить если не прав, помещая в таблицу значений, вы отделяете ее от сервера 1С и как бы работа с перебором строк идет «циклами» грубо, а не «запросами» непосредственно в базе через прослойку сервера, то есть буферизируя вы делаете ВЫБРАТЬ *, а потом уже работая с таблицей выбираете нужные данные, когда документ содержит информацию по нескольким сотням сотрудников это может быть значительно медленнее, чем делать непосредственно запрос, даже не оптимальный, так как втроенный оптимизатор запросов исключает повторы получения одинаковых данных, даже на уровне SQL

    Reply
  9. Synoecium

    (8) СКД после выполнения запроса также работает с таблицей с данными в прослойке сервера, тут выигрыш возможен только если включен отбор по сотруднику например, так как запрос будет выбирать меньше записей. В общем же случае вариант с ТЗ выигрывает у запроса по скорости (проверяли на данных порядка тысяч сотрудников)

    Reply

Leave a Comment

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