Набор функций, возвращающих данные из истории версий объекта или "Кто виноват?" оптом




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

33 Comments

  1. zeegin

    Разве это не типовой функционал БСП?

    Документация:

    https://its.1c.ru/db/bsp302doc#content:1858:1:issogl1_%D0%BF%D1%80%D0%BE%D1%81%D0%BC%D0%BE%D1%82%D1%80_%D0­%B8%D1%81%D1%82%D0%BE%D1%80%D0%B8%D0%B8_%D0%B8%D0%B7%D0%BC%D­0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D0%B9_%D0%BE%D0%B1%D1%8A%D0%B5%­D0%BA%D1%82%D0%B0

    Можно перейти к отчету по всем версиям объектов и отобрать в каких версиях конкретные интересующие реквизиты менялись…

    Reply
  2. user633533_encantado

    «Найти решения не удалось» — садись, два. Идите учить БСП и на пересдачу.

    Reply
  3. Rustig

    (1) круто придумали!

    что еще я не знаю?

    Reply
  4. Rustig

    (2) не кидайте камнями — это легче всего, покажите путь и дайте фонарь

    Reply
  5. user633533_encantado

    (4) Открываем конфигурацию «Библиотека стандартных подсистем» и изучаем подсистему «Версионирование объектов».

    Что же вы там за «проекты» делаете с такими знаниями типовых подсистем ?

    Reply
  6. feva

    (5) Хорошо, простой вопрос — какая функция мне вернет одно значение — кто изменил реквизит?

    Reply
  7. feva

    (1) Абсолютно верно, именно об этом и и писал в самом начале статьи, рад что вы «Внимательно» прочитали

    Reply
  8. feva

    (1)

    Хотелось бы отметить, что программирование в наше время, призвано облегчить работу пользователям и уменьшить количество кликов совершаемых ими до минимума, это и может послужить ответом на вопрос «Почему нельзя просто посмотреть сравнение версий объектов ткнув туда, потом туда, затем туда и потом ещё два раза»
    Reply
  9. feva

    (2) Товарищ магистр БСП, подскажите неучу каким образом можно получить в отчет на СКД кто изменил тот или иной реквизит

    Reply
  10. user633533_encantado

    (9) Не подскажу, так как это нафиг никому не нужная вещь , есть типовой отчет сравнения версий вызываемый из любого объекта подключенного к подсистеме.

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

    Reply
  11. feva

    (10)т.е. нет такого функционала в БСП? Или Вы плохо знаете БСП?

    Про типовой отчет сравнения версий написано ещё в начале статьи, и почему он не используется в некоторых случаях.

    Reply
  12. zeegin

    (11) Т.е. заполнить левую форму отбора набором параметров проще, чем пару раз ткнуть?

    Ответ на вопрос-то где? «Почему нельзя просто посмотреть сравнение версий объектов ткнув туда, потом туда, затем туда и потом ещё два раза». Что улучшено? Как было, как сейчас? Почему это лучше в вашем сценарии? Почему в общем случае лучше БСП, а не ваш сценарий?

    Где ответы на вопросы? Я вижу портянку текста кода и поноса мыслей, простите, а ответа на то почему стало лучше решать главный вопрос «КТО ПОСЛЕДНИЙ МЕНЯЛ?!?» не вижу.

    Reply
  13. feva

    (12)Левая форма была как пример использования функций.

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

    Вопрос — сколько нужно действий что бы проверить 1000 реализаций?

    Reply
  14. feva

    (12) все ответы в конце статьи, зачем использовать эти функции, их минусы и плюсы.

    это расширяет функционал СКД и позволит получать сведения о интересующих нас пользователях в отчетах и «давать по рукам» в режиме online и оптом.

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

    Reply
  15. zeegin

    (14) т.е. это не общее решение, а точечно, да еще и программировать надо…

    и это вместо того, чтобы, считаем:

    1. перейти на вкладку

    2. открыть форму отбора реквизита по которому надо найти изменения

    3. применить отбор

    4. нажать кнопку сравнения версий

    Вот если выбирать что проще, написать отчет или сделать кнопку с выводом или это же сделать в форме отчета бсп в режиме пользователя, что проще?

    Reply
  16. zeegin

    (13) Зачем проверять 1000 реализаций? Какая проблема решается?

    Reply
  17. bulpi

    Не понял. Что это за регистр ВерсииОбъектов ?

    Разве в новой платформе версионирование не встроено ?

    Reply
  18. Rustig

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

    Reply
  19. muskul

    (16)Например проблема кто и когда менял документы за определенный период. Этого отчета очень нехватает в типовых конфигурациях. Клиент хочет знать простой ответ, кто менял какие документы.

    Reply
  20. feva

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

    Reply
  21. feva

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

    Reply
  22. feva

    (18) Абсолютно верно!

    Reply
  23. feva

    (15) С точки зрения программирования — проще отправить пользователя в типовой. Это не замена ему, а расширение. Для решения локальной задачи в рамках одного объекта, в большинстве случаев, лучше использовать типовой вариант. Данное решение имеет место быть если нужно получать информацию по большому объему объектов.

    Reply
  24. zeegin

    (19) Журнал регистрации?

    Reply
  25. zeegin

    (21) Зачем для такого отчета версии? Для премирования надо использовать реальные продажи и реальные полученные деньги, а не скидку, которая потом была отменена. Да и вообще строить отчет с аналитикой для принятия управленческого решения по данным из документа, а не из регистра, это моветон.

    Reply
  26. acanta

    Можно ли по регистру сведений получить срез последних и показать отдельной колонкой к примеру в справочнике контрагенты (форма списка) дату и автора последних изменений (и вообще имеет ли смысл записывать признак изменения и авторство в элемент справочника партнеры при модификации к примеру соглашения или условий договора) вместо/по аналогии с типовой датой создания и менеджером?

    Reply
  27. muskul

    (24) можешь пример отчета из такого журнала привести.Период месяц показать все реализации которые менялись в этом месяце.

    Reply
  28. zeegin

    (27) Администрирование, Обслуживание, Журнал регистрации, Установить отбор: Интервал, События, Метаданные.

    Reply
  29. feva

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

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

    Reply
  30. feva

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

    На местах могут работать команды которые заводят и редактируют данные в хаотичном порядке. Менеджером продажи выступает один человек, о ценах договаривался другой человек, отгрузку и логистику рассчитывал третий человек, и если изначально не реализовано техническим, что фиксируется кто последний менял, а потом за год хотят получить эти данные, то журнал регистрации не несёт в себе ни какие были данные, ни когда их устанавливали. А когда штат работающий с 1с переваливает за 1к пользователей с каждой обособкой разбираться никто не захочет, но данные требуют уже вчера. По этому и приходится делать варварские решения (почему они не эффективны тоже описано в статье), но предоставляющие необходимые данные. Бывают и другие жизненные ситуации когда данные можно получить из регистра версий, но как правило приходилось отказывать клиентам.

    Reply
  31. feva

    (25) С опытом, и в Вашей практике появятся задачи требующие решения, пусть и не самого рационального на первый взгляд и это не единственный случай.

    Reply
  32. muskul

    (28)И он тебе покажет все документы которые записывал менеджер за месяц. а нужны только дважды записанные.

    Reply
  33. androgin

    Устарело.

    В текущих версиях можно использовать ИсториюДанных.

    Ну или журнал регистрации будет интересней, чем версионирование.

    Надеюсь в скором будущем 1С откажется от этой подсистемы в пользу ИсторииДанных

    Reply

Leave a Comment

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