Ошибка при попытке вставки записи с неуникальным значением ссылки. (решение)




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

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

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

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

20 Comments

  1. sknarid

    К сожалению выполнение обработки(ремонт таблиц) требует отбросить границу запрета редактирования документов, а с ней и последовательность к началу жизни. А потом всё восстанавливать за годы и рассылать на периферию…. Это гроб.

    Reply
  2. Danil.Potapov

    (1) sknarid,

    Тогда нужно включить у объектов режим ОбменДанными.Загрузка = Истина и другие флаги заложенные в конкретной конфигурации.

    Reply
  3. ccserg

    {(5, 3)}: Неоднозначное поле «Данные.Регистратор»

    <<?>>Данные.Регистратор КАК Регистратор,

    ЗИКБУ

    Reply
  4. chesnokov-a-v

    (1) sknarid, Если я правильно понимаю, то возникшая проблема — это проблема конкретной базы (будь то центральная или дочерняя база). У меня такая проблема возникла в дочерней базе, т.е. в центральной все нормально и из дочерней базы в центральную обмен уходит и центральной загружается. Не проходила только процедура загрузки данных из центральной базы в дочернюю.

    Сделал следующее:

    0. Сделал копии баз.

    1. Выполнил обмен как есть (т.е. без загрузки данных в ДБ) 2 раза. Таким образом из дочерней в центральную выгружено все что зарегистрировано для обмена и дочерняя база об этом знает.

    2. Убрал для своего пользователя дату запрета редактирования в дочерней базе.

    3. Запустил данную обработку и дождался выполнения.

    4. Открыл обработку «Регистрация изменений для обмена» (она стандартная) в дочерней базе и удалил всю регистрацию для центральной базы.

    5. На фтп удалил файлы обмена.

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

    7. Запустил обмен в дочерней. Все прошло нормально.

    Reply
  5. sultbec

    Обработка выключает итоги регистров, и не включает их потом.

    Reply
  6. Danil.Potapov

    (5) sultbec,

    не, все включается.

    Reply
  7. AlaBait

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

    Reply
  8. igorbon

    Не работает в УТ11.1

    Reply
  9. magolubev

    (7) Была ошибка в УТ 11.1 при проведении заказа клиента, что записи в таблице AccumRG6910 (как выяснил с помощью ПолучитьСтруктуруХраненияБазыДанных(), регистр накопления ЗаказыКлиентов)

    Аналогично распровел документ и провел повторно — ошибка ушла

    Reply
  10. zoomych

    Не работает в 11.3

    Reply
  11. Danil.Potapov

    (10)

    Не работает в 11.3

    что пишет система?

    Reply
  12. dragen

    (11)


    что пишет система?

    При обновлении на ут 11.2.2 грешит на справочник.Упаковки.

    Что делать?

    Reply
  13. kn8603

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

    Reply
  14. VaLerkaBed

    (7)Спасибо! Это решение спасло после трех дней поисков.

    Reply
  15. Сирёга

    не качайте. не работает. верни мне монетку

    Reply
  16. Bukaska

    (15)Смотрите дату. 2012 год, тогда 8.3 еще не было и в помине. А вы конечно ее открываете на современной конфигурации.

    Reply
  17. Danil.Potapov

    (15) что не работает?

    Reply
  18. Rans

    У меня ошибка возникает в Рознице на одном из узлов РИБ при выполнении метода прочитать изменения во время синхронизации. Проверки логической и ссылочной целостности, checkdbfl не помогли. Сначала ругался на регистр ПродажиПоДисконтнымКартам. Запрос не показывает задвоенные записи. Сделал реструктуризацию, удалил из выгрузки в центральной все записи регистров накопления, теперь ругается на регистр БонусныеБаллы. По нему запрос тоже ничего не возвращает. Куда дальше смотреть подскажите плз.

    Reply
  19. Danil.Potapov

    (18)

    как выглядит запрос?

    Reply
  20. Rans

    Да также как Ваш, подставил другой регистр:

    ТекстЗапроса = «ВЫБРАТЬ РАЗЛИЧНЫЕ

    | Данные.Регистратор КАК Регистратор

    |ИЗ

    | (ВЫБРАТЬ

    | БонусныеБаллы.Регистратор КАК Регистратор,

    | БонусныеБаллы.НомерСтроки КАК НомерСтроки,

    | СУММА(1) КАК КоличествоДублей

    | ИЗ

    | РегистрНакопления.БонусныеБаллы КАК БонусныеБаллы

    |

    | СГРУППИРОВАТЬ ПО

    | БонусныеБаллы.Регистратор,

    | БонусныеБаллы.НомерСтроки

    |

    | ИМЕЮЩИЕ

    | СУММА(1) > 1) КАК Данные»;

    Похоже проблема все-таки была в данных, которые прилетали из ЦБ.

    Пока удалось победить повторным удалением из выгрузки в ЦБ данных этих двух регистров.

    Reply

Leave a Comment

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