<?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='\
Интересно как виртуальные таблицы вы преобразуете в запросы sql ? )))
Учитываете ли разделение данных? )))
Задумка интересная, но есть много вопросов по поводу обработки таблиц) и версия 0.0.2, надеюсь не остановишься на этом.
Зачем такие сложности с виртуальными таблицами, если есть описание временной таблицы?
(4) Как раз через описание временных таблиц все и сделано, а сложности для того, что бы пользователь мог видеть в конструкторе все доступные поля, и эта информация ни как не влияла на создаваемый (конечный) текст запроса.
(2) Это не обработка прямого подключения к SQLной базе 1С (хотя идея интересная 😉 ). Это обработка написания произвольного (с большими ограничениями) запроса к SQLной базе. Поэтому она не предполагает использование в конструкторе ветки метаданных 1С, только обработкой сформированные временные таблицы.
(3) не остановлюсь, если вы будете оставлять свои пожелания и комментарии, желательно в развернутом виде и они будут дополнять первоначальную концепцию. Данный механизм мной был написан и успешно внедрен (с некоторыми дополнениями) на проекте. Так как я его долго искал по просторам интернета и не нашел, решил выложить, может я не один ищущий.
Классная штука=) Будем тестить!)
А зачем нужны два режима: нетиповой (слева) и типовой (справа) и маппинг между ними в виде временных таблиц. Не удобнее ли было реализовать типовой конструктор для таблиц SQL?
(9) Это вопрос ради вопроса?
В моей обработке один режим.
Маппинга тоже нет, есть представление таблиц SQL в виде временных таблиц, для возможности иметь доступ к полям присоединяемых таблиц.
Возможно, для каких то задач было бы удобнее, ваше предложение. Убедительная просьба, когда реализуете, оставьте здесь ссылку на вашу работу.
Типовой конструктор (на сколько мне известно, могу ошибаться) не работает с таблицами SQL, если вы не используете подключенные внешние источники данных.
(10) Извините, в самом деле, конечно же реализовать свой конструктор запросов задача еще та, поэтому предложенное Вами решение это разумный компромис между функционалом и сложностью реализации.
(0) Код не закрыт ?
(12) Можете примерчик такого «сложного» запроса?
(14) К примеру понадобится выбрать элементы справочника у которых в табличной части в одном из полей встречаются ссылки на другой элемент справочника, но только те что встречаются в табличной части определенного списка документов. Это достаточно простой запрос но часто требуются посложнее.
(12) Думаю, что многие, я в том числе :), пользуются конструкторами, что бы не заморачиваться с вводом имен полей. Набросал, через конструктор «мясо» а потом можно и котлетки-конфетки лепить, хоть конструктором, хоть руками. И самое важно, конструктор помогает не делать грамматических ошибок ;). Да и форматнуть структуру проще через конструктор, чем руками ТАБы выставлять 🙂
(13) Открыто, входите 🙂
(17) В таком случае разве недостаточно стандартного конструктора чтобы кубики наделать а потом из них уже не в конструкторе собрать домик?
Лучше создать универсальный механизм позволяющий делать любое кол-во иерархи в справочниках.
Чтобы группировать одни и те же элементы справочника по разному и при этом никогда не корректировать конфигурацию и ничего не зашивать в код.
(15) Читал , может что то упустил , где написано что код открыт ?
Как то было дело скачал одну из обработок , а там код был закрыт.
Вижу автор отписал уже , что открыт.
(18) Спасибо!
(0) Повторяете функционал внешних источников данных ) Без необходимости изменения конфигурации, конечно
Что-то прикольное 🙂
Интересная реализация. В избранное однозначно.
(6) а жаль, была бы бомба
Нет исполняемых функций, это жаль. Ещё я себе добавил ТЗ.Сортировать(«TABLE_NAME»); чтобы отсортировать таблицы по имени перед загрузкой их на форму
Короче дописал чтобы заполнял ещё и функции с параметрами и не ругался конструктор при работе с ними.
Ошибка выходит на пустой конфе
{ВнешняяОбработка.КонструкторЗапросаДляSQL.Форма.Форма.Форма(67,16)}: Переменная не определена (СтроковыеФункцииКлиентСервер)
МассивПолей = <<?>>СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок(ТекстЗапроса, «,»);
на какой то типовой ее надо запускать?
(30) да похоже, что в пустой базе не взлетит. Перепишите вызов корректно, а данную процедуру возьмите из типовой конфигурации (возможно ещё какие-то процедуры и функции потребуются из типовых)