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




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

34 Comments

  1. qwinter

    Работа с дополнительными реквизитами очень сильно разнится в зависимости от версии БСП. Например в последних имя реквизита на форме можно указать (просмотреть) в пользовательском виде. Об этом тоже стоило упомянуть.

    Reply
  2. papche

    (1)можно задать значение реквизита «Имя» в Плане видов характеристик «Дополнительные реквизиты». И соответственно этот параметр я и передаю в приведенные процедуры. Но чтобы задавать имена на формах — не видел/не слышал. Если приведете пример — буду рад

    Reply
  3. fxmike

    Спасибо! Только вчера сидел разбирался с этими непонятными абракадабрами на форме 🙂 А тут очень кстати ваша статья!

    Reply
  4. Jestery

    (2) Может имеется ввиду вот это. Честно говоря пока не понятно как это можно использовать.

    Reply
  5. fxmike

    (4) Как непонятно, все же понятно. В этом поле задается значение реквизита «Имя» для доп свойства. Подразумевается, что оно уникальное в пределах базы данных, система следит за этим. Поиск свойства и обращение к нему удобно вести по этому имени. Можно даже задать его, но только при первоначальном создании доп, потом уже редактировать не дает. Во встроенных функциях также можно использовать обращение по этому имени.

    Reply
  6. Denis S

    (5) Редактировать можно, в группе «Еще» есть команда «Разрешить редактирование реквизитов».

    Reply
  7. kembrik

    (4) Использую частенько, особенно в запросах как параметр, не надо тогда следить за принадлежностью к конкретному набору и городить конструкции с «Где» и коротким заголовком

    Reply
  8. PerlAmutor

    Когда внедряли ERP по первой «развлекались» с этими доп.реквизитами, чтобы конфигурацию не кочеряжить. Потом началось. То им отчеты нужны, то печатные формы где используются эти реквизиты. Потом они хотят больше бантиков. Потом они должны участвовать в планах обменов… И все в таком духе. Это кошмар.

    Если организация решила сэкономить на программисте 1С, то этот вариант ей подойдет до момента пока им не понадобится этот дополнительный реквизит использовать где-то еще.

    Reply
  9. gorakh

    (8)Доп реквизиты полезная штука. Положим у нас есть 100 тыс. элементов справочника номенклатуры. в 1000 элементов характерезует какое-то свойство. А всем остальным элементов это свойство не нужно и всегда будет пустым. Вот в этолм случае очень хорошо помогают дополнительные реквизиты. А в отчетах на СКД их использовать очень просто. И в обменах не сложнее чем обычные элементы.

    Reply
  10. kolya_tlt

    (8) самое страшное будет когда будет меняться бизнес логика документов в зависимости от реквизитов.

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

    кстати вроде есть функционал упаковок в программе. зачем было городить доп реквизиты Количество мест и тип упаковки?

    Reply
  11. papche

    (10)Собственно, статья не про полезность и необходимость использования доп реквизитов, а про то как решать указанные в топике задачи, если уж вступили на «скользкую дорожку» использования доп реквизитов.

    Сама по себе тема необходимости и оптимальности использования дополнительных реквизитов заслуживает целой серии статей и сотен сломанных копий )). Я тут — пас

    Reply
  12. triviumfan

    Коротко: автор рассказал, что есть такая штука как БСП и какие методы есть в подсистеме доп свойств/реквизитов.

    Эта статья для самых ленивых, не способных воспользоваться отладчиком любого справочника с доп. реквизитом.

    Reply
  13. papche

    (12) БСП не упоминал, ни прямо, ни косвенно)))

    Reply
  14. men1949

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

    Reply
  15. user820037

    Наверно что-то недопонимаю, но Функция ПолучитьПолеДополнительногоРеквизитаНаФорме(Форма, ИмяРеквизита) исполняется на сервере, а форма туда не передается «Отсутствует отображение для типа ‘УправляемаяФорма'»

    Reply
  16. papche

    (15) На сервере, да. Форма вполне себе передается.

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

    &НаСервере
    Процедура СвойстваВыполнитьДополнительнуюИнициализацию();
    пп_Сервер.ПереместитьДополнительныйРеквизит(ЭтаФорма,»СерийныеНомера_ЗаданиеНаПеревозку», «пп_ГруппаДопРеквизиты», Истина);
    пп_Сервер.ПереместитьДополнительныйРеквизит(ЭтаФорма,»Комплектовщик_ЗаданиеНаПеревозку», «пп_ГруппаДопРеквизиты», Истина);
    КонецПроцедуры
    
    &НаСервере
    Процедура УстановитьДоступностьЭлементовФормы(Доступность)
    Элементы.МаршрутДобавитьРаспоряжение.Доступность = Доступность;
    
    ПолеСерийныеНомера = пп_Сервер.ПолучитьПолеДополнительногоРеквизитаНаФорме(ЭтаФорма, «СерийныеНомера_ЗаданиеНаПеревозку»);
    Элементы[ПолеСерийныеНомера.ИмяРеквизитаЗначение].Доступность = Истина;
    
    ПолеКомплектовщик = пп_Сервер.ПолучитьПолеДополнительногоРеквизитаНаФорме(ЭтаФорма, «Комплектовщик_ЗаданиеНаПеревозку»);
    Элементы[ПолеКомплектовщик.ИмяРеквизитаЗначение].Доступность = Доступность;
    
    Элементы.Маршрут.Доступность = Доступность;
    КонецПроцедуры
    
    &НаКлиенте
    Процедура пп_ПриОткрытииПосле(Отказ)
    //СвойстваВыполнитьОтложеннуюИнициализацию();
    //УправлениеСвойствамиКлиент.ПослеЗагрузкиДополнительныхРеквизитов(ЭтотОбъект);
    СвойстваВыполнитьДополнительнуюИнициализацию();
    Если ПризнакЗаданиеНаОтборНапечатано Тогда
    
    //ТолькоПросмотр = Истина;
    УстановитьДоступностьЭлементовФормы(Ложь);
    Состояние(«Сформирована печатная форма «»Задания на отбор»», редактирование ограничено»);
    
    КонецЕсли;
    КонецПроцедуры

    Показать

    Reply
  17. user820037

    (16) Разобрался. Очень, очень помогла Ваша публикация.

    Reply
  18. manb

    Статья очень помогла. Спасибо))

    Reply
  19. user895773

    Вот как раз сижу разбираюсь.

    УТ(11.3.4.47)

    Мне надо, чтобы поле доп. реквизита имело вид «ПолеНадписи»

    В расширении в процедуре формы

    Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)

    Вызываю:

    УправлениеСвойствами.ЗаполнитьДополнительныеРеквизитыВФорме(ЭтотОбъект,,Истина); \Параметр ПоляНадписей = Истина

    Но поле все равно имеет вид «ПолеВвода», да еще в список значений попадают лишние значения.

    Что то делаю не так или это ошибка в конфигурации?

    PS: Попытался в УправлениеСвойствами.ЗаполнитьДополнительныеРеквизитыВФорме

    Исправить

    Если ПоляНадписей Тогда

    Элемент.Вид = ВидПоляФормы.ПолеВвода;

    На

    Если ПоляНадписей Тогда

    Элемент.Вид = ВидПоляФормы.ПолеНадписи;

    Заработало ….

    Reply
  20. user594726_artyem.romanenkov

    (16) Помогите разобраться — что делаю не так?

    &НаКлиенте
    Процедура ДТ_ПриОткрытииПосле(Отказ)
    
    Если Строка(Объект.ВидДокумента) = «Акт выполненных работ» Тогда
    МожноМенятьАкт = ПроверитьИзменениеАкта();
    КонецЕсли;
    
    ДопРеквизитНаФорме = ПолучитьПолеДополнительногоРеквизитаНаФорме(ЭтаФорма, «Номер заказа в SAP»);
    
    Если МожноМенятьАкт Тогда
    Элементы.ДопРеквизитНаФорме.Доступность = Истина;
    Иначе
    Элементы.ДопРеквизитНаФорме.Доступность = Ложь;
    КонецЕсли;
    
    КонецПроцедуры
    
    &НаСервере
    Функция ПолучитьПолеДополнительногоРеквизитаНаФорме(Форма, ИмяРеквизита) Экспорт
    
    Список = Форма.Свойства_ОписаниеДополнительныхРеквизитов;
    
    Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту(«Наименование», ИмяРеквизита);
    
    Если ЗначениеЗаполнено(Свойство) Тогда
    НайденныеСтроки = Список.НайтиСтроки(Новый Структура(«Свойство», Свойство));
    Если НайденныеСтроки.Количество() > 0 Тогда
    Возврат НайденныеСтроки[0];
    КонецЕсли;
    КонецЕсли;
    
    КонецФункции

    Показать

    Reply
  21. Светлый ум

    Взял на вооружение +1

    Reply
  22. mnb-next

    Спасибо! Статья сразу помогла решить мою сегодняшнюю проблему! Очень своевременно!

    Reply
  23. Sergafan10

    Спасибо за статью! Информативно.

    Reply
  24. mikleRo

    Спасибо,

    помогло, только для нужной конфигурации (ЭДО вер. 2.1.12.2) пришлось изменить в функции

    ПолучитьПолеДополнительногоРеквизитаНаФорме

    строку

    у Вас :

    Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоРеквизиту(«Имя», ИмяРеквизита);

    заработало

    Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию(ИмяРеквизита);

    Reply
  25. awe007

    (24)

    Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию(ИмяРеквизита);

    А не могли бы вы полностью привести пример работающей функции для 1С ДО ?

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

    Reply
  26. papche

    (25) На ДО не тестировал, вообще не в курсе, будет ли там работать или нет.

    Reply
  27. awe007

    (26) Отлично работает именно в том виде, как вы и предложили

    Свойство = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию(ИмяРеквизита);
    Reply
  28. papche

    (27) Ну и хорошо. Только это mikleRo про ДО предложил.

    Посмотрел — в ДО у реквизита «Имя » ПВХ ДополнительныеРеквизитыИСведения не выставлен признак индексирования, в отличие от ЕРП образных. Для универсальности нужно запросом получать

    Reply
  29. kotov2000

    Воспользовался готовыми функциями в ERP 2.4.8.

    ПолучитьЗначениеДополнительногоРеквизитаНаФорме

    УстановитьЗначениеДополнительногоРеквизитаНаФорме

    Все работает! разбираться с БСП гораздо дольше.

    Reply
  30. papche

    (29)

    2.4.8

    Алексей, появились готовые функции? Ооо, здорово! А в каком модуле?

    Reply
  31. kotov2000

    (30) в Этой статье появились, которые я перенес в свой модуль.

    Автору респект!

    Reply
  32. SashinPapa

    Низкий поклон автору!

    Очень-очень полезно тем, кто допиливает 1С:Документооборот v2.1

    Reply
  33. morgershtern

    Может оффтоп, но подскажите, а реально ли сделать множественный выбор «дополнительных значений» в «дополнительный реквизит»?

    Reply
  34. Xershi

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

    Вам нужна таблица, а тут реквизит. Логика вашей задачи другая.

    Reply

Leave a Comment

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