Хранилище конфигурации: не очевидные особенности групповой разработки




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

33 Comments

  1. kapustinag

    C картинками какая-то проблема. Не отображаются картинки в тексте публикации, только место пустое. В трех доступных мне броузерах посмотрел — везде пусто. Или все-же у меня локальная проблема?

    Reply
  2. _also

    (1) kapustinag, проверьте сейчас, пожалуйста.

    Reply
  3. mentos
    Пользователей хранилища мы называем по имени базы на 1с сервере.

    вот за это спасибо 🙂 простейшая вещь, но в голову никогда не приходила

    Reply
  4. _also

    (3) mentos, да, это очень удобно

    Reply
  5. kapustinag

    Похоже, стоит фильтр на нашем прокси-сервере. Картинки-то не на сервере Инфостарта, а на google…

    С другого компьютера, внешнего, зашел — все Ок.

    Reply
  6. _also

    (5) kapustinag, видимо инфостарт не копирует лишнего на свой сервер. Я в статье делал вставить картинку и указывал url.

    Reply
  7. speshuric

    «Рабочая база подключена к хранилищу;» — после этого читать желание пропало.

    Reply
  8. _also

    (7) Поясните свою точку зрения

    Reply
  9. speshuric

    (8) _also

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

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

    Авральные исправления в этой схеме — снятие с поддержки и последующая загрузка конфы для обратной постановки. Тоже с нюансами, например, конечно, нужно не поломать конфу загрузкой.

    Если исправления не авральные, то как бонус — можно протестировать именно тот файл поставки, который пойдёт в бой, хотя б «джентельменский набор»: синтаксис, проверки конфы, логин админа, логин пользователя, время реструктуризации. Автоматизируется на раз-два, зато не сможете совершить ошибку, которую допустила 1С в релизе УПП 1.2.8:

    Исправлена ошибка 00092921:

    При входе пользователя не с полными правами происходит ошибка.

    Опять же заранее будет видно если косяк с реструктуризацией и т.п.

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

    Reply
  10. _also

    (9) speshuric,

    держать продуктовую базу у себя на поставке «на замочке»

    это мечта. Конкретно в наших реалиях авральных исправлений порой больше, чем нормальных обновлений, так что… НУ не можем мы себе такого позволить.

    Спасибо за схемку, подход у Вас очень правильный. Однако я считаю ее слишком тяжелой для случаев небольших баз, с небольшим количеством пользователей, И… с низкоквалифицированными программистами.

    В любом случае спасибо за конструктив, этого я и ждал 🙂

    Reply
  11. pumbaE

    (9) speshuric, не хватает хранилищу «веток».

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

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

    p.s: Имхо, вряд ли что-то изменится кардинально даже с выходом 8.3 и возможности тестирования, если сама 1С не повернетса к программистам и не будет пропогандировать «best practice» среди программистов и будет публиковать тесты к типовым конфигурациям (скептик во мне заявляет «Не бывать этому!»). Возможно будут единицы использовать тесты, чего таить и сам не без греха, но я то постараюсь вместе с Артуром Аюхановым поразрабатывать в стиле TDD , а основаня масса програмистов так и будет писать комментарии в коде «Здесь было Вася» и считать, что это верх совершенства в способах доработок типового кода, а про тестирование даже понятия не иметь.

    p.s.s: Я знаю, что автоматическое тестирование — это не волшебная пилюля.

    Reply
  12. _also

    (11) pumbaE, подписываюсь под каждым словом. Но думаю, что тестов к типовым мы так и не дождемся. И, кстати, даже «Здесь был Вася», к сожалению, не все пишут.

    Reply
  13. _also

    (11) pumbaE, Жень, а не тестировал работу с хранилищем в 8.3. 1С там заявляла какие-то ништяки. Мол работать будет сравнение быстрее?

    Reply
  14. pumbaE

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

    Reply
  15. _also

    (14) pumbaE, я понял. Надо что-то придумывать с ролями и частичной выгрузкой в xml 8.3 и переходить на git…

    Reply
  16. speshuric

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

    (11) pumbaE, Веток не хватает. Git не хватает с распределённой структурой. Есть такое. Но цикл сборка/поставка дисциплинирует вне зависимости от того есть тестировщик или нет. Просто же: собрал, проверил синтаксис и конфу на ошибки, проверил реструктуризацию, проверил логин великого админа и проверил логин твари ничтожной. Да хоть бы и в УПП — это займёт на нормальной железяке около получаса от силы. Не хочешь сам — отдай «подовану», заодно пусть посмотрит изменения и покритикует, если время есть. Выше приведён пример, что и фирма 1С когда-то забивала на эти проверки и к чему это приводило. Не нужен на этом уровне ни билдбот, ни отдельный тестер. Нужен просто этап «Я собрал поставку, я сейчас её накачу и хочу проверить, что мне не придётся сидеть 2 выходных и восстанавливать работу предприятия».

    Давайте не будем пенять на 1С и ждать когда она «повернетса к программистам» (кстати, какой стороной? 🙂 ). Хочется, чтобы был идеальный код — начни с себя и своего коллектива. Юнит-тестов не хватает? Так надо писать и показывать на практике результативность этого подхода, другие методы не сработают.

    Reply
  17. _also

    (16) speshuric, низкоквалифицированные сотрудники порождают такой код, что придется каждый день с поставки снимать.

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

    Reply
  18. Kutuzov

    Еще хотелось бы подробную инструкцию по настройке подключения к хранилищу через интернет.

    Reply
  19. SPID

    По поводу «Захватил корень — добавил объект — поместил корень — захватил объект и дальше его разрабатываеш» тоже кроется подвох, если этот объект регистр — нужно не забыть добавить хоть одно измерение и назначить регистратор, если он необходим. Если поместить пустой регистр в хранилище, то для разработчика получившего конфигурацию с хранилища ждет сюрприз — он не сможет обновить конфигурацию БД, конфигуратор будет «ругаться» на этот регистр без регистратора и/или без измерений.

    Reply
  20. _also

    (19) SPID, согласен. Вообще лучше все новые объекты, в том числе с реквизитами за один раз добавлять.

    Reply
  21. xzorkiix

    текст читаешь, приговаривая «конечно», «это же логично». Но всё равно полезно.

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

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

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

    Имхо, на инфостарт-евенте скорее такого простого доклада ожидал, а поверх какие плюшки появляются при внедрении иных продуктов, технологий, методологий.

    Reply
  22. pumbaE

    (21) xzorkiix, не ставил себе целью описания работы с хранилищем. Рассказывать банальные вещи не очень хочется ни мне и вам их слушать тоже думаю не сильно охота.

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

    p.s.: Ben Collins-Sussman: Итак есть два «класса» программистов-разработчиков, назовем их «20%» и «80%», основная движущая сила индуструии программного обеспечения — это «80%»-ные парни… Их знаний в точности достаточно, что бы сделать свою работу, затем пойти домой и забыть о комьютерах…

    Жутка правда №1 — Основной объем…ПО — создается вышеупомянутыми «80%» программистов.

    Жуткая правда №2 — Большинство «альфа — гиков» забывают «жуткую правду №1» .

    Вышеупомянутым программистам вообще трудно использовать контроль версий, а вы собираетесь объяснять им разницу между «pull» и «update»…

    Ben Collins-Sussman — автор svn.

    Reply
  23. laduk

    Статья ни о чем, да еще и с неадекватными советами типа: «имя пользователя по имени базы и одинаковые пароли» — по моему полнейший бред;

    «Рабочая база автоматически обновляется из хранилища» — да за такое руки поотрывать мало

    Reply
  24. _also

    (23) laduk, я рад, что Вам понравилось )

    Reply
  25. zqzq
    имя пользователя по имени базы и одинаковые пароли

    ИМХО лучше на каждого программиста своего пользователя (с правами захвата) + админа хранилища + юзера с правами только на чтение для обновления рабочей из хранилища (лучше заходить с одного сервера). Тогда и нормальный отчет по истории работы с хранилищем будет. Естественно, для сложных случаев лучше рабочую обновлять поставками/объединением.

    Reply
  26. cdover

    всё по полочкам. Спасибо!

    Reply
  27. omut

    (9) speshuric, полностью поддерживаю. Сам работаю точно по такой же схеме 🙂

    Отдельно по запуску (пароли, пароли, пароли…) У кого нет снегопата: напишите батник с параметрами запуска и сразу попадете в конфигуратор под нужным пользователем в нужную базу и подключением к хранилищу. Если баз много, то файлов будет тоже много. Но это уже, что называется, на любителя. На всякий случай, если кто не знает, пример строки в батнике такой:

    «C:Program Files (x86)1cv82ВАША_ВЕРСИЯ_ПЛАТФОРМЫin1cv8.exe» DESIGNER /S СЕРВЕР_1С/ИМЯ_БД_1С /NИМЯ_ПОЛЬЗОВАТЕЛЯ_1С /PПАРОЛЬ_ПОЛЬЗОВАТЕЛЯ_1С /ConfigurationRepositoryNИМЯ_ПОЛЬЗОВАТЕЛЯ_ХРАЛИНИЩА /ConfigurationRepositoryPПАРОЛЬ_ПОЛЬЗОВАТЕЛЯ_ХРАНИЛИЩА (для клиент-серверной БД, если файловая база, то вместо /S ставим /F и дальше папку БД вместо сервера и имени БД)

    Reply
  28. Templ

    Из-за чего может быть. Внесли изменения из хранлища в основную базу. И оказалось что в рабочую базу затянулось старая версия изменений.

    Reply
  29. Stas-ch

    (27) omut,

    а зачем батники? Можно ведь все прописать сразу в параметрах запуска 1С. Из минусов — надо прописывать у всех, кто работает с базой (копи-паст рулит), зато нет кучи батников.

    Reply
  30. Stas-ch

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

    т.е. средствами SQL скопировали базу, старую убили (или пока еще нет, но скоро убьют). Захожу в новую базу а информации о подключении ее к хранилищу нет — при попытке подключения к хранилищу вся информация замещается данными хранилища. Приходится выгружать через конфигуратор все изменения и закачивать их в новую базу. Муторно. Может есть способ проще? Поделитесь.

    Reply
  31. Дмитрий74Чел

    (30)Официально способа нет. Вы неправильно понимаете суть регитстрации базы в хранилище.

    Информация о подключении харнится на 2х сторонах: и в базе (к какому хранилищу подключена, скорее всего, просто путь к хранилищу), и в хранилище (какие базы подключены, скорее всего просто в виде «сервер-база»).

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

    Цитата с ИТС:

    https://its.1c.ru/db/v8doc#content:82:1:issogl2_28.1.2.подключениекхранилищу

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

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

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

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

    Reply
  32. romankoav

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

    Reply
  33. CratosX

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

    Кстати, раньше я как-то указывал метки к версиям хранилища, а сейчас не нашёл, как это сделать, подскажет кто?

    Reply

Leave a Comment

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