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




Принцип обмена данными из 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 не будет опубликован. Обязательные поля помечены *