Кто и что изменял в документе




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

57 Comments

  1. CheBurator

    Антон! а прокомментируйте, плиз, — ловит ваша разработка протое изменение порядка строк (считаем что это не изменение), добавление строк, удаление строк? Прокомментируйте чуть подробнее.. в каком формате хранится, как логгируется?

    Reply ↓
  2. antonrost

    Исправил

    вместо

    ТЗ.Автор = глПользователь;

    теперь

    ТЗ.Автор = ?(ПустоеЗначение(ПолноеИмяПользователя())=0,ПолноеИмяПользователя(),ИмяПользователя());

    Reply ↓
  3. antonrost

    1. Хранится в виде файла: «ЗначениеВФайл(ИмяФайла, ТаблицаИзменений)»

    При этом файлы имеет вид: КаталогБазыLogВидДокументаВнутреннийНомерДокументаНомерИ­зменения.txt

    (Например: D:БазыТоргDemoDBLogПоступлениеТМЦ3470002.TXT)

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

    3. Добавление и удаление строк отслеживается. Принцип просмотра изменений ТЧ следующий (он, кстати, продемонстрирован в скриншотах): если есть измененная строка, то в результатах мы увидим ДВЕ СТРОКИ. Одна со знаком «-» (то, что было до изменения), вторая со знаком «+» (то, что стало). Измененные реквизиты выделены цветом. Для удобства сравнения рекомендуется отсортировать таблицу по ключевым реквизитам (например, по номенклатуре) двойным щелчком по наименованию колонки. Соответственно, если количество строк изменилось, то будет ТОЛЬКО строка с минусом (если строку удалили), или ТОЛЬКО строка с плюсам, если строку добавили.

    Reply ↓
  4. antonrost

    При снятии флажка «Только измененные реквизиты», в отчет выведутся ВСЕ реквизиты документа. Измененные также останутся выделенными цветом.

    Reply ↓
  5. antonrost

    Если у кого-то есть необходимость отслеживать изменение порядка строк — говорите. Добавлю через некоторое время.

    Reply ↓
  6. antonrost

    70 человек скачали, никто не оценил. Вывод: кг/ам ???

    Reply ↓
  7. Abadonna

    Совсем недавноя делал подобную штуку. Умудрился запихать весь документ в одну «плоскую» ТЗ из 4 колонок. Т.е. в этой 4-х колоночной ТЗ хранятся разом и общие, и реквизиты шапки, и все строчки документа.

    Если интересно — могу намылить.

    Примечание: а т.к. у нас всё равно SQL стоял, я завел «боковую» базу

    Change с одной таблицей того же наименования, где в текстовых полях хранятся значения типа ЗначениеВСтрокуВнутр(). Табличка получилась универсальная — и для доков, и для справочников.

    Контрагенты! Вот где они, гады, творят, что хотят, а потом отпираются 😉

    Reply ↓
  8. antonrost

    И у меня тоже одна ТЗ. Только колонок пять :).

    Reply ↓
  9. wadus

    Внедрил в свою конфигурацию. Шеф в восторге (неописуемом).

    Вопрос: можно тоже самое, но для справочников?

    Reply ↓
  10. CheBurator

    Изменения пишутся в какой файл? текстовый? xml?

    или как еще…? в принципе, нормально, вопрос с типом файла выясню — может поставлю вместо своей…

    Reply ↓
  11. antonrost

    Применяется метод «ЗначениеВФайл».

    Минус — на больших конфигурациях «жрет» дисковое пространство. Есть идея архивировать каждый документ. Нет времени. 🙂

    Со временем приделаю и справочники.

    Reply ↓
  12. antonrost

    Вернее, на больших базах…

    Reply ↓
  13. Denisыч

    Очень хорошая разработка. Хотелось бы еще изменения справочников увидеть. Когда можете сделать?

    Reply ↓
  14. antonrost

    Банально не хватает времени 🙁

    Reply ↓
  15. lustin

    +1

    Reply ↓
  16. glavbukh

    +1. Присоединяюсь к Denisыч : «Ну когда же…»?

    Reply ↓
  17. antonrost

    Скоро. Для себя сделал — тестирую.

    Reply ↓
  18. gubsky

    ну и что там на счет справочников? как тема движется?

    Reply ↓
  19. antonrost

    Выложил новую версию (документы + справочники). Описание внутри архива. Извиняюсь, если не очень подробное.

    Если что-то неработает — обращайтесь, разберусь.

    Reply ↓
  20. infossa

    (19) обработка интересная и полезная

    (7) также интересует вариант для SQL Server

    если можно , то выложите здесь также свой вариант

    Reply ↓
  21. mdzen

    Интересно. Сравню со своей….

    Reply ↓
  22. mdzen

    В принципе неплохо как идея.

    Только есть небольшое неудобство — доки в среднем 100 — 150 позиций занимают 56-80 кб. , за день лепят до 100 документов — по минимуму за день отожрет 56 — 80Mb если нет изменений, а если хоть по разу поменяют это еще 56-80 Mb , итого — 112 — 160 Мб ( т.е. полтора гига за 10 дней), а если надо логи за год-полтора иметь?

    Для организаций с небольшим документо-потоком решение отличное ( потому +1)

    Reply ↓
  23. Polukuzov

    Я переделал процедуру хранения изменений(изменения по одному документу храняться в виде архива.zip и при надобности распоковывается во временную папку добавляется и снова упаковывается) при этом достигается экономия по месту хранения в 5-6 раз, а это уже что-то. А так вообще вещь нужная правда слегонца громоздкая. Много места занимает хранение в ввиде «ЗначениеВСтрокуВнутр» там куча скобок,кавычек и пробелов, но писать свою процедуру хранения как-то совсем неохота. Автору риспект +1

    Reply ↓
  24. antonrost

    Теперь корректно работает в распределенных базах.

    Reply ↓
  25. Mario Bro

    я не програмист 1С но нам в фирму очень нужна подобная вещь, скачал, дак на работе блин даже ЗИП-аврхиваторов нету блин:(

    Reply ↓
  26. antonrost

    давай адрес — вышлю

    Reply ↓
  27. Mario Bro

    Разархивировал но там как я понял документы уже для внедрения в 1С, надо будет программиста нашего загрузить

    Reply ↓
  28. Mario Bro

    А нет чё нить типа презентации данной функции)))

    Reply ↓
  29. antonrost

    Скриншоты не подходят ?

    Reply ↓
  30. Mario Bro

    antonrost

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

    Reply ↓
  31. Fedorenko

    Попробовал на документе Реализация в Торговля и Склад 7.7. Обработка «Просмотр изменений в документах и справочниках.ert» пишет ошибку:

    Стр = ЗначениеВСтрокуВнутр(СоздатьОбъект(Шаблон(«[ТекТип].[ТекВид]»)));

    {E:TORGEXTFORMSПРОСМОТР ИЗМЕНЕНИЙ В ДОКУМЕНТАХ И СПРАВОЧНИКАХ.ERT(144)}: Неудачная попытка создания объекта.

    Обработка «ПРОСМОТР ИЗМЕНЕНИЙ.ERT» выдает ошибку: ВидЭлемента = Конт.Вид();

    {E:TORGEXTFORMSПРОСМОТР ИЗМЕНЕНИЙ.ERT(230)}: Значение не представляет агрегатный объект (Вид).

    Reply ↓
  32. antonrost

    (31) Загляни в личные сообщения.

    Reply ↓
  33. antonrost

    Глючила функция «Шаблон». Исправил.

    Reply ↓
  34. GenTay

    Идея очень хорошая, но оценить не могу, т.к. теже ошибки что и у сообщ. № 31

    Reply ↓
  35. GenTay

    И еще при проводке сообщает {D:ПАПКА ОБМЕНАПРОБАEXTFORMSРЕГИСТРАЦИЯ ИЗМЕНЕНИЙ.ERT(36)}: Функция не обнаружена (глРазложить)

    Reply ↓
  36. antonrost

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

    Reply ↓
  37. GenTay

    Осталось

    Конт = Форма.Параметр;

    ВидЭлемента = Конт.Вид();

    {Обработка.РегистрацияИзменений.Форма.Модуль(230)}: Значение не представляет агрегатный объект (Вид)

    Reply ↓
  38. GenTay

    Пардон, плз. Это у меня глюки. Все заработало, но когда прошу показать изменения, выдает что-то про точку актуальности, но 1с бух нет оперативных итогов!

    Reply ↓
  39. antonrost

    Сейчас исправлю.

    Reply ↓
  40. antonrost

    Исправлено.

    Reply ↓
  41. GenTay

    Просто супер!!!!!

    Reply ↓
  42. GenTay

    Привет! Не хочу надоедать, но какой-то конфуз у меня. Вчера все поставил, все работало. А сегодня не работает, причем в папке «log» создает ссылки, в отчете «просмотр изм в доках и спр» выдает в вверху,ну к примеру, «прих.накл». Но перечень изменений зась. Пишет «0 строк». Изменения были.Вчерашние изменения пожалуйста, сегодняшие ни как. Я глянул код, китайская грамота на русском языке, учебник квантовой физики. Что бы это значило?

    Reply ↓
  43. antonrost

    Напиши на мыло a.yuhlin@empils.ru

    Reply ↓
  44. korpas

    Обновил файлы на новую версию. При попытке посмотреть изменения вылетают следующие ошибки:

    КодВида = СЗ.ПолучитьЗначение(2);

    {\…EXTFORMSПРОСМОТР ИЗМЕНЕНИЙ В ДОКУМЕНТАХ И СПРАВОЧНИКАХ.ERT(119)}: Индекс не входит в границы списка значений.

    КодЭл = СЗ.ПолучитьЗначение(3);

    {\…EXTFORMSПРОСМОТР ИЗМЕНЕНИЙ В ДОКУМЕНТАХ И СПРАВОЧНИКАХ.ERT(120)}: Индекс не входит в границы списка значений.

    КодБазы = СЗ.ПолучитьЗначение(4);

    {\…EXTFORMSПРОСМОТР ИЗМЕНЕНИЙ В ДОКУМЕНТАХ И СПРАВОЧНИКАХ.ERT(121)}: Индекс не входит в границы списка значений.

    Таблица документов не заполняется. В старой версии все работает.

    Reply ↓
  45. antonrost

    (45) Боюсь, что совместимость не предусмотрена 🙁 , т.е. новый просмотрщик показывает только новые изменения.

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

    Reply ↓
  46. korpas

    (46)

    1) Сильно изменился формат хранения? Заметил пару новых функций, в остальное не внедрялся…

    2) У меня был случай, что обработка показывала изменения человеком, который их в это время не делал, а делал другой человек. Я думал, что это связано с открытием одного документа двумя пользователями: одним на редактирование, вторым на просмотр, но воспроизвести такую ситуацию не смог. Возможны ли вообще случаи, что обработка покажет другого пользователя, не делавшего изменения?

    3) Как можно правильно перейти на новую версию обработки? Удалить Папку Log? Тогда в нее будут записываться изменения уже новой обработки?

    Reply ↓
  47. antonrost

    (47)

    1. Изменился только формат имени файла.

    2. Если документ изменен программно, то в LOG изменения будут добавлены при первом открытии документа и припишутся тому, кто его открыл. Чтобы такого не происходило, надо после Док.Записать() вызывать глРегистрацияИзменений().

    3. Если есть возможность очистить log, проще всего так и сделать.

    Reply ↓
  48. Ekstrem13

    Почему нет периода дат. Мне например нужно видеть изменения за конкретный квартал а не все

    Reply ↓
  49. rosalin

    Антон,

    Приветствую, скачал вашу обработочку отличная вещь внес изменения

    в ГМ

    но не могу сделать что бы работала кнопка

    по обработке «Просмотр изменений в документах и справочниках», все

    показывает

    а вот кнопка с формулой

    ОткрытьФорму(«Отчет#», ТекЭлемент, КаталогИБ()+»ExtFormsПросмотр изменений.ert»);

    ругаеться типа

    ОткрытьФорму(«Отчет<<?>>

    Пропущен символ ‘»‘ (двойная кавычка)

    ОткрытьФорму(«Отчет<<?>>

    Ожидается символ ‘)’

    Помогите плиз

    Reply ↓
  50. rosalin

    еще ругаеться

    ВидЭлемента = Конт.Вид();

    {W:ARCHIVE1903EXTFORMSПРОСМОТР ИЗМЕНЕНИЙ.ERT(195)}: Значение не представляет агрегатный объект (Вид)

    Reply ↓
  51. tanekQ

    Интересная вещица! А главное столько лет поддерживается и, соответственно, совершенствуется! Автору БОЛЬШОЙ плюс!

    Reply ↓
  52. grayglobus

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

    Reply ↓
  53. lees

    Для моей самописной небольшой базы объемом 1,5 ГБ хорошее решение задачи поиска виновных, спасибо большое

    Reply ↓
  54. merlin1975

    Здравия!

    Посмотрел Вашу обработку. Интересно. Начал пробовать. Внес изменения в глобальный модуль, встроил отчеты ПросмотрИзменений и РегистрацияИзменений. Немного из-за этого подправил код (на открытие встроенных отчетов).

    Внес изменения в один документ — логи создались. Решил посмотреть «Просмотр изменений в документах и справочниках» (код подправил на открытие встроенного отчета) — изменения документа показаны . Но, почему «Табличная часть посмотреть изменения» показываются все реквизиты а не только измененные? Можно ли как-то отобрать?

    И, при выборе на главной форме «Справочник» (я менял только один документ) — обработка впадает в ступор. Видимо ищет того, чего нет… Это у меня что-то плохо отрабатывает или сама обработка?

    Благодарю.

    Reply ↓
  55. merlin1975

    (7)Можно получить Ваш вариант обработки?

    Reply ↓
  56. merlin1975

    (23)Можно Вашу версию «пощупать»?

    Reply ↓
  57. antonrost

    (55)

    Писал эту обработку 13 лет назад, вообще не помню как там что работает )))

    1. Если в ТЧ показывать только измененные колонки, то может быть не видно ключевых, необходимых для понимания к чему относится данная строка. Например — не будет видно Номенклатуры, неудобно разбираться. Но при желании можно и скрыть их — кто мешает?

    2. Не понял сути вопроса.

    Reply ↓

Leave a Comment

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