Ввод по строке (переопределение)




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

15 Comments

  1. blindcat2006

    Прикольно, наверное, но… (см картинку)

    Хотя если для других вариантов использовать — для новичков пойдет

    Reply
  2. anig99

    (1) blindcat2006, Чутка подправить статью и будет годна. То, что на картинке, появилось только в 8.3, а ОбработкаПолученияДанныхВыбора есть уже в 8.2 на управляемых формах.

    Reply
  3. klinval
    Данный способ решиния задачи я использовал еще на Платформе 2.0. Как подсказали в комментариях коллеги в Платформе 3.0 задача решается ещё проще.

    Платформа 2.0 и 3.0? Может платформа 8.2 и 8.3 или конфигурация Бухгалтерия предприятия 2.0 и 3.0? Когда работал во франче у нас менеджеры так путались, не думал, что программист может также запутаться…

    Сама публикация нормальная, правда я уже давно на платформе 8.3 сижу, поэтому вряд ли мне понадобится данные в публикации наработки.

    Reply
  4. niko11s

    (3) klinval, Это очепятка)

    Reply
  5. Brawler

    стоило бы ограничить число строк возвращаемых запросом

    Reply
  6. dtripleh

    Зачем это всё, когда в платформе реализован ввод по строке по любой части?

    p.s Понял. Недочитал:)

    Reply
  7. monkbest

    Есть минусы:

    1. Производительность. номенклатура — справочник содержащий тысячи позиций даже в небольшой фирме. Выражение ПОДОБНО — медленное по сравнению с вырезанием первых n символов. Я бы сначала проанализировал длину строки поиска и допустим искал бы от 3ех или 4ех символов, если введен 1 символ или два отказ = истина. Еще бы добавил в запрос Выбрать первые 5-6, т.к. больше в список выбора один фиг не поместится

    2. Вы убили поиск по коду и артикулу. В ЗУП 3.0 в свое время убили ввод сотрудника по табельному т.к. косячно запрос написали. Т.е. они учли поиск по табельному, но сравнивали табельный с кодом физ.лица а не сотрудника 🙂 у Вас это вообще не учтено. Т.е. надо писать столько условий ПОДОБНО через ИЛИ, сколько у Вас полей используется для ввода по строке. Универсально будет пройтись по метаданным справочника и кодом сгенерить текст условия по всем полям. Это позволит в дальнейшем, если кто добавит еще один реквизит для ввода по строке, он не будет ломать мозг почему не работает, пока не найдет Вашу процедуру.

    Reply
  8. mickey.1cx

    Где то месяц назад мне потребовался ввод по строке с поиском по реквизитам справочника, включая неограниченные строковые.

    Реализовал через полнотекстовый поиск, из плюсов — произвольный порядок слов

    при вводе по строке.

    Reply
  9. pentanom

    (1) blindcat2006, А у меня почему-то это не работает 🙁

    Конфигурация 11.1.10.180

    Платформа 8.3.6.2152

    Reply
  10. V.Nikonov

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

    Автору +

    Reply
  11. vdmkvrshn
    Reply
  12. slitov

    Вот вариант от 1С

    http://v8.1c.ru/o7/201302ss/

    Reply
  13. MaiorovYury

    Спасибо!

    Сделал ограничение для определенных пользователей (что-то вроде RLS) с помощью этой штуки

    Reply
  14. group2tts

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

    Функцию ВернутьФорматированнуюСтрокуПоиска необходимо добавить в СтроковыеФункцииКлиентСервер

    Пример использования ниже:

    Процедура ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка)
    ДанныеВыбора = Новый СписокЗначений;
    Запрос = Новый Запрос;
    Запрос.Текст = «ВЫБРАТЬ ПЕРВЫЕ 10
    | Номенклатура.Ссылка,
    |   Номенклатура.Код
    |ИЗ
    | Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    | (Номенклатура.Наименование ПОДОБНО &Наименование ИЛИ Номенклатура.Код ПОДОБНО &Код )
    | И НЕ Номенклатура.ПометкаУдаления
    | И НЕ Номенклатура.Родитель.Наименование = «»Удалённые»»
    |  И НЕ Номенклатура.ЭтоГруппа»;
    
    Запрос.УстановитьПараметр(«Наименование», «%» + Параметры.СтрокаПоиска + «%»);
    Запрос.УстановитьПараметр(«Код», «%» + Параметры.СтрокаПоиска + «%»);
    
    РезультатЗапроса = Запрос.Выполнить();
    ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
    Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
    Структура = Новый Структура(«Значение», ВыборкаДетальныеЗаписи.Ссылка);
    Элемент = ДанныеВыбора.Добавить();
    Элемент.Значение = Структура;
    Элемент.Представление = ВыборкаДетальныеЗаписи[0].Наименование + » (» + ВыборкаДетальныеЗаписи[0].Код + «)»;
    Элемент.Представление = СтроковыеФункцииКлиентСервер.ВернутьФорматированнуюСтрокуПоиска(Элемент.Представление,Параметры.СтрокаПоиска);
    КонецЦикла;
    СтандартнаяОбработка = Ложь;
    
    КонецПроцедуры
    
    
    Функция ВернутьФорматированнуюСтрокуПоиска(СтрокаДляРазбора, СтрокаПоиска) Экспорт
    СтрокаВВерхнемРегистре = Врег(СтрокаДляРазбора);
    СтрокаПоискаВВерхнемРегистре = Врег(СтрокаПоиска);
    
    ФормСтрока = Новый Массив;
    Для Стр = 1 По СтрЧислоВхождений(СтрокаВВерхнемРегистре, СтрокаПоискаВВерхнемРегистре) Цикл
    Индекс = Найти(СтрокаВВерхнемРегистре, СтрокаПоискаВВерхнемРегистре);
    Если НЕ Индекс = 1 Тогда
    ФормСтрока.Добавить(Новый ФорматированнаяСтрока(Сред(СтрокаДляРазбора,1,Индекс-1)));
    КонецЕсли;
    ФормСтрока.Добавить(Новый ФорматированнаяСтрока(Сред(СтрокаДляРазбора, Индекс, СтрДлина(СтрокаПоиска)), Новый Шрифт(,,Истина),WebЦвета.ЗеленыйЛес));
    СтрокаДляРазбора = Прав(СтрокаДляРазбора, СтрДлина(СтрокаДляРазбора) — (Индекс + (СтрДлина(СтрокаПоиска)-1)));
    СтрокаВВерхнемРегистре = Прав(СтрокаВВерхнемРегистре, СтрДлина(СтрокаВВерхнемРегистре) — (Индекс + (СтрДлина(СтрокаПоиска)-1)));
    КонецЦикла;
    ФормСтрока.Добавить(Новый ФорматированнаяСтрока(СтрокаДляРазбора));
    
    Возврат Новый ФорматированнаяСтрока(ФормСтрока);
    КонецФункции
    

    Показать

    Reply
  15. PLAstic

    (2) Более того, чтобы не колхозить, можно применить свои условия к тому списку, что выдаст сама платформа. Метод ПолучитьДанныеВыбора().

    Reply

Leave a Comment

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