Обработка для замены ссылок (дублей) без перепроведения в "1С:Предприятие 8" для любых конфигураций (обычное приложение)




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

26 Comments

  1. pepe

    А каким образом происходит поиск ссылок?

    Reply ↓
  2. tunesoft

    (1) pepe, генерируется текст запроса 1С по всем метаданным только по реквизитам, содержащим тип ссылки и отбором по значениям «Источник».

    Фрагмент этой функции видно на скрине:

    Reply ↓
  3. karpik666

    (2) так, а чем стандартный поиск дублей не угодил или из инструментов разработчики, да и на худой конец «Поиск и замена значений» , что на диске ИТС? Все это работает без перепроведения документов.

    Reply ↓
  4. insurgut

    Так это же стандартная обработка с диска ИТС поиска и замены значений, которая точно так же напрямую в движениях заменяет ссылки без перепроведения документов. Куда смотрят модераторы?

    Reply ↓
  5. tunesoft

    (3) karpik666, согласен, варианты есть, но они не совсем подходят для наших задач.

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

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

    Ещё в типовой обработке «ПоискИЗаменаЗначений.epf» с диска ИТС выполняется поиск объектов через стандартную функцию «НайтиПоСсылкам», и далее в цикле выполняется перебор всех реквизитов объектов с проверкой на тип и содержание:

    …

    Для Каждого Реквизит Из СтрокаТаблицы.Метаданные.Реквизиты Цикл

    Если Реквизит.Тип.СодержитТип(ТипЗнч(Ссылка)) И Параметры.Объект[Реквизит.Имя] = Ссылка Тогда



    …

    Для Каждого ТЧ ИЗ СтрокаТаблицы.Метаданные.ТабличныеЧасти Цикл

    Для Каждого Реквизит Из ТЧ.Реквизиты Цикл

    Если Реквизит.Тип.СодержитТип(ТипЗнч(Ссылка)) Тогда



    …

    это будет медленно при большом количестве объектов для замены.

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

    Далее выполняется замена ссылок уже по заранее полученным именам таблиц, табличным частям и реквизитам, без излишних проверок в циклах.

    Reply ↓
  6. tunesoft

    (4) insurgut, совсем не стандартная, основные отличия описаны в предыдущем комментарии.

    ещё избыточные циклы и проверки в типовой обработке «ПоискИЗаменаЗначений.epf»:

    Для Каждого ТЧ ИЗ СтрокаТаблицы.Метаданные.ТабличныеЧасти Цикл

    Для Каждого Реквизит Из ТЧ.Реквизиты Цикл

    Если Реквизит.Тип.СодержитТип(ТипЗнч(Ссылка)) Тогда

    СтрокаТабЧасти = Параметры.Объект[ТЧ.Имя].Найти(Ссылка, Реквизит.Имя);

    Пока СтрокаТабЧасти <> Неопределено Цикл

    (3) karpik666,

    >»или из инструментов разработчики»

    внутрь кода не смотрел, но в описании публикации указано «основано на обработке «ПоискИЗаменаДублирующихсяЭлементов» с ИТС»

    Reply ↓
  7. tunesoft

    На двух одинаковых тестовых БД «Бухгалтерия 2» запустил разные обработки, в одной типовую «ПоискИЗаменаЗначений», в другой нашу, настроил одинаковые элементы для замены.

    Через несколько секунд «ПоискИЗаменаЗначений» выдала сообщение и прервалась:

    Существуют документы, оформленные по договору «Договор №… от 01.01.15г.».

    Контрагент договора не может быть изменен, элемент не записан.

    Не удалось записать «Договор №… от 01.01.15г. (Договоры контрагентов)»!

    Наша обработка успешно завершила выполнение за несколько минут, при этом в журнал регистрации добавлены сообщения вида «Замена <Справочник.Контрагенты;Почта;005;7cba181e-335b-11e4-a84f-001f29081c26> на <Справочник.Контрагенты;Почта России;000011;4a9b2d6c-26b0-11df-97a9-001d7d9bbaae> в таблице <Справочники.ДоговорыКонтрагентов>», данные «Договор №… от 01.01.15г.».

    Reply ↓
  8. insurgut

    (7) ОбменДанными.Загрузка = Истина, вот и все отличие… Поиск и замена дублирующих использует замены в режиме загрузки данных, поиск и замена значений просто записывает элемент (в итоге выполняются проверки).

    Reply ↓
  9. tunesoft

    (8) insurgut, это знаю, с 1С работаю более 15 лет, смысл в том, что в исходном варианте обработка «ПоискИЗаменаЗначений» не заменяет ссылки и нет флажка на форме чтобы включить режим «ОбменДанными.Загрузка = Истина»

    Reply ↓
  10. karpik666

    (9) что то непонятно, с 1С более 15 лет, так зачем тогда приводите такое сравнение, или вы думаете, что квалификация посетителей сайта не позволит сказать в чем различия таких данных? Стандартная «поиск и замена значений» предусматривает обмен данными загрузка, просто почему то разработчики не удосужились просто вывести параметр на форму, переделывается это в течении 5 минут, достаточно в функцию замены передавать параметр, что выполнять без проверок. Вам говорят вы изобрели велосипед, притом, что есть уже точно работающие инструменты, и не для одних справочников, а также ПВР, ПВХ, планов счетов, Задач и т.д. А по поводу инструментов, это очень сильно переработанная обработка с ИТС, так как заменяет не только ссылки, но и позволяет оценивать регистры сведений, чтобы не было ошибки на уникальность строк.

    Reply ↓
  11. tunesoft

    (10) karpik666,

    >и не для одних справочников, а также ПВР, ПВХ, планов счетов, Задач и т.д.

    В нашей обработке тоже есть аналогичная возможность, сейчас в форме в типе элемента явно указано «Справочник», раньше было «Любая ссылка», можно снова выбрать мышкой «Любая ссылка»

    >А по поводу инструментов, это очень сильно переработанная обработка с ИТС, так как заменяет не только ссылки, но и позволяет оценивать регистры сведений, чтобы не было ошибки на уникальность строк.

    Отлично.

    Тоже заменяем в регистре сведений.

    >Вам говорят вы изобрели велосипед

    Ну и замечательно.

    Обработки разные, работают по-разному, и вообще изобретать «велосипеды» полезно 🙂

    Reply ↓
  12. karpik666

    (11) ладно будь по вашему, может кому то пригодится.

    Reply ↓
  13. pepe

    (12) karpik666, Нужно проверить эту обработку, думаю она быстрее работает. Стандартной обработка на моей базе тупо виснет. Через запросы более эффективнее, только сложность, что нужно разбирать метаданные.

    Reply ↓
  14. tunesoft

    (13) pepe,

    >Стандартной обработка на моей базе тупо виснет.

    Не должна зависать.

    В другой сессии 1С в журнале регистрации смотрели запись транзакций фиксируется ?

    База файловая или SQL ? Какой размер БД ?

    Пробовали выполнить в конфигураторе «Администрирование — Тестирование и исправление» ?

    Reply ↓
  15. pepe

    Это проблема размера базы, база уже 600 гбайт. Тестирование и исправление делали относительно не давно.

    Reply ↓
  16. gulchitai

    (5) tunesoft. Вы пишите про обработку «Поиск дублей», который готовит список замен, она есть на инфостарте? Как ее можно получить?

    Reply ↓
  17. tunesoft

    (16) gulchitai, какие-то были, можете через поиск найти.

    Reply ↓
  18. gulchitai

    (17) Свою написала )

    Reply ↓
  19. gulchitai

    Замена ссылок происходит не в режиме ОбменДанными.Загрузка = Истина? При замене появляются сообщения об ошибках, которые у нас вставлены в подписки на события, в них есть такая проверка

    Если Отказ ИЛИ Источник.ОбменДанными.Загрузка Тогда
    Возврат;
    КонецЕсли;

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

    Reply ↓
  20. tunesoft

    (19) gulchitai, запись выполняется в режиме «.ОбменДанными.Загрузка = Истина», но в случае изменения регистра сведений без регистратора используется менеджер записи, у которого нет «ОбменДанными». Почему используется «МенеджерЗаписи», а не «НаборЗаписей» уже не помню 🙂

    Reply ↓
  21. gragden

    Ожидал что можно будет любой тип объекта искать, а тут только можно справочники выбирать ))), очень похожа на ИТС версию, и 6 стартмани за это жирно

    минус

    Reply ↓
  22. tunesoft

    (21)

    Добрый день, Денис.

    В обработке можно использовать любые ссылочные типы.

    Для этого нужно в конфигураторе у поля выбора присвоить тип «Любая ссылка».

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

    Reply ↓
  23. gragden

    (22)

    тому задан такой тип чтобы сузить с

    Ваша обработка для «полного счастья» еще и запаролена (Введите пароль для работы с текстовым модулем).

    минус

    Reply ↓
  24. tunesoft

    (23)

    пароль подобрать не удалось 🙂

    поищу в архивах и сообщу

    Reply ↓
  25. alexey_t

    Отдать 4 стартмани за запароленную обработку!

    В описании про это ни слова!

    Reply ↓
  26. tunesoft

    (25) постараюсь убрать пароль и обновить, давно это было

    Reply ↓

Leave a Comment

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