Когда добавлять предопределенные элементы справочников уже поздно… но ОЧЕНЬ хочется




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2026-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='\

18 Comments

  1. ksvd

    Надо проверить сегодня. За идею спасибо

    Reply
  2. Franco

    http://1clancer.ru/article/predopredelennye_elementy…_ne_izmenyaya_tipovuyu_konfiguratsiyu_687

    Reply
  3. qwinter

    В 8.3 с этим славо богу проще)

    Reply
  4. rasswet

    почти аналогично делаю.

    Reply
  5. kosmo0

    я добавил в мой справочник предопределенный элемент «СтранаУкраина»

    Наверное я что-то не понимаю. Чтобы не создавать предопределенный элемент в нужном справочнике автор создает предопределенный элемент в специально созданном справочнике? Если это так, то это бред.

    Reply
  6. torch

    (6) Я хотел создать предопределенный элемент в справочнике «Страны». Но когда я понял, что мне это надо — было уже поздно. Пользователи создали его интерактивно

    Reply
  7. Stim213

    Если честно, это похоже на изобретение велосипеда. Конешн, так проще, чем создавать предопределенный элемент справочника Страны, переносить все ссылки на него.. но простой вариант не значит правильный!

    Предопределенный элемент — это в первую очередь элемент, заданный разработчиком и изменяющийся только разработчиком! Ваш же якорь могут изменять любые пользователи, имеющие доступ к справочнику «предопределенных» элементов. И не факт, что однажды в Справочники.ПредопределенныеЭлементыСправочников.СтранаУкраина.СправочникЯкорь не окажется страна Замбабве, скажем.

    Кроме того, созданием нового справочника с якорями вы только усложняете структуру связей в конфигураторе, «замусориваете» код и затрудняете дальнейшее сопровождение.

    В общем, хороший такой костыль. временный.

    Reply
  8. torch

    (8) Во-первых переносить ссылки не всегда получается, т.к. некоторые клиенты используют закрытие периода и блокируют документы до определенной даты. А во-вторых справочник ПредопределенныеЭлементыСправочников является служебным, заполняется мною лично и остальным пользователям даже не показывается

    Reply
  9. DAnry

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

    Reply
  10. karapuzzzz

    Идея, конечно не новая. Пользуюсь подобным справочником довольно давно. Это намного лучше, чем «НайтиПоНаименованию» или «НайтиПоКоду». Я бы даже сказал — более правильно.

    Сначала я хотел написать комментарий из серии «Автор, пользуйся поиском…» или «Зачем писать прописные истины…». Но после просмотра комментариев — автор, спасибо, что подняли эту тему и сдули с нее пыль.

    (8) Stim213, (6) kosmo0, пожалуйста, поделитесь «правильным» способом. В топике есть ситуация, предложите свое решение.

    Reply
  11. Stim213

    оххх..

    (11) karapuzzzz, решений несколько, выбор того или иного способа зависит от условий бизнес-процессов, которые автор не описал.

    кроме того, справочник Страны — должен(!) заполняться на основании классификатора стран мира (Общероссийский классификатор стран мира )

    там есть и правильный названия стран и коды и многое другое.

    При правильном ведении учета(а мы же говорим про него?) на этапе внедрения разработки справочника нужно как минимум проанализоровать дальнейшую его бизнес-логику, а не бросать его в растерзание пользователям. Заполнить справочник из классификатора, заполнить все служебные реквизиты, по которым будет идти поиск.. в крайнем случае заполнить справочник предопределенными значениями на основании того же классификатора..

    НО ЭТО ВСЕ ДЕЛАЕТСЯ ДО(!), А НЕ ПОСЛЕ ВНЕДРЕНИЯ! не тогда, когда пользователи набивают 100500 одинаковых стран и используют их в 100500#k8SjZc9Dxk100500 документах.

    Если вы в чем-то сомневаетесь, господа — посмотрите хотя бы как это реализованы в типовых. От ошибок и они не застрахованы, но с архитектурой там все в порядке.

    Reply
  12. Stim213

    + а когда «уже все поздно» — можно обойтись и без дополнительных справочников.

    но все опять же зависит от бизнес-логики и структуры базы, универсальных советов дать не смогу..

    Например, если доставка для разных стран разная, то можно спр

    Reply
  13. karapuzzzz

    (12) Stim213, Типовые на то и типовые, что пытаются охватить многое, но не все. Считается нормальным 10% бюджета на внедрение выделять на программирование.

    Вы говорите «старайтесь строить архитектуру своих решений с минимальными возможными изменениями. Продумывайте свои действия на пару шагов вперед.». Я продумываю свои действия. Но продумать действия заказчика невозможно.

    Судя по вашим ответам, можно сделать вывод, что все программирование происходит только во время внедрения. А потом всеми руками и ногами отбрыкиваемся от заказчика. А он ведь как: «сначала не хочу, а потом хочу» или «ой, а как же мы все это время жили без этой кнопки?».

    Ваш «Возможно, это будет какой-то регистр с настройками.» предполагает создание еже одного объекта. Так почему регистр с настройками лучше справочника?

    Reply
  14. Stim213

    «Так почему регистр с настройками лучше справочника?»

    Потому что в 1С настройки программы или отдельных подсистем хранятся в основном в регистрах сведений:)

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

    Тем более регистр сведений наиболее оптимален для хранения и чтения периодически изменяющейся информации.

    «все программирование происходит только во время внедрения.» — так и должно быть. К этому нужно стремиться, по крайней мере. До начала внедрения все вопросы должны быть решены. Конешн, всех затыков не избежать, но в конкретной ситуации с автором — при проектировании справочника Страны — нужно было бы сразу вспомнить о классификаторе стран мира и обсудить вариант с его с клиентом.

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

    Господа, читайте мануалы! http://its.1c.ru/db/v8std#browse:13:-1

    Reply
  15. Wrols

    (15) Stim213, программирование происходит не только во время внедрения.

    А у вас довольно-таки идиалистический взгляд…

    Практика показывает, что бизнес меняется, а из-за этого меняются и требования к учетной системе.

    Всё течет, всё изменяется. Это жизнь. Это нормально.

    Предложенное решение автора имеет право на существование. А то, что справочник «Страны» упомянут — так это же только пример.

    Вот только минусы имеет — производительность и такое обращение не сработает в запросе…

    Reply
  16. karapuzzzz

    (16) Wrols, Почему не сработает? Можно в запросе напрямую обращаться к предопределенному элементу (не используя параметры).

    Идея предопределенного элемента сводиться к тому, что можно жестко обратиться к нему из конфигуратора. С регистром так не получиться.

    Reply
  17. red80

    (6) kosmo0, ты действительно не понимаешь. Чтобы понять, нужен опыт обновлений типовой.

    Reply

Leave a Comment

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