Программисту на заметку: автозаполнение реквизитов документов и справочников




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

13 Comments

  1. Поручик

    (0) Лучше сделайте в виде отдельной подсистемы и продавайте за деньги.

    Reply
  2. vdscom

    (1) Поручик,

    спасибо, подумаю 🙂

    возможно, объединю с другими механизмами, пока не опубликованными на сайте

    Reply
  3. awk

    (1) Поручик, Кто это купит?

    1. Ошибки проектирования:

    Ошибка №1. Поиск по синониму. Если делать, так делать по полному имени Метаданные().ПолноеИмя();

    Ошибка №2. Работа при записи, а не перед записью.

    Ошибка (сильно субъективная) №3. Использование справочника. По моему гораздо лучше подойдет объект регистр сведений. Тем более там контроль уникальности по измерениям и периодичность.

    Регистр (периодический независимый):
    Измерения:
    ПолноеИмя: Полное имя объекта метаданных
    Ресурсы:
    Условие: Строка — функция дополнительной проверки Если Не ПустаяСтрока(Условие) И Вычислить(Условие) <> Истина Тогда Возврат; КонецЕсли;
    ЗначениеПоУмолчанию: Составной — значение для подстановки.
    ЗаменятьТолькоЕслиНеЗаполнено: Булево — Если Истина, тогда проверяем на заполненность иначе не проверяем.
    Обработчик: Строка — Обработчик перед записью конкретного объекта.
    

    Показать

    2. Способы применения? Почему нельзя использовать Перед записью в объекте или подписке на событие? Что мешает работать в конфигураторе?

    3. Безопасность. Где гарантия, что сторонняя установка не понаставит того, чего не надо?

    Reply
  4. vdscom

    (3) awk,

    я не считаю это ошибками

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

    2. чем вам не нравится событие «ПриЗаписи» ?

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

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

    5. не понаставит. если не поставить галочку «принудительно», то заполняются только незаполненные значения

    Reply
  5. awk

    (4) vdscom,

    1. Считаешь ты поиск по синониму ошибкой или нет. Пишешь или нет, что он должен быть уникальным. Это остается ошибкой. То есть действием нарушающим правило. А правило гласит: «Идентификатор должен быть уникальным». Второе правило гласит: «Если что-то может пойти не так и ты об этом знаешь, то оно обязательно пойдет не так».

    2. Тем что При записи выполняется после записи объекта в БД, но до окончания транзакции. Это серьезная ошибка.

    3. А я и написал, что субъективно. То есть спорно и не факт, что правильно.

    4. Что-то неправильное в этом. Если одному надо одно, другому — другое, то вроде реализовано это пользовательскими настройками, зачем огород городить?

    5. А если оно должно оставаться пустым?

    Reply
  6. vdscom

    (5) awk,

    1. вся жизнь у нас построена на допущениях. в контексте поставленной передо мной задачи поиск по синонимам меня вполне устраивает. считаете вы это ошибкой или нет. появится необходимость — переделаю, а пока — есть такое выражение — «Лучшее враг хорошего».

    2. насчет «ПриЗаписи» — почти согласен

    3. тут мы поняли друг друга

    4,5. пользовательскими настройками реализовано далеко не все, а только заполнение некоторых стандартных параметров, типа ОсновнаяОрганизация или Ответственный. предложенный механизм — универсальный, заполняй любой параметр любым значением, в зависимости от заданных условий. «а если оно должно оставаться пустым» — ну так не создавайте для этого реквизита правило или наоборот, создайте правило, при определенных условиях записывающее в этот реквизит пустое значение. а если совсем уж везде враги народа мерещатся — настройте права доступа к этому справочнику

    Reply
  7. awk

    1. Зачем делать допущение, что два плюс два равно пять? Всем известно, что два плюс два равно четыре. Так и тут. Зачем делать допущение что синоним неизменен и уникален? Есть имя — оно хоть и изменяемо, но уникально в пределах типа. А полное имя уникально в пределах конфигурации.

    2. Что означает почти? Что событие при записи возникает до помещения в базу данных? Или что оно происходит вне транзакции? Или что на ИТС нет рекомендаций? 😀

    3…

    45. Ну хорошо. Допустим. Но посмотреть реализацию на всякий случай можно было? Там реализовано автозаполнение форм при открытии. Почему? Да потому, что пользователь перед записью видит что делает и может повлиять на записываемый реквизит. А если при записи это делать, то может получится следующее:

    * Открываем выписку по кредиту

    * Смотрим и видим, что в ней сумма нашего долга равна нулю

    * Закрываем с записью

    И о чудо мы должны 100 тысяч рублей.

    А как должно бы было быть:

    * Открываем выписку по кредиту

    * Смотрим и видим, что в ней сумма нашего долга равна нулю

    * Закрываем с записью

    И видим сообщение, что надо либо указать сумму кредита, либо закрыть без сохранения.

    Reply
  8. vdscom

    (7) awk,

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

    2. посмотрел в конфигураторе рабочих баз — в подписке на событие задан обработчик «ПередЗаписью». получается, что в моей статье опечатка и мы спорили ни о чем 🙂

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

    надеюсь, мы друг друга услышали

    Reply
  9. awk

    Он то же доверял…

    Reply
  10. burlakov

    не сочтите за рекламу, но моя разработка в чем-то лучше вашей. посмотрите сами http://infostart.ru/public/197108/

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

    Reply
  11. vdscom

    (10) burlakov,

    ну, мне моя больше нравится 🙂

    и денег за нее я тоже не прошу

    Reply
  12. Эсти

    спасибо за статью

    Reply
  13. user730384

    спасибо большое за статью))

    Reply

Leave a Comment

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