Дружелюбная система компоновки данных (СКД)




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

30 Comments

  1. json

    А чем не устраивает комментарий у отчета?

    По моему скромному мнению, лишние поля в схеме — не есть гут. Все равно все отчеты, которые есть — не подпишешь. Обязательно найдутся пользователи, которым ваш заголовок будет мешать. Самый лучший способ — самодокументируемое название отчета в дереве метаданных. См. Рекомендации по именованию метаданных на ИТС

    Reply
  2. vasilev2015

    (1) yurii_host,

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

    Reply
  3. Synoecium

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

    Reply
  4. papche

    Производительность не пострадает, а вот эстетика — да ))

    Я бы формировал заголовок программно (ПриКомпоновкеРезультата).

    Reply
  5. vasilev2015

    (4) papche,

    Тоже хороший вариант. Но чуть сложнее.

    Reply
  6. Evil Beaver

    (4) papche, если сбросить СтандартнуюОбработку, то фоновое выполнение отчета придется реализовывать руками.

    Reply
  7. Cyberhawk

    (4)

    Я бы формировал заголовок программно (ПриКомпоновкеРезультата)

    Увы, такое не прокатит для подключаемых к БСП отчетов, не имеющих собственной формы отчета

    Reply
  8. starik-2005

    (7) Cyberhawk, кто сказал? На сколько я знаю, метод модуля отчета «ПриКомпоновкеРезультата» выполняется всегда.

    С другой стороны, всегда можно вывести заголовок с помощью макета. Я обычно так и делаю: заголовок из макета, остальное из схемы.

    Reply
  9. papche

    (6) Evil Beaver, а и не надо сбрасывать флаг стандартной обработки без необходимости

    Reply
  10. papche

    (7) Cyberhawk, а Вы попробуйте, удивитесь, но работает и без собственной формы ))

    Вот рабочий код, выводит заголовок с использованием параметра «Период» типа стандартный период

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

    Настройки = КомпоновщикНастроек.ПолучитьНастройки();

    ЗначениеПериода = Настройки.ПараметрыДанных.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных(«Период»)).Значение;

    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;

    Настройки.ПараметрыВывода.НайтиЗначениеПараметра(Новый ПараметрКомпоновкиДанных(«Заголовок»)).Значение =

    «Дата начала: «+Строка(ЗначениеПериода.ДатаНачала) + «. Дата окончания: «+Строка(ЗначениеПериода.ДатаОкончания);

    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);

    ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;

    ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки);

    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;

    ПроцессорВывода.УстановитьДокумент(ДокументРезультат);

    ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных,);

    КонецПроцедуры

    Reply
  11. papche

    (8) starik-2005, а это как, можно поподробнее?

    Reply
  12. SITR-utyos

    (0)

    Пара вопросов:

    1. А что будет если параметр является необязательным и он не установлен?

    2. Необходимо добавить вычисляемое поле в группировку? Думаю, будет не лишним указать, что в этой группировке надо отключить автополе, и выбрать только вычисляемое поле. Подобным образом надо сделать в разделе сортировка

    Reply
  13. echo77

    Добавьте еще скриншот как будет выглядеть отчет с этим заголовком

    Reply
  14. starik-2005

    (11) papche, если исходить из того, что некоторые вместо «Отчет.Сформировать()» используют процессор, то у них не работает. А вот если отчет формируется (можно и в фоне), то метод «ПриКомпоновке…» отрабатывает. В типовой через «Сформировать» все работает.

    Но если вопрос касался макета для заголовка, то тут нужно показывать.

    ЗЫ: вапсче, господа, если о чем-то спрашивайте, то детали иногда важны, Особенно если в сообщении два ответа.

    Reply
  15. zqzq

    Использовал данный подход. Имеет смысл, когда нужно программно формировать заголовок с учетом параметров и т.д.. Кстати, можно в настройках СКД шапку и рамку заголовка убрать, а также шрифт настроить.

    Reply
  16. vasilev2015

    (15) zqzq,

    я рад, что кому-то пригодилось.

    Reply
  17. vasilev2015

    (13) echo77, Добавил.

    Reply
  18. vasilev2015

    (12) SITR-utyos,

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

    2. Да. Спасибо за дополнение.

    Reply
  19. echo77

    (0) Так же советую, рассказать про то, что группировку можно оформить макет оформления — Без оформления, а в самой схеме прописать, что данное поле оформляется минимальной шириной = х, максимальной шириной = х, чтобы не было переносов, так же можно поиграть со шрифтами

    Reply
  20. Alien_job

    Как бы проблема поиска нужного отчета не решилась — все равно надо все отчеты перебирать пока подходящий не найдется

    Reply
  21. vasilev2015

    (19) echo77, спасибо.

    Reply
  22. vasilev2015

    (20) Alien_job, Такой заголовок сделает отчет понятнее пользователю. Количество вопросов уменьшится.

    Reply
  23. starik-2005

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

    Лучше период указывать отдельными полями, чтобы можно было его скопировать, например, в другой отчет (открыли отчет из письма, например, в Excel или ООо). Также и с некоторыми другими полями отбора — контрагент, склад, подразделение. Если каждый раз придется выдирать дату, контрагента или иной полезный параметр данных из центра строки, то это увеличит количество кликов, а количество кликов надо сокращать.

    Reply
  24. Agapov_Stas

    (23) starik-2005, Это все можно запихнуть в стандартный «Заголовок отчета» — который находится на последней закладке в отчете

    делается это все в процедуре «При компановке результата» — кода одна строка.

    зачем изобретать велосипед ?

    Reply
  25. vasilev2015

    (24) Agapov_Stas,

    Использовать вычисляемое поле проще, чем кодировать процедуру «При компоновке результата».

    Кроме этого, можно управлять размером шрифта и прочим оформлением, положением заголовка относительно отчета или его частей.

    Reply
  26. starik-2005

    (24) в стандартный заголовок можно, но муторно. Если дети-программисты пилят отчет и тащат туда две даты (для начала периода и его окончания, а потом пилят КОНЕЦПЕРИОДА(ДатаКонца, День) ) — это одно, тут две даты в двух полях. А если это уже подростки, то они вполне способны вместо двух дат стандартный период юзать — и тут уже одна строка с двумя датами и до кучи временем, что совсем не гут при копировании — приходится выдирать. Ну и отборы в одну строку все падают, а хотелось бы в разные ячейки, чтобы проще выбрать и найти что-либо при анализе отчета. Это уже предполагает, что заголовок будет нарисован.

    (25) по поводу «проще», то я бы лично так не сказал. Процедура в модуле создается одним кликом. Но изменить макет можно только после выполнения компоновки. Т.е. «стандартнаяОбработка = ложь; сформировать(); …работать с макетом…» Этот момент уже не даст пользователю возможности помимо отчета делать что-то еще, ибо тут асинхронности формирования отчета не получается.

    Reply
  27. Vlad_2008
    Reply
  28. vasilev2015

    (27) Vlad_2008,

    Макеты — это стандартно, красиво.

    Это лучший выбор, когда есть время.

    Reply
  29. starik-2005

    (28) если нет времени на макет, но есть время на инфорстарт, то кто-то что-то делает не так.

    Reply
  30. МимохожийОднако

    Комментарии впечатлили больше, чем статья, сработавшая катализатором.

    Reply

Leave a Comment

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