Хватит создавать формы выбора!




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

47 Comments

  1. Поручик

    А я не знал. В понедельник воспользуюсь.

    Reply
  2. slipers

    Изящно. Беру на заметку.

    Reply
  3. konstruktiv

    Получается здесь какая-то неактуальная информация

    http://its.1c.ru/db/metod8dev#content:3575:hdoc:_top:%D1%84%D0%BE%D1%80%D0%BC%D0%B0%20%D0%B2%D1%8B%D0%B1%D0%BE%D1­%80%D0%B0

    Reply
  4. TODD22

    (3) konstruktiv,

    Получается здесь какая-то неактуальная информация

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

    Это как с обработчиками событий. Для каждого обработчика своя процедура. Так же и тут для каждой задачи своя форма. Как минимум путаницы будет меньше. Особенно если работаешь не один. И после тебя людям поддерживать и дорабатывать конфигурацию. И люди которые придут со стороны как минимум ожидают что это будут разные формы.

    И что потом делать если вдруг надо изменить поведение формы списка, а поведение формы выбора оставить как есть… придётся делать две формы.

    ИМХО не очень красивое решение…

    Reply
  5. Fragster

    (3) konstruktiv, там очень туманно написано. Описанный мной вариант работает. Лишних вызовов сервера не плодит.

    Reply
  6. Fragster

    (4) TODD22, тут можно поспорить. Повторю публикацию — мне много раз приходилось убеждаться, что когда при выборе значения в поле ввода открывается такая же форма, как и при отображении списка — у пользователя возникает меньший дискомфорт. Он пользуется теми же приемами (например для отбора), что и при работе в форме списка. Колонки находятся на тех же местах, их ширина запомнена, ненужные для пользователя данные он сам выключил, условное оформление, которое он для себя настроил — схоранилось. А когда это две разных формы — то, например, добавлении реквизита или изменения запроса ДС для вывода доп. информации, приходится дорабатывать две формы, что влечет дублирование кода.

    И что потом делать если вдруг надо изменить поведение формы списка, а поведение формы выбора оставить как есть… придётся делать две формы.

    Как часто приходилось это делать? Понятно, что есть случаи типа отображения остатков и прочие особенности форм подбора. Но посчитайте по своим конфигурациям, сколько форм выбора по отображаемой информации дублируют формы списка. Или отображают меньше информации (которая бывает необходима)?

    Reply
  7. TODD22

    (6)

    тут можно поспорить.

    ИМХО тут даже спорить не о чем.

    Нужно придерживаться стиля применяемого в типовых…

    А не придумывать свои велосипеды…

    влечет дублирование кода.

    Так создание однотипных обработчиков событий то же ведёт к дублированию кода. Может тогда один обработчик начать делать?

    Он пользуется теми же приемами (например для отбора), что и при работе в форме списка.

    А что приёмы в форме выбора и форме списка отличаются?

    Reply
  8. Fragster

    (7) TODD22,

    А что приёмы в форме выбора и форме списка отличаются?

    вот именно — меньше разных контекстов, меньше раздражение кожи пользователя

    Reply
  9. TODD22

    (8)

    вот именно — меньше разных контекстов, меньше раздражение кожи пользователя

    Ещё ни разу не видел раздражения пользователя на список формы и список выбора… Да так что бы раздражение вызывало что это две разные формы и нужно срочно переделать в одну.

    А вот такие «неожиданные» решения ИМХО не правильно. Механизмы должны быть так сказать с ожидаемым поведением и очевидной реализацией, 1С в первую очередь открытая система.

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

    Пусть даже это увеличивает трудоёмкость. Зато это понятно и очевидно.

    Reply
  10. Fragster

    (9) TODD22, ну, у вас пользователи не настраивают условное оформление, видимо. Не настраивают ширину колонок, не выключают «лишние» для них.

    Я посчитал, сколько у меня одинаковых форм и как часто приходится дорабатывать обе, и вывел для себя подобное решение. Например когда дополнительная связанная информация хранится в РС и данные в этом РС вдруг расширили доп. реквизитом, надо этот реквизит добавить в обе формы.

    Естественно, данное решение не панацея. Я не призываю его применять вообще везде. Например брать и перепиливать вдоль и поперек объекты типовых конфигураций не следует. А вот провести анализ, понять, сколько же одинаковых форм у нас есть в конфигурации — бывает полезно.

    Reply
  11. jerry_maguire

    А зачем свойство структуры сравнивать с Неопределено ?

    Параметры.МножественныйВыбор <> Неопределено

    Можно воспользоваться методом

    Параметры.Свойство(«МножественныйВыбор»)
    Reply
  12. Fragster

    (11) jerry_maguire, к сожалению, этот параметр у формы всегда есть (просто равен Неопределено) и .Свойство() возвращает Истина. А Параметры.Свойство(«МножественныйВыбор», Элементы.Список.МножественныйВыбор) вообще выдает ошибку «несоответствие типов».

    Reply
  13. alyaev.a.v

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

    Reply
  14. Drak0n

    Поддержу (13) alyaev.a.v.

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

    — пересечь пользовательский отбор с «программным»

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

    Хотя реализация с 1 формой встречается и в типовых конфигурациях 1С.

    Reply
  15. TODD22

    (14) Drak0n,

    Хотя реализация с 1 формой встречается и в типовых конфигурациях 1С.

    В каких ?

    Мне вроде не попадалось что бы было сделано одной формой форма списка и выбора.

    Reply
  16. olegmedvedev

    Например в Бухгалтерия предприятия, редакция 3.0 (3.0.43.258) Форма списка в справочнике Физические лица используется в Выборе и Списке

    Reply
  17. TODD22

    (16) olgerd666, Интересно 🙂

    Reply
  18. Fragster

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

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

    Reply
  19. herfis

    Ну, для простейших справочников (которые суть перечисления с парой доп-реквизитов) предложение вполне здравое.

    Вряд ли там когда-то потребуется отдельная форма выбора, как и отборы.

    Reply
  20. Drak0n

    (15) TODD22, помнится в УНФ у справочников «Контрагенты» и «Номенклатура» тоже 1 форма…

    Reply
  21. monkbest

    (7) TODD22, чувак, открой ЗУП 3.0!!! Это АДДДДДДДД. Там фильтров в форме выбора сотрудников (уволен, организация, подразделение, архивный) жесть скока. И может так случиться, что в форме выбора сотрудника нет, а в форме списка есть. И пользователь сходу не врубается, почему данные отличаются. Я молчу, что при выборе физ-лица они показывают формы выбора сотрудника.

    Я с автором солидарен: одна форма, единая логика работы! Прячем «архивных» сотрудников, следовательно прячем их и там и там. Один справочник — одна форма со списком.

    Reply
  22. TODD22

    (21) monkbest,

    чувак, открой ЗУП 3.0!!! Это АДДДДДДДД. Там фильтров в форме выбора сотрудников (уволен, организация, подразделение, архивный) жесть скока.

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

    Reply
  23. kg_am

    Мы с самого начала отказались от идеи плодить лишние сущности. Только стандартный код при создании на сервере у нас немножко другой:

    ЭтаФорма.Элементы.Список.РежимВыбора = Параметры.РежимВыбора;
    Если ЭтаФорма.Элементы.Список.РежимВыбора Тогда
    ЭтаФорма.РежимОткрытияОкна = РежимОткрытияОкнаФормы.БлокироватьОкноВладельца;
    КонецЕсли;
    

    За нюанс с множественным выбором — спасибо.

    Reply
  24. Fragster

    (23) kg_am, добавлю в пост, если не против

    UPD: проверил, при стандартной обработке начала выбора окно и так открывается в этом режиме, эта строка не требуется.

    Reply
  25. kg_am

    (24)

    При стандартном — да, но если выбор открывается программно, то тут оно и пригождается.

    Конечно не против. Как можно быть против? 😉

    Reply
  26. Fragster

    (25) kg_am, если программно — то можно и в параметр ОткрытьФорму указать.

    Reply
  27. clev

    Спасибо за пример!

    Reply
  28. stolya

    Не так давно тоже начал применять данный подход и столкнулся с двумя особенностями из-за которых перестал использовать данный способ:

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

    2. Если используется метод глобального контекста ПоказатьВводЗначения или ВвестиЗначение, то в открываемой форме режим выбора не устанавливается, в результате приходится дописывать параметр РежимВыбора в модуль менеджера в событие ОбработкаПолученияФормы при открытии формы выбора что не очень удобно. Не тестировал еще работу в режиме подбора в список значений, открываемый в отборе компоновки с видом сравнения «В списке» и т.п.

    Reply
  29. Fragster

    (28) Спасибо за замечания!

    1. Проблема понятна, обход делается в три строчки:

    Если Параметры.РежимВыбора И Не ЗначениеЗаполнено(Параметры.КлючПользовательскихНастроек) Тогда

    Параметры.КлючПользовательскихНастроек = «РежимВыбора»;

    Список.АвтоматическоеСохранениеПользовательскихНастроек = Ложь;

    КонецЕсли;

    добавлю это в публикацию.

    2. Странно, видимо имеет место ошибка платформы в конкретном вашем релизе. У меня при ПоказатьВводЗначения Параметры.РежимВыбора = Истина. Проверял на релизе 8.3.8.2137, режим совместимости = не использовать.

    Reply
  30. Pawlick
    Ещё ни разу не видел раздражения пользователя на список формы и список выбора…

    У Вас еще все впереди, видимо 🙂

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

    Может стоит посмотреть в основные формы в конфигураторе?

    Использование одной формы в место двух оправданно и с точки зрения разработчиков и точки зрения пользователей.

    Для меня как для разработчика проще обслуживать одну и туже форму, особенно на сильно доработанных конфигурациях, и особенно на сложных формах. Если в форме 100500 отборов, и она находится в активной разработке, и в день приходит 15 «указивок» что и как изменить.

    Например у меня форма документа заказ покупателя:

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

    И ты еще одну задачу типа «если это младший менеджер, то что бы только не отгруженные», и все это надо сделать в двух СОВЕРШЕННО ОДИНАКОВЫХ ФОРМАХ, открывающихся в разных режимах…

    С проблемой программных отборов при открытии формы в режиме выбора пока не сталкивался, но уверен что решение есть. Тоже программное 🙂

    А с точи зрения пользователя — уже писали выше. Одни колонки, одно оформление.

    Reply
  31. Fragster

    (30)

    С проблемой программных отборов при открытии формы в режиме выбора пока не сталкивался, но уверен что решение есть. Тоже программное 🙂

    при наличии отборов можно выключать «предопределенные» пользовательские настройки, и использовать отдельный ключ для «непредопределенных». Вторая часть есть в примере кода, первая часть (и для фиксированных настроек для сложногоотбора и для отбора при связи параметров выбора) используется, например в http://infostart.ru/public/556514/ в форме списка документа «Задачи».

    Reply
  32. Hatson

    Разные формы списка и выбора и раньше выбешивали.

    Reply
  33. AlexO

    (7)

    Может тогда один обработчик начать делать?

    Это как?!

    Reply
  34. TODD22

    (33)писать одну процедуру и назначать её нескольким обработчикам….

    Reply
  35. AlexO

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

    Reply
  36. AlexO

    Кстати, у 1С в типовых все тоже самое (немного видоизменен код в «ПриСозданииНаСервере» у формы списка), только никаких «нюансов» со множественностью выбора, работает и без этого:

     Если Параметры.РежимВыбора Тогда
    Элементы.Список.РежимВыбора = Истина;
    КонецЕсли;
    

    Подозреваю, что код статьи подсмотрен через партнерский форум в типовых, т.к. навряд ли 1С использовала данный материал в своих разработках ))

    Reply
  37. Octopus

    (36)

    Элементы.Список.РежимВыбора = Параметры.РежимВыбора;
    Reply
  38. AlexO

    (37) ну вот не написали так, сделали через условие. Я же говорю — немного видоизменили.

    Главное — что никаких проблем с множественным выбором и пользовательскими настройками.

    Поэтому нет дополнительного кода.

    Reply
  39. Fragster

    (36) нет, никакой код не подсматривался.

    Reply
  40. Fragster

    (38) а вот есть проблема с множественным выбором. в варианте (36) он не работает.

    Reply
  41. zqzq

    (29)

    1. Проблема понятна, обход делается в три строчки:

    Если Параметры.РежимВыбора И Не ЗначениеЗаполнено(Параметры.КлючПользовательскихНастроек) Тогда

    Параметры.КлючПользовательскихНастроек = «РежимВыбора»;

    Список.АвтоматическоеСохранениеПользовательскихНастроек = Ложь;

    КонецЕсли;

    добавлю это в публикацию.

    На платформе 8.2.19 выдаёт ошибку на этих строках

    )}: Поле объекта не обнаружено (КлючПользовательскихНастроек)
    Если Параметры.РежимВыбора И Не ЗначениеЗаполнено(Параметры.КлючПользовательскихНастроек) Тогда
    

    И т.к. в 8.2 отборы не запоминаются, то оно и не нужно.

    Reply
  42. spenser123

    Не актуально совсем… 8.3.11.3034 (без режима совместимости)- если форма не является формой выбора — стандартные команды выбора исчезают и недоступны, а в старых формах списка которые использовались как формы выбора — получаем программные ошибки с завершением работы (форма пользователей от ут например)

    Reply
  43. Fragster

    (42) Ну не знаю, у меня работает, в т.ч. в https://infostart.ru/public/556514/

    Одна и та же форма является формой списка и формой выбора:

    Reply
  44. spenser123

    (43) условия проявления косяка — 8.3.11.3034, Режим совместимости — Не использовать.

    Поясню итоги исправлений:

    Косяк провился в первую очередь в справочниках из типовой УТ (Пользователи, внешние пользователи, группы пользователей), там форма списка была назначена и на список и на выбор, программно устанавливался Режим выбора у списков на форме, и в зависимости от «РежимВыбора» прятались/показывались кнопки выбора — результат был выбивание из программы. Если у каждого отдельного элемнта формы списка не установлен режим выбора — в списке команд нет стандартной команды «Выбрать», в результате если вынесена кнопка этой команды на форму и управляется её видимость, а режим выбора назначается программно — в случае параметра РежимВыбора = Ложь, у кнопки пропадает команда и кнопка сама пропадает из элемнтов формы, в результате код который их прячет — вызывает ошибку с вылетом.

    Reply
  45. Fragster

    (44)

    1. Это очень похоже на ошибку платформы

    2. БСП 2.4 У(и УТ в частности) не поддерживает режим совместимости, отличный от 8.3.10 😉

    надо проверить в БСП 3.0 (ну и на платформе 8.3.12), но там куча косяков и я пока не готов её себе ставить

    Reply
  46. zurapa

    Да вы провокатор батенька.

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

    А, если у вас сотрудников 20 тыс. и пользователей около 10 тыс, баз по регионам обменивающихся конфигурацией штук — 100, и во всей этой каше вам постоянно нужно делать разные хотелки в этих конфигурациях, то вы вероятно, будете экономить ваши силы на создание повторяющегося кода. В том числе и ценой общих функций вставляемые в обработчики событий, чтобы не фигачить, как оголтелый, когда нужно будет глобально везде сменить механизм обработки какого-то шаблонного события. Вы работаете в обольшой корпорации, где история работающей конфигурации уже насчитывает второй десяток лет. У вас многие бизнес-процессы не так, как у 1С (потому что это жизнь, а не сферический конь в вакууме!).

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

    Reply
  47. tireal

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

    Reply

Leave a Comment

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