Прием конвертации, который позволит решить много задач




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

44 Comments

  1. Филин

    Со всеми примерами еще подробно не разобрался, но по первому есть вопросы.

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

    Получается что-то вроде такого:

    ПВД:

     ..тут может быть какой-то цикл…
    
    данныеДокумента = создатьОбъект(«СписокЗначений»);
    данныеДокумента.добавитьЗначение(1,»НомерДок»);
    данныеДокумента.добавитьЗначение(«Перенос данных»,»Комментарий»);
    
    тчДокумента = создатьОбъект(«ТаблицаЗначений»);
    тчДокумента.новаяКолонка(«Сумма»);
    тчДокумента.новаяСтрока();
    тчДокумента.сумма = 100;
    
    данныеДокумента.добавитьЗначение(тчДокумента, «Платежи»);
    
    выгрузитьПоПравилу(«заглушка»,,данныеДокумента,,»Платежка»);
    
    …конец цикла…

    Показать

    В ПКО у реквизитов шапки и у ПКГС табличной части ставим флаг «получить из входящих данных». Бонус: в ПКС полей табличной части не надо ничего писать или ставить какие-то галки, все само схватится

    Reply
  2. LexSeIch

    Мир этому дому!

    Конвертация — как шаманство — есть инструмент и правила, а все остальное свобода творчества. Судя по статье — это результат практического использования. Это всегда плюс.

    Reply
  3. Азбука Морзе

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

    Reply
  4. stanru1

    (3) особенно в 7.7 XDTO сериализация рулит 🙂

    на практике перенос (планирование — разработка — тестирование — эксплуатация) из конфигурации 77 в 82 с помощью КД выполняется в несколько раз быстрее, чем альтернативные варианты.

    Reply
  5. Istur

    (3) xotr, раз такой крутой механизм для тебя, то почему нет ни одной твоей статьи про XDTO-сериализацию?

    Reply
  6. AlexO

    (5) Istur,

    так одно в страшном сне, другое — видимо, в прекрасном сне 🙂

    Reply
  7. Азбука Морзе

    (5) xotr не писатель, xotr читатель:)

    п.с. В соседней ветке про XDTO целый цикл статей замутили, желающие могут ознакомится.

    Reply
  8. Yashazz

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

    Reply
  9. ARL

    Автор заслуживает громадное уважение за то, что самостоятельно разобрался с системой КД, т.к описание КД оставляет желать лучшего (мягко говоря). Но сейчас для программистов появился громадный помощник — курсы Гилева. Все подобные задачи на курсах выполняются в качестве домашнего задания, от «шаманства» ничего не остается.

    (3) xotr, «На конкретном примере показал убогость и неестественность правил и приемов КД при обмене данными между разнородными системами.»

    На самом деле, это вопрос компетенции. Если разобраться с КД — то никакой убогости, вполне достойная и работоспособная система.

    Reply
  10. Stepan_1c

    спасибо за статью) на пару дней пораньше бы еще лучше было) эээх)

    Reply
  11. DoctorRoza

    Хорошая статья, очень нужная информация! Плюс однозначно! 🙂

    Reply
  12. KliMich

    Спасибо! Наглядные и показательные примеры, когда надо «приготовить из ничего…»

    Reply
  13. IgorXml

    Спасибо. Наглядно сделал.

    Reply
  14. OVladius

    Где вы раньше были? Всех сотрудников с 7-ки руками фигачили 🙁

    Reply
  15. fomix

    (3) xotr, Интересно как в XDTO можно решить задачи по конвертации одного объекта в другой, получения из одного объекта двух и более, а также наоборот, настроить поиск и прочие фичи. Сдается мне у вас есть опыт тривиального обмена через XDTO между типовыми конфами в общем виде. Не помню, чтобы при использовании XDTO, можно было бы вмешаться в процесс формирования итогового файла выгрузки.

    Reply
  16. Boroda

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

    Reply
  17. sa1m0nn

    Спасибо за статью, нормально написано, хоть и не ново.

    Видать, стал я матёрым конвертатором, ничего не удивило)

    Reply
  18. Азбука Морзе

    (15)formix

    Синтаксис-помощник:

    Механизм XDTO позволяет создать модель представления данных (модель типов и значений), которая, с одной стороны, обеспечивает возможность просто и естественно манипулировать данными в среде 1С:Предприятия 8, а с другой стороны, данная модель хорошо приспособлена для прозрачного преобразования данных в другие форматы, главным образом XML.

    На практике достаточно:

    1.создать модель документа «Ляляля» в базе приемнике

    2.создадать и описать файл для записи данных в xlm-формате

    ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();

    НоваяЗаписьXML = Новый ЗаписьXML;

    ФайлXML = ОсновныеПараметры.ФайлВыгрузки;

    НоваяЗаписьXML.ОткрытьФайл(ФайлXML, ПараметрыЗаписиXML);

    ЗаписьСообщения.НачатьЗапись(НоваяЗаписьXML, СтрокаТаблицыИнформации.УзелИнформационнойБазы);

    // из описания типов фабрики XDTO выберем нужные для создания объектов

    Фабрика = ФабрикаXDTO;

    документыТип = Фабрика.Тип(«http://www.lalala.ru», «Документы»);

    // дальше объектные реквизиты и табличные части

    ЛяляляТип = ДокументыТип.Свойства.Получить(«ляляля»).Тип;

    ТЧляляТип =ЛяляляТип .Свойства.Получить(«ТЧляля»).Тип;

    ЭлементТЧляляТип =ТЧляляТип.Свойства.Получить(«ЭлементТЧляля»).Тип;

    3.запросом получить все необходимые данные для заполнения ляляля-объекта

    4. обработать выборку:

    Документы = Фабрика.Создать(документыТип);

    Пока Выборка.Следующий() Цикл

    //создадим объект XDTO и заполним его

    ЛяляляОбъект = Фабрика.Создать(ЛяляляТип);

    ЗаполнитьЗначенияСвойств(ЛяляляОбъект, Выборка)

    документыТип.ляляля.Добавить(ЛяляляОбъект);

    КонецЦикла;

    5. закончить формирование XML-файла

    Фабрика.ЗаписатьXML(НоваяЗаписьXML, Документы);

    ЗаписьСообщения.ЗакончитьЗапись();

    НоваяЗаписьXML.Закрыть();

    Reply
  19. AlexO

    Курсы — это когда дают знания, которые потом народ не знает, куда применить.

    Все это делается более наглядным и быстрым способом — через DBF.

    Reply
  20. AlexO

    (17) sa1m0nn,

    нет, просто тут затронута сугубо узкая специфика.

    И все делается кодом — все преимущества КД сведены только к выгрузке в XML.

    Reply
  21. Tishu

    Из всей неисчерпаемой как атом КД можно зазубрить один приём — в ПВД создается таблица значений по структуре совпадающей с объектом из Приемника и вызывается ПКО — и можно быстро решать массу одноразовых задач. Достаточно посмотреть примеры конвертаций из КД.

    Reply
  22. AlexO

    (21) Tishu,

    «одноразовых» — это только создание в приемнике тех объектов, которых нет с источнике.

    Reply
  23. saiten

    (19)

    Все это делается более наглядным и быстрым способом — через DBF.

    Кому-то каменным топором удобнее, кому-то — станком с ЧПУ… Каждому своё.

    Reply
  24. INSh

    Человек, победивший КД, уже достоин уважения 🙂

    А еще этот человек не поленился и поделился своими достижениями!

    Молодец! Плюс.

    Reply
  25. karakozov

    XDTO Конечно отличный механизм, и не буду защищать КД, но тем не менее очень часто нужно сделать обмен и очень быстро, правильно описать большие объемы по средствам XDTO это то же серьезная работа, особенно если меняешься между разными структурами метаданных или вообще между 77 -> 8.2 . Или еще усложним, из 8.2 в иные реляционные структуры с извесной нам структурой но не свойственной 1С источнику вообще по структуре МД.Имеет место быть в общмею

    Reply
  26. AlexO

    (23) saiten,

    ну конечно, чем непонятнее и замуторнее — тем лучше: и сам не понимаешь, что там делается, и коллеги ничего не разберут, но зато сколько таинственности и значимости… 🙂

    А вот и слушатели под стать:

    Человек, победивший КД, уже достоин уважения
    Reply
  27. DieseL_OFF

    Эххх мне бы лучше другое

    Reply
  28. saiten

    (26) Думаю, эта тема мусолилась уже достаточно, чтобы не поднимать её ещё раз. А непонятность, собственно, — вещь относительная.

    Reply
  29. Sasha255n

    Спасибо очент необходимое и интересное ренение

    Reply
  30. Sasha255n

    Как алтернатива КД имеет место на существование спасибо

    Reply
  31. vkr

    (19) AlexO

    Да, Вы правы…

    Через DBF все получается гораздо быстрее, прозрачнее и более управляемо.

    Можно из одного большого выгруженного файла с кучей информации брать

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

    объектов «на лету». Причем, для совершенно разных, иногда очень слабо

    совместимых конфигураций ( даже и не 1С-овских иногда 🙂 )

    Но, все равно, автору большое спасибо за подробное описание процесса !

    Reply
  32. kurvik

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

    Reply
  33. fnv

    Спасибо за информацию) Оч. сложные приемы конвертации, я бы через OLE, наверное, делала, если бы мне пришлось делать такой перенос)

    Reply
  34. Franchiser

    Нового ничего не узнал, но статья заслуживает уважения. Рекомендую прочитать методичку О. Кузнецовой, все эти моменты там есть.

    Недостаток использования переменной ВыборкаДанных с моей точки зрения — слишком много написанного кода, не всегда наглядного. То есть чтобы понять как какой объект или свойство трансформируется нужно читать весь код в обрабочике «передобработкой» ПВД. Кроме того фильтры при выгрузке из 7.7 работать не будут.

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

    Reply
  35. &rew

    Да, статья полезная. Подобный способ сам использовал при переносе из самописной 7.7 в типовую УТ 10.3, кстати методичка Кузнецовой мне помогла.

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

    Reply
  36. &rew

    Кстати белый серого сейчас через бедро на иппон бросит.

    Reply
  37. echo77

    (0) ИМХО, для каждого ПКС в ПГКС создавать обработчик:

    Значение = ОбъектКоллекции.ИмяКолонкиТаблицыЗначений
    

    не надо

    Reply
  38. Romany

    (34) Franchiser, Здравствуйте. Как раз разбираюсь с этими переменными, есть много вопросов. Так например задача такая — Для простоты будем считать, что конфигурации самописные, и разные по структуре. В источнике есть документ, в приемнике надо из этого документа создать два объекта 1) справочник. 2) РегистрСведенийЗапись. Пытаюсь сделать так. 1) ПКО — Документ ->Справочник,

    2) ПКО Источника нет -> РегистрСведенийЗапись, ПКС — В приемнике — структура регистра (3 поля), стоит флаг «Получить из входящих данных». Далее в ПВД Документ. В обработчике «ПослеВыгрузки» запросом получаю таблицу движений документа, для переноса их в регистр сведений в приемнике. Тут же надо вызвать функцию «ВыгрузитьПоПравилу()», но вот сложности. В какие параметры, чего пихать, и как это вообще должно работать. То есть, можно ли в параметр ИсходящиеДанные записать таблицу значений (Выгрузку запроса) или создать выборку, и в цикле формировать структуру, и вызывать выгрузить по правилу. Скажу сразу, в моем случае, ни так ни эдак не работает. Обмен происходит по средствам типовой обработки обмена. Если не сложно расскажите в двух словах, как правильно с этим работать, и использовать.

    Reply
  39. ultrannge89

    Добрый день. А есть ли возможность отследить в событии после загрузки, попал ли определенный документ в выгрузку? Мне важно знать есть ли в файле, другой документ по такому же договору как мой, только с другим видом… Не могу нигде найти(

    Reply
  40. Pirat-37

    (39) ultrannge89, через [Сообщить()] выводите, в событии [При загрузке].

    Reply
  41. nems

    Здраствуйте! Подскажите, плиз, как перенести справочник Номенклатура по отбору

    ВходящиеДанные = Новый Структура;
    
    Запрос = Новый Запрос;
    Запрос.Текст =
    «ВЫБРАТЬ
    | ТоварыОрганизацийОстатки.Номенклатура
    |ИЗ
    | РегистрНакопления.ТоварыОрганизаций.Остатки КАК ТоварыОрганизацийОстатки
    |ГДЕ
    | ТоварыОрганизацийОстатки.КоличествоОстаток > 0»;
    
    Результат = Запрос.Выполнить();
    
    Выборка = Запрос.Выполнить().Выгрузить();
    
    
    ВходящиеДанные.Вставить(«НоменклатураТабл», Выборка);
    
    ВыгрузитьПоПравилу(,,ВходящиеДанные,,»Номенклатура1″)
    

    Показать

    Выгрузка проходит успешно.

    Но есть проблема: Как правильно задать ПКО и ПКС ?

    Reply
  42. Kvitka_ru

    Спасибушки! безценная консультация!!

    Reply
  43. echo77

    Обычно весь выгружаемый объект формируют в ПВД, а не в ПКГС и разных местах.

    Reply
  44. SergeMalikov

    (43) Да. Можно было бы сформировать в ПВД структуру соответствующую объекту в приемнике и передать нужному ПКО. Это был бы более наглядный вариант.

    Reply

Leave a Comment

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