Универсальная обработка очистки регистров сведений, накопления и бухгалтерии от битых ссылок




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

49 Comments

  1. Shaman342

    а то это за формат у файлика —

    2009.04.08 UdalitjBityeZapisiIzRegistrovSvedenijNakopl?

    расширение какое и для какой 1С?

    Reply
  2. Borisych

    Имя файла обрезалось 55 символами

    буду делать короткие имена

    Обработка для 8.1, обновил файл

    Reply
  3. Serj1C

    А она применима для РБД, если документ удалился, а движения остались?

    Думаю, что да. Модуль под паролем ((

    Reply
  4. Borisych

    убивает записи где в поле регистратор видишь надпись типа <Объект не найден : и GUID>

    сейчас нет примера показать

    Reply
  5. Russell82

    Пароль для просмотра модуля???))))

    Reply
  6. _TINA

    а что в этом, простите, сложного? коду ей богу меньше чем на страницу.

    Reply
  7. Катя84

    сама себе такое писала. Скачала, потому что было интересно посмотреть реализацию. Зачем пароль то?))

    Reply
  8. savageRrr

    {ВнешняяОбработка.УдалитьБитыеЗаписиИзРегистровСведенийНакопления(51)}: Ошибка при вызове метода контекста (Выполнить): {(6, 2)}: Неоднозначное поле «Регистр.Регистратор.Номер»

    <<?>>Регистр.Регистратор.Номер ЕСТЬ NULL

    по причине:

    {(6, 2)}: Неоднозначное поле «Регистр.Регистратор.Номер»

    <<?>>Регистр.Регистратор.Номер ЕСТЬ NULL

    Reply
  9. Borisych

    Процедура УдалитьБитыеСсылки()

    Для Каждого Регистр Из Метаданные.РегистрыНакопления Цикл

    Состояние(Регистр.Имя);

    УдалитьБитыеСсылкиРН(Регистр.Имя);

    КонецЦикла;

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

    Если («» + Регистр.РежимЗаписи) <> «ПодчинениеРегистратору» Тогда

    Продолжить;

    КонецЕсли;

    Состояние(Регистр.Имя);

    УдалитьБитыеСсылкиРС(Регистр.Имя);

    КонецЦикла;

    КонецПроцедуры

    Процедура УдалитьБитыеСсылкиРН(ИмяРегистра)

    Запрос = Новый Запрос(

    «ВЫБРАТЬ

    | Регистр.Регистратор

    |ИЗ

    | РегистрНакопления.» + ИмяРегистра + » КАК Регистр

    |ГДЕ

    | Регистр.Регистратор.Номер ЕСТЬ NULL

    |

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

    | Регистр.Регистратор»);

    Выборка = Запрос.Выполнить().Выбрать();

    Пока Выборка.Следующий() Цикл

    НЗ = РегистрыНакопления[ИмяРегистра].СоздатьНаборЗаписей();

    НЗ.Отбор.Регистратор.Установить(Выборка.Регистратор);

    НЗ.Записать();

    КонецЦикла;

    КонецПроцедуры

    Процедура УдалитьБитыеСсылкиРС(ИмяРегистра)

    Запрос = Новый Запрос(

    «ВЫБРАТЬ

    | Регистр.Регистратор

    |ИЗ

    | РегистрСведений.» + ИмяРегистра + » КАК Регистр

    |ГДЕ

    | Регистр.Регистратор.Номер ЕСТЬ NULL

    |

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

    | Регистр.Регистратор»);

    Выборка = Запрос.Выполнить().Выбрать();

    Пока Выборка.Следующий() Цикл

    НЗ = РегистрыСведений[ИмяРегистра].СоздатьНаборЗаписей();

    НЗ.Отбор.Регистратор.Установить(Выборка.Регистратор);

    НЗ.Записать();

    КонецЦикла;

    КонецПроцедуры

    Reply
  10. Borisych

    (8)

    Регистратор в этом случае не документ, обработка корректно отрабатывает битые ссылки для РС, подчиненных регистраторам — документам, а у них номер есть 🙂

    Reply
  11. almas

    Не ребята демократы. С закрытым кодом это все «НАХ». Слишком старшные последствия подобных чисток могут быть.ТОЛЬКО «-«

    Reply
  12. Borisych

    Добавлена чистка регистров бухгалтерии

    Reply
  13. Marilucik

    А если в поле в поле регистратор нет надпись типа <Объект не найден : и GUID>

    — а пусто. Что тогда делать?

    Reply
  14. Borisych

    Марьяна!

    Поподробнее опишите ситуацию, пожалуйста!

    Какой регистр, что происходит при попытке открыть регистратор (дабл-клик по полю), скриншот выложите

    Reply
  15. yahoo_VK

    УТ (1.3.7.9) выдал ошибку:

    {Форма.Форма(35)}: Ошибка при вызове метода контекста (Записать): Ошибка записи! Не установлен отбор по регистратору (Регистр накопления: Партии товаров на складах (управленческий учет))

    НЗ.Записать();

    по причине:

    Ошибка записи! Не установлен отбор по регистратору (Регистр накопления: Партии товаров на складах (управленческий учет))

    Reply
  16. Borisych

    (15) Странно, базы УТ с битыми ссылками у меня нет, но запрос по всем регистраторам очистил регистр без ошибок. Если не разрешите Вашу ситуацию — могу выслать обработку для удаления всей лишней информации, а то что получится после зачистки — присылайте мне для анализа

    Reply
  17. Marilucik

    Регистратор имеет идентификатор равен : 00000000-0000-0000-0000-000000000000

    Обробка дает ошибку:

    {Форма.Форма(73)}: Ошибка при вызове метода контекста (Записать): Ошибка записи! Не установлен отбор по регистратору (Регистр бухгалтерии: Журнал проводок (налоговый учет))

    НЗ.Записать();

    по причине:

    Ошибка записи! Не установлен отбор по регистратору (Регистр бухгалтерии: Журнал проводок (налоговый учет))

    Reply
  18. Borisych

    (17) В моей правктике пока такого не встречалось, но предполагаю, что проводилось тестирование и исправление с переключателем «При наличии ссылок на несуществующие объекты» в положении «Очищать ссылки»

    Reply
  19. Marilucik

    Да проводилось проводилось тестирование и исправление, но с переключателем «При наличии ссылок на несуществующие объекты» в положении «Не изменять». Как можно решить єту проблему?

    Reply
  20. Borisych

    Написать обработку для выявления таких записей и удалить

    Если записей не очень много — могу выслать вам универсальную обработку удаления объектов ИБ, дату зададите = дате битой записи регистра

    Если много — и все типа 00000000-0000-0000-0000-000000000000 — нужно найти способ выбрать все подобные записи, очистить их, перепровести документы за период появления записей

    Reply
  21. Marilucik

    Обработка сервис – групповое изменение справочников и документов выдает ошибку на этапе — ….ПолучитьОбъект(). Объект не выбран. Если маете другую обработку, которая справляетесь с этим заданием вышлите, пожалуйста!

    Reply
  22. Borisych

    (21) Адрес

    Reply
  23. Marilucik
  24. Diamante

    По чему модуль под паролем?

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

    А так же считаю не красиво заставлять пользователя голосовать при закрытии.

    С удовольствием поставил бы «МИНУС».

    Reply
  25. Borisych

    Весь код выложен в этих комментах, см. выше

    Ничего лишнего в коде нет, гарантирую

    Будет время выложу открытую версию

    Reply
  26. Borisych

    Заодно надо реализовать корректную отработку регистраторов — как документов, так и справочников

    Reply
  27. almas

    Borisych — приношу свои извинения. Про комменты не знал/не понял. Несколько раз качал вашу обработку. Видимо неудачно. «АХРЕНИТЕЛЬНО ВЗЛЕТЕТЬ» -Спасибо за критику, но от своих слов не откажусь под страхом смерти.Преценденты были. Поэтому ко всему с закрытым кодом отношусь только отрицательно.

    Reply
  28. itt

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

    Reply
  29. Borisych

    (28) При открытии сформируй список регистров — проставь флажки — и используй обработку помеченных

    программировать 10 минут

    Reply
  30. psychotoad

    Простая и полезная штука!

    Reply
  31. VapPaha

    Спасибо, реально помогало.

    Reply
  32. VapPaha

    помогает для восстановления обмена, повторная чистка

    Reply
  33. esa35

    спасибо, пригодилось для своей разработки

    Reply
  34. RG84

    спасибо, пригодилось при повторной настройке обмена данными УТ-БП

    Reply
  35. Banzai79

    Спасибо за обработку, хорошо работает при малых данных, как можно ускорить процесс для больших данных кол-во записей может превышать больше 10 000 записей

    Reply
  36. Maks_Payn

    Спасибо! Хорошая обработка!

    Reply
  37. Borisych

    (37) Maks_Payn, пожалуйста 🙂

    Reply
  38. fluid

    Спасибо. съэкономил время.

    Reply
  39. velox

    Спасиб! отработала корректно, время заняло немного, всем доволен!

    Reply
  40. DenIv

    2 (9) Автор, а разве в регистрах сведний с режимом записи не подчиненном регистратору не может быть битых сылок?

    В противном случае пишите «Удалиение битых ссылок ТОЛЬКО по регистрам подчиненным регистратору»

    Reply
  41. DenIv

    Автор, здаестя мне я видел этот код в публикации http://infostart.ru/public/82878/

    Reply
  42. Borisych

    (43) DenIv, http://infostart.ru/public/19574/ — не кажется, что публикация 19574 была опубликована гораздо раньше чем 82878???

    Reply
  43. DenIv

    не увидел ответа на вопрос из (42)

    Reply
  44. Borisych

    (45) DenIv, и не увидишь. в данный момент не интересно заниматься обработкой трехлетней давности

    Reply
  45. DenIv

    (46) не поверишь — не интересно. посыл был следующий: в описании обработки написать, что удаляет она ссылки ТОЛЬКО по регистрам с режимом записи — подчинен регистратору и не вводить народ в заблуждение и не важно сколько лет поделке.

    Reply
  46. 3sf

    Спасибо! Пригодилось!

    Reply
  47. RubikJan

    {Форма.Форма(50)}: Ошибка при вызове метода контекста (Выполнить): {(6, 2)}: Неоднозначное поле «Регистр.Регистратор.Номер»

    <<?>>Регистр.Регистратор.Номер ЕСТЬ NULL

    Выборка = Запрос.Выполнить().Выбрать();

    УТ 10.3.7.9

    Reply
  48. rozan

    Огромное спасибо!!! Все получилось с первого раза.

    Столько времени было потеряно зря.

    Reply
  49. lambert

    А, как это лечится?

    {Форма.Форма.Форма(50)}: Ошибка при вызове метода контекста (Выполнить)

    Выборка = Запрос.Выполнить().Выбрать();

    по причине:

    {(6, 2)}: Неоднозначное поле «Регистр.Регистратор.Номер»

    <<?>>Регистр.Регистратор.Номер ЕСТЬ NULL

    Reply

Leave a Comment

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