Панель избранного 1.05




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

35 Comments

  1. German

    Конечно красиво .. но немного не понял смысла… Самое удобное это вроде Операции->

    Reply
  2. Totoro

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

    Потом планирую добавить справочник или дерево «Шаблоны» (с ограничением на права пользователей). И некоторые пользователи смогут выбирать доступные команды только от туда.

    Reply
  3. Serj1C

    +. Очень удобная обработка!

    Reply
  4. Totoro

    Изменения 1.02:

    1) Сохранение настроек (избранное, внешние файлы) в файл — закладка «Настройки»

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

    3) Исправлены ошибки

    Reply
  5. Yashazz

    Красиво, но… В 8.2, насколько понимаю, это уже будет встроено в платформу.

    Reply
  6. Шёпот теней

    ну…блин и медленная….воооООооооот…

    Reply
  7. Totoro

    (6) Что совсем? Или только в основном при открытии закладки метаданных или обновляемых каталогов? Над этим я думаю как оптимизировать.

    Reply
  8. Шёпот теней

    (7) …ОсОбеннО при открытии… ага, надо оптимизировать… тем более есть примеры… воооООоооотИвооОообще….

    Reply
  9. Шёпот теней

    поздравляю… за ДЕСЯТКУ ушло… с успехом вас…. воооООООоооот….

    Reply
  10. RailMen

    Хорошая идея, интересная реализация.

    Но чего — то еще хочется, эдакого

    Reply
  11. Evg-Lylyk

    Много сделано, а описание скудновато.

    (7) «думаю как оптимизировать» Самый простоя способ оптимизировать это не делать лишнего, зачем получать все дерево метаданных если пользователь его не видит. Можно получать элементы ветки дерева только перед разворачиванием, а один элемент добавлять сразу (события ПередСворачиванием, ПередРазворачиванием).

    Есть ошибка с перетаскиваниям если группу вернего уровня перенести в принадлежащий ей нижний то бесконечная рекурсия (т.к. рекурсивно добавляются элементы содержащиеся в группе) и программа вылетает. Сталкивался с этим у себя, потому сразу проверил учтено или нет и нашел. 🙂

    Reply
  12. Evg-Lylyk

    (11)+ «Самый простой способ оптимизировать» сорри самый действенный, а еще когда делается перенос копирование через кнопку Ctrl элемент почемуто просто переносится, а не копируется.

    Reply
  13. Evg-Lylyk

    «стоит ли…делать эту обработку не зависимой от конфигурации» ИМХО стоит подсистема эту неудобно нужно накатывать на конфигурацию, а это сложнее и не всегда приемлимо. Я бы даже не глянул обработку если бы она была подсистемой. Вон пример подсистема «инструменты разработчика» супер весчь, а пользовал крайне редко т.к. не буду же я ее накатывать на рабочую базу (ошибок и так хватает). А еще допустим у меня 10 клиентов мне что им всем ставить подсистему O_o.

    Reply
  14. Totoro

    (11) Чтение метаданных только при разворачивании/сворачивании ветки не пойдет. Не будет работать фильтр по подсистемам или по наименованию. Склоняюсь сделать сохранение кэша полного дерева метаданных в настройках (с возможностью обновления вручную по кнопке). Т.ч. тормозить будет только при первом заполнении дерева (основной тормоз — обход метаданных и чтение их имен). Хотя можно скомбинировать этот способ с выше указанным (если первый раз накладывается фильтр).

    За ошибку перетаскивания спасибо, разберусь 🙂

    Сейчас доделываю закладку полнотекстового поиска и с учетом ее работы буду решать проблему с метаданными.

    Описание уже делаю …

    Reply
  15. O-Planet

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

    Reply
  16. Totoro

    (15) Я понимаю, что лучше делать это при открытии ветви нужных метаданных. Но, для поиска в метаданных по подстроке или наложении фильтра по подсистемам необходимо иметь полное дерево метаданных. Да и для определения права просмотра (и соотв. вывода на экран) объекта метаданных тоже. А пользователь должен видеть только доступные для него объекты и ветви.

    Для нормальной работы с метаданными есть Ei. Да и честно говоря подождать 2-5 секунд после каждого обновления на УПП не большая потеря 🙂 Сейчас уже оптимизировал открытие формы (подчистил функции инициализации) и открытие метаданных (подсистемы будут считываться только при необходимости). У меня в файловом варианте оптимизированный алгоритм выполняется за 1-2 секунды на УПП (4 пень 3 ГГц). Но чтение метаданных тоолько при открытии узла точно не буду делать по вышеуказанным причинам.

    Reply
  17. logarifm

    Честно говоря я что-то не до конца понял, а смысл этой обработке в чем заключается? В чем его фишка?

    Reply
  18. Totoro

    Изменения 1.03:

    1) Сделал краткое описание обработки.

    2) Оптимизирован код.

    3) Добавлена страница полнотекстового поиска.

    (17) См. (2).

    Reply
  19. Totoro

    Изменения 1.03.11:

    1) Исправил конвертацию сохраненных настроек (Статистика и Избранное) старой версии обработки

    Reply
  20. jeg

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

    Reply
  21. PRoman

    Зауважааааал! 🙂

    время потрачено с толком.

    Буду пользовать.

    Reply
  22. Totoro

    Изменения 1.04:

    1) для каждой команды можно задавать указать свои параметры (ссылочные и простые типы), к которым можно обращаться в коде действий через переменную-структуру «пиПараметры».

    2) доделал фильтр по метаданным для полнотекстового поиска.

    Reply
  23. IronDemon

    Переименуй функцию ПолучитьФильтрИзображений(), используется в УТ

    Reply
  24. Totoro

    (23) Хорошо.

    Reply
  25. IronDemon

    Можно ли хранить настройки в ИБ а не во внешних файлах?

    Reply
  26. Totoro

    (25) Да. Доступные места хранения:

    1) Справочник «Сохраненные настройки» — в типовых БУ, ЗУП, может еще и в других (функции формы СохранитьНастройкиВСправочник/ЗагрузитьНастройкиИзСправочник­а)

    2) Стандартный способ через СохранитьЗначение/ВосстановитьЗначение

    Могу, если надо, по аналогии добавить сохранение в типовой регистр сведений СохраненныеНастройки (использовался раньше).

    Место сохранения настроек задается в реквизите ТипХраненияНастроек либо в конце модуля обработки, либо при её программном создании до открытия формы. По умолчанию задан тип «Файл». Если указать пустую строку, то при открытии обработки будет производиться попытка поиска места возможного хранения настроек (сначала попытка прочитать/записать настройки из справочника, затем из файла, затем стандартное сохранение).

    Reply
  27. dim85

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

    Reply
  28. Totoro

    Изменения 1.05:

    1) Добавлено сохранение в регистр сведений типовой конфигурации «СохраненныеНастройки» — тип «Регистр»

    2) Возможно открытие обработки без изменения конфигурации через табло командой: ВнешниеОбработки.ПолучитьФорму(«C:FavoritePane81.epf»,,,»Файл»).Показать(), где вместо C:FavoritePane81.epf указывается путь к внешней обработке, а вместо «Файл» можно указать место хранения настроек обработки («Справочник, «Регистр», «Файл», «Стандартно», «»). Если пропустить этот параметр (т.е. команда будет ВнешниеОбработки.ПолучитьФорму(«C:FavoritePane81.epf»).Показать()), то будет использованно место по умолчанию из модуля обработки — «Файл»).

    3) Можно отключать автозаполнение каталогов сразу с подкаталогами (удобно когда добавляется дерево корня диска из которого нужно заполнять автоматически только некоторые каталоги)

    4) При открытии страницы «Разное» внешние обработки раскрываются.

    5) Исправил (23)

    Reply
  29. Multik

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

    Reply
  30. Nickon

    Неплохая вещь. Надо принять на вооружение и пользоваться ее возможностями.

    Reply
  31. evgea

    Сконвертировал обработку в 8.2. Теперь при свертывании левой панели, правая панель превращается в узкую полоску. Видимо с привязками не все в порядке

    Reply
  32. evgea

    Сконвертировал обработку в 8.2. Теперь при свертывании левой панели, правая панель превращается в узкую полоску. Видимо с привязками не все в порядке

    Reply
  33. evgea

    Сконвертировал обработку в 8.2. Теперь при свертывании левой панели, правая панель превращается в узкую полоску. Видимо с привязками не все в порядке

    Reply
  34. adhocprog

    Классная обработка!

    Reply
  35. user1286096

    Спасибо!. Актуально до сих пор в УПП 1.3., ЗУП 2.5 и т.п

    Добавил строчку в форме ЧистыйКонтекст, т.к. не открывались внешние отчеты из справочника «внешние обработки»

    Процедура пиОткрытьВнешнийОтчет(СсылкаИлиИмяФайла)
    
    ЭтоФайл = (ТипЗнч(СсылкаИлиИмяФайла) = Тип(«Строка»));
    
    Попытка
    
    Если ЭтоФайл Тогда
    ИмяФайла = СсылкаИлиИмяФайла;
    Иначе
    ИмяФайла = ПолучитьИмяВременногоФайла();
    ДвоичныеДанные = СсылкаИлиИмяФайла.ХранилищеВнешнейОбработки.Получить();
    ДвоичныеДанные.Записать(ИмяФайла);
    КонецЕсли;
    
    Форма = ВнешниеОтчеты.ПолучитьФорму(ИмяФайла);
    Если Форма <> Неопределено Тогда
    пиОткрытьФорму(Форма);
    Иначе
    ВнешнийОтчет = ВнешниеОтчеты.Создать(ИмяФайла);
    ВнешнийОтчет.ПолучитьФорму().Открыть();  //Добавил строчку , не открывались внешние отчеты
    КонецЕсли;
    
    Если НЕ ЭтоФайл Тогда
    УдалитьФайлы(ИмяФайла);
    КонецЕсли;
    
    Исключение
    
    Предупреждение(
    «Выбранный элемент не является внешним отчетом.
    |Либо, данный отчет не предназначена для
    |запуска в этой конфигурации или содержит ошибки.»);
    
    КонецПопытки;
    
    КонецПроцедуры // пиОткрытьВнешнийОтчет()
    
    
    

    Показать

    Reply

Leave a Comment

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