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




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

36 Comments

  1. Aleksey_3

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

    А по поводу регионов … к примеру в БП 2.0 появился механизм дополнительных реквизитов, который прекрасно вписывается в типовые отчеты и позволяет пользователю отбирать по этим реквизитам

    Reply ↓
  2. iov

    Встречал решение с использованием «свойств документов» соответственно отчеты строились дольше но при обновлениях проблем не было…

    Но как говорится каждое решение имеет место быть..

    Reply ↓
  3. wirg

    как обычно, автор не учел категорий и свойств, на крайняк можно из регистратора всё взять и ничего особенно не менять.

    Reply ↓
  4. zfilin

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

    Вы, конечно, правы про категории и свойства и про проведение документа. Но, как сказал уважемый iov, решений может множество. Все зависит от конкретной ситуации.

    Reply ↓
  5. DoctorRoza

    Согласен с Aleksey_3 по поводу работы с транзакциями и блокировками. Это основные, подводные камени, которые следует учитывать при работе в клиент-серверном режиме. Предложенное автором увеличивает объем базы, но решает проблему обновления, в первом приближении. Наибольший интерес вызывает применение данного метода к 8.2! Тут уже придется учесть еще и применение директив компиляции у процедур и функций!

    P.s. Идея, в принципе не нова, но за понятное, общее объяснение принципа плюсану! ))

    Reply ↓
  6. SergeyT2006

    Для 8.0 не подходит, ибо нет там механизма подписки

    Reply ↓
  7. Craig

    ХМ… возможно вы меня раскритикуете, но не проще было бы создать Справочник.Регион. с реквизитами типа «Регион» и «Ссылка на документ». И добавить во вкладку ввод на основании. Где сразу же создается новая форма, пользователь может спокойной внести необходимые сведенья, нажмет сохранить и вот оно щастье. И выдернуть будет легко для отчета, сильно система не будет нагружена и самое главное обновить не составит особого труда… Ах да с транзакцией проблем не будет, да и по времени программирование по моему способу займет гораздо меньше.

    Reply ↓
  8. zfilin

    DoctorRoza: Спасибо!

    SergeyT2006: Спасибо, подредактирую тэги.

    Craig: Я уже заметил что пример слишком простой. Может быть нужно было описывать две дополнительные аналитики одновременно или ввести дополнительные ограничения, которые бываю (например, когда документ-обертка должен делать ЕЩЕ и свои движения). Но зато такое мое упрощение примера натолкнуло меня на новые мысли благодаря вашим комментариям.

    Reply ↓
  9. KRIHA

    а еще полезно общие модули копировать :), из которых вызываются процедуры и функции документа «обертки» ), а то как обновиццо конфига — общие модули перемелятся в труху, функции и процедуры поменяют место жительства и «ФИО» и все — играла волына и доигралась 🙂 — не будет работать документ «обертка», а ты к тому времени (по заявкам телезрителей) — накрутил много много фенечек и терять все это жалко.

    Reply ↓
  10. o.nikolaev

    Вообще, если бы в 8-ку добавили понятие «Модуль» такое же как понятие «Форма», то все было бы гораздо проще. Имеем: Форма — ОсновнойМодульФормы, дополнительные модули формы, Документ — ОсновнойМодульДокумента, дополнительные модули документа, тогда все изменения сводились бы к тому что основные модули отцеплялись и основными делались бы добавляемые модули. Т.е. грубо говоря нужно в платформу добавить понятие «МодульОбъекта» и иметь возможность работать с ним так же как сейчас с формами. Надеюсь понятно объяснил 🙂

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

    Reply ↓
  11. tango

    чёта туплю я. зачем обновляться, если потом «перецеплять обратно основные объекты»?

    Reply ↓
  12. zfilin

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

    Reply ↓
  13. alexk-is

    (0) Можно не создавать дополнительный документ, а добавить только реквизит и форму в существующий документ. Проблем с обновлением быть не должно, если знаешь как обновлять.

    Текст модуля в публикации можно раскрасить получше. 🙂

    Reply ↓
  14. zfilin

    Спасибо, отлично раскрашивает. =)

    И статья об обновлении хорошая.

    Reply ↓
  15. sss999

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

    Reply ↓
  16. ups9999

    Гы. Добавляем реквизиты объекту. Переопределяем «ПередОткрытием» динамически добавляем реквизиты на форму. Подписка обеспечит нужное проведение. Все имения кода это 3 добавленные в модуль строчки. Их полагаю любой может перенести при обновлении 😉

    Reply ↓
  17. tango

    (12) ок. «полезные» изменения 1с — там, где «перецепляем» или где-то в другом объекте?

    Если там же, то по-любасику надо адекватно изменять свое. Если в стороне — то и обновляем только это. Что пропустил?

    Reply ↓
  18. mus2008

    Жуть. Может пример неудачный приведен? Дублировать документы из за реквизита? Если уж на то пошло, проще создать регистр сведений и посредством его увязать контрагентов и регионы. Это самый простой вариант. Второй, чуть более сложный — свойства сделать у контрагента. В бухгалтерии этого нет, но привязывается легко. В крупных конфах это уже есть. Но тогда:

    База не пухнет необоснованно (я считаю, что в данном случае это именно так).

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

    И восстановление последовательности, особенно накрученное, когда .Восстановить() не прокатывает. Там вообще че-то малопредставимое будет…

    Reply ↓
  19. FormatC

    Замечу, что иногда в типовых конфигурациях некоторые отчеты работают с привязкой к конкретному виду документа. Например, в КА отчеты по заказам и резервированию. И данный способ не прокатит.

    Reply ↓
  20. zfilin

    FormatC: Да, ну, так ведь фишка именно в том, что движения делает именно родной документ.

    А отчеты, которые будут учитывать и дополнительную аналитику все-равно писать самому.

    Reply ↓
  21. zfilin

    tango: Ну, да. Об этом и статья.

    Reply ↓
  22. PopAndr

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

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

    2. Новая форма стандартного документа, в которую добавлено поле редактирования записи регистра сведений. При этом нет необходимости делать его с привязкой к регистратору, достаточно сделать измерение регистра по документу ведущим.

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

    Reply ↓
  23. Арчибальд

    Решение спорно. Но изложено внятно, а предмет статьи актуален. Ergo, плюс.

    Reply ↓
  24. RailMen

    Комменты не менее ценные чем самастатья 😉

    Reply ↓
  25. I_G_O_R

    регистры, дополнительные формы, дополнительные документы….

    а про пользователя и не подумали: будет ли ему удобно так работать?

    Reply ↓
  26. zfilin

    I_G_O_R: Подумал — неудобно. О чем и писал. А на самом деле все зависит от реализации, порой пользователю оказываются удобны самые неожиданные вещи. =)

    Reply ↓
  27. flagman

    статья писалась не для внесения одного реквизита. Сам делал практически тоже самое: нужен был аналог «поступления товаров» и «расходной накладной» НО со своими табличными частями, кучей доп. реквизитов, + движения по 5 НОВЫМ опер. регистрам.

    отличие от статьи только в том, что на типовой документ, кот. создан автоматически накладывался ПОЛНЫЙ запрет на изменение (контролировалось по тому же самому регистру сведений). Т.е. все изменения только ч/з новый документ.

    Основная беда — потеря скорости проведения документов (за счет необходимости синхронизации). Но расхождений данных нет

    Reply ↓
  28. gusinea

    Согласен с «PopAndr» можно сделать доп. форму в том же документе, назначить её ОСНОВНОЙ, а при обновлении максимум что случится — слетит эта настройка(поправляется в течении неск. секуд). Зато отпадает надобность в синхронизации документов

    Reply ↓
  29. aegoncharov

    Это же так называемая методика «мегадокументов». Позволяет создать прослойку между пользователем и типовым функционалом.

    4 основные проблемы:

    1. Длинные транзакции при записи

    2. Более быстрый рост базы

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

    4. Усложняется настройка обмена в распределенных базах.

    С проблемой №1 наверное буду бороться, реализовав «отложенное создание» подчиненных документов.

    Reply ↓
  30. Lancelot-2M

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

    Reply ↓
  31. zhleonid8

    эту статью нужно в первый день работы програмисту дать

    Reply ↓
  32. zhleonid8

    а то по очереди исправляют, а обновлять потом не возможно:)

    Reply ↓
  33. zfilin

    Ну, я бы в первый день не советовал. Потому-что в классическом понимании это все-таки «чесать левое ухо левой рукой через голову». Скорее это подойдет для отчаявшихся людей, которые устали тратить все время своей жизни на то, чтобы беспрестанно сверять конфигурации и ползать по-коду в поиске различий, но хотят что-то в жизни поменять.

    В общем, тут нужен баланс между «не трогать как есть» и «добавить немного», понимание ситуации, ну и включение мозга в целом. А-то дашь новичку такую статью, а он ради одного реквизита целую подсистему наворотит. И хрен разберешься потом.

    Но с тем, что «а то по очереди исправляют, а обновлять потом не возможно» согласен. Достали до невозможности. =)

    Reply ↓
  34. zfilin

    Да, и кстати, это все в конечном итоге упирается в «золото разработки», такое как «изоляция кода», «декларирование интерфейсов» и прочее. Эх, когда уже заживем по-человечески?!… =)

    Reply ↓
  35. zhleonid8

    в результате 2 летней работы в 8 понятно, лучше не изменять код а решать штатными средствами

    Reply ↓
  36. zfilin

    Ага. Самый лучший способ разработки — ничего не разрабатывать.

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

    Reply ↓

Leave a Comment

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