Журнал регистрации изменений




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

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

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

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

55 Comments

  1. svarog

    Отличная обработка.

    Есть пожелание:

    1) при внесении изменений в табличной части (например, изменил колич. товара с 8 на 10), старое и новое значение количества в разных строках находятся. Т.е. выводит все реквизиты таб. части со старыми значениями и ниже все реквизиты таб. части с новыми значениями. Неудобно искать, что же изменилось. С реквизитами шапки документа синхронизация старых и новых значений происходит на ура (например, сумма документа).

    2) Для более быстрого поиска измененных реквизитов можно было бы добавить галочку «Изменен» в таблице изменений.

    Reply
  2. ivvvvvvan

    А как эта подсистема реагирует на УРИБ? Например, в филиале Создали Документ, исправляли и дополняли, но не провели. Документ отправился в центр. Там его провели. И он опять уходит в филиал. КАк это все отражается?

    Reply
  3. PowerBoy

    (1) Быстрое определение изменений в табличных частях — это отдельная тема, и еще требует дальнейшей проработки. Пока реализовано на уровне записей — но можно подумать как их свернуть.

    (2) Подсистема не фиксирует загрузки объектов, только их изменение в центре.

    Reply
  4. Yashazz

    На основе справочника? А он от объёма не задохнётся? Может, лучше бы регистр сведений?

    Reply
  5. PowerBoy

    (4) На справочник нет никаких ограничений! Для хранения изменений он более оптимален по сравнению с регистрами сведения (за счет использования табличной части).

    Reply
  6. Romarius

    Отлично!!! Буду тестировать!

    Reply
  7. Ish_2

    (5) Почему «справочник..для хранения изменений..более оптимален по сравнению с регистрами сведения ( за счет использования табличной части )» ?

    Reply
  8. svarog

    странно отрабатывается обновление (при нажатии кнопки «Обновить») в обработке «Журнал изменений». С самом журнали запись есть, а в обработке показывает с запозданием минут на 15.

    Reply
  9. svarog

    (7) Где то на инфостарте были измерены скорость работы с регистрами и справочником. Так в регистры сведений проигрывают по скорости записи/чтения справочникам. В регистрах идут проверки на уникальность записи, кажись так.

    Reply
  10. Yashazz

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

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

    Reply
  11. Ish_2

    (10) Согласен в качестве общего подхода.

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

    Reply
  12. Yashazz

    (11) Не совсем понимаю, причём тут табличная часть справочника. Каждая запись регистрации означает элемент, а не строку табчасти, или я не прав? Для чего вообще в этом случае табличная часть может использоваться?

    Reply
  13. Ish_2

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

    имеет справочник с табличной частью перед регистром сведений.

    Reply
  14. Re:аниматор

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

    Reply
  15. PowerBoy

    (13)

    1. Запись в справочник идет быстрей.

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

    Reply
  16. tsd

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

    (14) дык проверить недолго. 5 минут пишем обработку, час закачиваем информацию 🙂

    (15) нормально все на справочнике должно вертеться. Проблем с блокировками быть вроде не должно. вывести из ТЧ данные не долго, сколько там строк в реалиях будет мах. 100-150

    Reply
  17. Ish_2

    (14) На мой взгляд , более правильно вести речь не об общем подходе ,

    а о решении данной конкретной задачи. В ней , насколько я понял автора,

    наиболее критична по времени — операция записи. Учитывая более

    высокую скорость записи и отсутствие «тормозящих» блокировок ,выбор

    справочника как объекта хранения данных представляется оправданным.

    Можно также предположить , что «миллионы записей» существенно картину не

    изменят.

    Reply
  18. tsd

    (15) хе хе, подозрения оправдались.

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

    Если Вы ссылку на объект в реквизит пишите, то ее наверное при удалении объекта отрабатывать нужно?

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

    Обработка просмотра изменений для пользователей будет не очень удобна. одна измененная строка в документе разбивается на неопределенное кол-во строк в таблице просмотра изменений. Многих будет вводить в ступор состояние «Строка удалена», «Строка добавлена» (ведь в реалиях никто строки не удалял и не добавлял).

    Кстати, а почему сделана обработка? Ведь мы никаких действий, кроме просмотра, не выполняем.

    Reply
  19. PowerBoy

    (18) «Кстати, а почему сделана обработка? Ведь мы никаких действий, кроме просмотра, не выполняем.»

    С обработкой манипулировать легче. Да и функционал может расти со временем, кроме просмотра уже есть «Очистка журнала» например. 🙂

    Reply
  20. MRAK

    (0) молодца! Классная вещь!

    Единственно, что пока не нравится:

    (18) «Обработка просмотра изменений для пользователей будет не очень удобна. одна измененная строка в документе разбивается на неопределенное кол-во строк в таблице просмотра изменений»

    с этим согласен…. мне (думаю и многим другим) более эргономично представление в строку, тем более, что для удаленных строк «новое значение» не актуально.

    Но это легко и самому дописать. Код-то открыт.

    Reply
  21. marih

    Подскажите пож-та, что не так : после объединения с конф ЗиК

    версии 8.1.8.76 потерян путь к функциям глобального модуля ,

    например глЗначениеПеременной(«глУчетнаяПолитикаПоПерсоналуОрганизации»),

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

    Reply
  22. PowerBoy

    (21) При обмене видимо заменили общий модуль на пустой. Скопируйте этот модуль обратно из ЗиК.

    Reply
  23. marih

    общий модуль НЕ пустой и ф-ция в нем есть , но не выполняется

    из модуля документа

    Reply
  24. MRAK

    (21) не бывает «конф ЗиК версии 8.1.8.76»

    Reply
  25. alexaled

    Обработка супер!!! Тестирую. Автору спасибо!!!

    Reply
  26. analit1c

    Просто и доступно

    Reply
  27. KrutoyGeniy

    Просто суппер! Спосибо большое!

    Reply
  28. HIgor

    Потестируем. Хотя на той неделе сам писал такую на регистре сведений.

    Reply
  29. HIgor

    Кстати, сразу пожелание. Надо фиксировать текущего пользователя, кто внес изменения. Если с БД работает человек 30 и у многих права взаимозаменяемы. То потом не разгрести — кто накосячил.

    Reply
  30. HIgor

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

    Можно добавить как пожелание к развитию фильтр по типам документов. Можно тупо группы сделать равные типам.

    Reply
  31. HIgor

    Последняя версия УПП:

    Добавлен механизм «Версионирование»

    Механизм версионирования объектов используется для аудита изменений объектов информационной базы в разрезе времени и позволяет ответить на вопросы КТО, КОГДА и ЧТО изменил. В качестве версионируемых объектов могут выступать справочники и документы

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

    Reply
  32. Юля_1

    Вчера объединили конфигурации — выложенную здесь и свою (УПП 1.1). Сегодня целый день юзеры в шоке: обработка клиент-банк не запускается, отчет Декларация по НДС не формируется, цвета надписей и фона поменялись:))) Ну ничего, программист денек поисправлял и все пучком:))

    Reply
  33. wolf_az

    Огромное Спабибо! Просто и со вкусомммммммммммм!

    Reply
  34. androidT1C

    Удобная вещь. Еще бы добавить:

    — анализ изменений в регистрах сведений (например, кто цену поменял)

    — выбор объектов, для которых фиксировать изменения

    Reply
  35. alexer

    Перебрав множество подобных разработок, остановились именно на этой, т.к. она бесплатна и не требует существенных изменений конфигурации.

    Только были сделаны следующие доработки (тюнинг):

    1. Справочник ЖурналРегистрацииИзмененияОбъектов, в ТЧ у реквизитов СтароеЗначение и НовоеЗначение тип вместо «Строка» стал составной «Строка,ЛюбаяСсылка», теперь можно просматривать ссылки ТЧ (бывает, что номенклатура имеет одинаковое наименование, но разный артикул).

    2. Изменен функционал:

    2.1. Если ТЧ Объекта строка сменила НомерСтроки, то в ЖурналРегистрацииИзмененияОбъекта делается одна запись: «Строка изменена», что существенно уменьшает рост БД, раньше делалось несколько записей по количеству реквизитов ТЧ, и еще «Строка добавлена»,»Строка удалена».

    2.2. Реквизиты ТЧ Объекта были поделены на Ключевые И НеКлючевые, к НеКлючевым относятся реквизиты, имеющие простой тип(Число,Строка,Булево…). Если было изменение значения НеКлючевого реквизита, а значения Ключевых реквизитов не сменились, то в ЖурналРегистрацииИзмененияОбъекта делается запись «Строка изменена», раньше делалось несколько записей по количеству реквизитов ТЧ, и еще «Строка добавлена»,»Строка удалена».

    3. Сменился Интерфейс обработки ЖурналИзменений, основные изменения коснулись просмотра ТЧ объекта.

    4. От Подсистемы.РегистрацияИзмененийВОбъектах и РегламентныеЗадания.ОчисткаЖурнала отказались, за ненадобностью. Обошлись только ОбщимМодулем, ПодпискамиНаСобытие, Справочником и Обработкой.

    И вот что получилось: Скриншот здесь

    Прикрепить картинку почему-то не получилось. 🙁

    Автору спасибо!!!

    Reply
  36. Svattt

    alexer , а то, что получилось, на ИСе выложите?

    Reply
  37. alexer

    (36) Могу конечно, только для этого необходимо разрешение PowerBoy

    Reply
  38. Eraser1

    {Справочник.Товары.Форма.ФормаСписка(16,19)}: Переменная не определена (глСписокТипЦен)

    Для Счетчик=0 по <<?>>глСписокТипЦен.Количество()-1 цикл

    {Справочник.Товары.Форма.ФормаСписка(18,27)}: Переменная не определена (глСписокТипЦен)

    НовСтрока.Колонка1 = <<?>>глСписокТипЦен.Получить(Счетчик).Значение;

    {Справочник.Товары.Форма.ФормаСписка(44,114)}: Переменная не определена (глСписокТипЦен)

    СтруктураЦен = РегЦены.ПолучитьПоследнее(ТекущаяДата(),Новый Структура(«Товар, ТипЦен»,Элемент.ТекущаяСтрока,<<?>>глСписокТипЦен.Получить(Счетчик).Значение));

    {Справочник.Товары.Форма.ФормаСписка(21,54)}: Переменная не определена (глПользовательСистемы)

    СпрТовВыборка = Справочники.СкладыВТоварах.Выбрать(,<<?>>глПользовательСистемы,,»Номер Возр»);

    {Справочник.Товары.Форма.ФормаСписка(159,45)}: Переменная не определена (глПользовательСистемы)

    ЗапросСклада.УстановитьПараметр(«Владелец»,<<?>>глПользовательСистемы);

    {Справочник.Товары.Форма.ФормаСписка(248,55)}: Переменная не определена (глПользовательСистемы)

    СпрТовВыборка = Справочники.СкладыВТоварах.Выбрать(,<<?>>глПользовательСистемы);

    При выборе товара выдает такую ошибку в чем причина не могу найти подскажите?

    Reply
  39. PowerBoy

    (37) Да пожалуста, выкладывайте. Толко ссылку на первоисточник разместите и все.

    Reply
  40. alexer

    (39)(36) Выложил http://infostart.ru/public/63420/

    Reply
  41. Evgeniy

    Вещь супер, но возникла проблема с удалением помеченных на удаление объектов.

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

    Посему обращаюьсь к автору данной вещички с данной проблемой.

    Есть какие наработки для устранения этого бага?

    Reply
  42. PowerBoy

    (41) смотри (40)

    Reply
  43. axae

    Спасибо! Еще хотелось бы регистрацию удаления документов

    Reply
  44. natlens

    Ценная вещь! Очень помогла!

    Reply
  45. Mshaydurov

    PowerBoy, а все таки как дела обстоят с удалением объектов? В том числе непосредственным?

    Reply
  46. microkontrol

    С чем может быть связана ошибка «Ошибка формата потока»

    {Форма.Форма.Форма(122)}: Ошибка при вызове метода контекста (ЗначениеИзСтрокиВнутр)
    стрТч.ДоИзменения=ЗначениеИзСтрокиВнутр(Выборка.СтароеЗначение);
    по причине:
    Ошибка преобразования
    по причине:
    Ошибка формата потока
    
    Reply
  47. anton-1c

    Удобная вещь, спасибо

    Reply
  48. DenSergeev1968

    Спасибо, будем тестить!

    Reply
  49. edyardg

    Удобная вещь давно искал!

    Reply
  50. shatshat

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

    спасибо за отличное начало. вещь очень нужная

    Reply
  51. 4ur

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

    Reply
  52. 3sf

    Отличная вещь! Спасибо!

    Reply
  53. dyak84

    Автор подскажите каствомк будет проходить работа с большими базами да них на SQL и огоромным количеством пользователей. Подвисать не будет. А можно как то организовать хранение етой базы в отдельной базе. Зарание спасибо за ответ.

    Reply
  54. PowerBoy

    (54) Развитие обработки и вопросы смотрите здесь:

    http://infostart.ru/public/63420/

    Reply
  55. nikkolay

    надо опробывать! Спасибо!

    Reply

Leave a Comment

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