Реализация периодических характеристик для произвольных объектов




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

7 Comments

  1. human_new

    Сергей, а почему нельзя было воспользоваться при разработке стандартными дополнительными реквизитами?

    Reply
  2. bforce

    В эту статью меня заставил заглянуть ее заголовок. Однако в содержании Вы описали обычное использование того, что в типовых называется Дополнительные сведения. Все то же самое я могу получить и путем внедрения в свою самописную конфу подсистемы Свойства Библиотеки стандартных подсистем. Не ясно, что же нового по сравнению с имеющимся предлагаете Вы? Может я что-то недопонял?

    Вот, если бы показали нам настоящий пример использования периодичности дополнительных свойств, тогда это бы ценно с прикладной, а может и теоретической, точки зрения. На данный момент, я не понимаю, как пользователь может их менять, сохраняя старое значение.

    Далее еще один спорный момент.

    …имя периодического реквизита, для обращения к нему (без пробелов и спец. символов), чтобы при необходимости можно было использовать его в конфигураторе.

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

    Ну, и последний момент, который бросился в глаза. К сообщению я приложил два скриншота из демонстрационной базы, которую публикуют вместе с платформой. Вопрос: знаете ли для чего нужна кнопка Характеристики?

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

    Reply
  3. tristarr1

    (2) bforce, 1. Если Вы обратили внимание, то в получении значений реквизитов используется виртуальная таблица «РегистрСведений.ЗначенияПериодическихРеквизитов.СрезПоследних» из чего можно сделать что значения хранятся в ПЕРИОДИЧЕСКОМ регистре сведений. Как их менять «сохраняя старые значения» — очень просто добавлять запись в регистр сведений с заполненным периодом, а с помощью регистратора этоо будет или независимо, уже не важно.

    2. Что касается реквизита «ИмяРеквизита» для использования в конфигураторе — все очень просто. Представим себе ситуацию когда у вас очень большая РИБ в разных частях страны (а может и света) вводу разности во времени вы не имеете возможность выгонять пользоватей из базы и ждать обновления, так что неплохо бы иметь возможность обновлять конфигурацию динамически. Для этого и была реализована данная возможность. Должна это быть неотъемлемая часть объекта или нет это не принципиально данная конструкция позволяет работать с дополнительными сведениями как с полноценными реквизитами объекта. Что касается нашего случая, то был разработан механизм, который позволяет размещать дополнительные реквизиты на форме документов в режиме предприятия, как раз потому что нет возможности выгонять пользователей из 85 филиалов по всей стране.

    3. Ну и по последнему пункту. Не надо утверждать что я знаю или чего не знаю это не профессионально и мы здесь не для того чтобы мериться друг с другом знаниями или опытом, а для того чтобы делиться ими. Хотелось бы в качестве приложения увидеть скрин где таблица из которой вы получаете значения характеристик была бы виртуальная таблица регистра «СрезПоследних» и все это с помощью той же кнопки «Характристики». Заранее спасибо.

    Reply
  4. tristarr1

    (1) human_new, По причинам указанным выше, в комментарии для пользователя bforce

    Reply
  5. bforce

    (3)

    1. Конечно, я приметил виртуальную таблицу. Но я ожидал, что Вы, все-таки, используете доработанный кусок БСП и надеялся, что Вы расскажете секрет о том, где и что пришлось изменить, чтобы все это заработало. БСП дает хороший инструментарий, который я бы не стал писать вручную. Речь об этом.

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

    2. Здесь сложно как-то высказываться, так как у Вас своя специфика: много баз, разные часовые пояса и прочее. Но, ведь, конфигурацию все-равно когда-то приходится обновлять? Вряд ли она у вас на замке от поставщика.

    3. Вы абсолютно правы! Срез последних там не выбрать, но учитывая то, что я сказал в первом абзаце, можно легко найти выход. Первое, что приходит в голову: берем типовую подсистему Свойства, добавляем регистр История дополнительных сведений (периодический), создаем подписку на типовой регистр и записываем измененные свойства в наш регистр. При такой настройке мы имеем все возможности, которые дает БСП, а также, можем просматривать историю изменения свойств. Я так понимаю, непосредственно в логике конфигурации история изменений не нужна? Она требуется в редких случаях, когда пользователь хочет посмотреть кто и что менял? В этом случае, остается добавить отчет или команду для просмотра истории.

    И это снова мое ИХМО на ту задачу, что Вы описали. Специфики я не знаю, поэтому не стану утверждать, что мое видение правильное. Решать в любом случае Вам, так как Вы ближе к проблемной области.

    Reply
  6. tristarr1

    (5) bforce, 3. Представьте что вам потребуется использовать эти самые реквизиты в печатной форме. И что тогда? проще обращаться в периодический регистр на дату документа, чем в зависимости от рабочей даты скакать по разным регистрам. И вообще на мой взгляд использование всякого рода «костылей» в виде подписок является плохим тоном, так как их выполнение не очевидно и проблематично в отладке.

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

    Reply
  7. ukunad

    Платформа 8.3.10.2168, обе ошибки исправлены.

    Reply

Leave a Comment

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