1С: Специалист по платформе. Задача 1.25




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

25 Comments

  1. vasyak319

    ОбработкаЗаполнения написана неправильно, так как ДанныеЗаполнения при интерактивном вводе нового не всегда равны Неопределено, так что нужно проверять, что передан именно счёт.

    Дальше читать не стал.

    Reply
  2. slazzy
    4) Документ «Расходная накладная»

    Чтобы документ вводился только на основании счета, потребуется 2 процедуры

    На самом деле для этого понадобится 1 строчка

    &НаСервере
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    Отказ = НЕ ЗначениеЗаполнено(Параметры.Основание);
    КонецПроцедуры
    

    Кстати за такой синтаксис отрубают руки

    Запрос = Новый(«Запрос»);

    Движения.Счета.Записывать = Истина;
    Движения.Взаиморасчеты.Записывать = Истина;
    // Блокировка
    Блокировка = Новый БлокировкаДанных;
    ЭлементБлокировки = Блокировка.Добавить(«РегистрНакопления.Счета»);
    ЭлементБлокировки.УстановитьЗначение(«Счет», Счет);
    ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
    Блокировка.Заблокировать();
    
    Запрос = Новый(«Запрос»);
    Запрос.Текст =»ВЫБРАТЬ
    |СчетаОстатки.СуммаОстаток КАК Долг
    |ИЗ
    |РегистрНакопления.Счета.Остатки(&ТочкаИтогов, Счет = &Счет) КАК СчетаОстатки»;
    Запрос.УстановитьПараметр(«Счет»,Счет);
    ТочкаИтогов = ?(РежимПроведения= РежимПроведенияДокумента.Оперативный, Неопределено, Новый Граница(МоментВремени(),ВидГраницы.Исключая));
    Запрос.УстановитьПараметр(«ТочкаИтогов»,ТочкаИтогов);
    Результат = Запрос.Выполнить();
    Если Не Результат.Пустой() Тогда
    Выборка = Результат.Выбрать();
    Выборка.Следующий();
    Если Выборка.Долг < СуммаПоДокументу Тогда
    Отказ = Истина;
    Сообщение = Новый(«СообщениеПользователю»);
    Сообщение.Текст = «Сумма документа превышает сумму долга «+ Выборка.Долг;
    Сообщение.Сообщить();
    КонецЕсли;
    КонецЕсли;
    
    Если Не Отказ Тогда
    Движение = Движения.Счета.ДобавитьРасход();
    Движение.Период = Дата;
    Движение.Счет = Счет;
    Движение.Сумма = СуммаПоДокументу;
    
    Движение = Движения.Взаиморасчеты.ДобавитьПриход();
    Движение.Период = Дата;
    Движение.Счет = Счет;
    Движение.Сумма = СуммаПоДокументу;
    Движение.Контрагент = Контрагент;
    КонецЕсли;
    КонецПроцедуры

    Показать

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

    Reply
  3. spetzpozh

    Задач в сборнике сколько, штук 140 всех вместе? Держите нас в курсе :))

    Reply
  4. Betis

    (1) vasyak319, не могу согласится, по условию задачи накладная может вводится только на основании счета, поэтому «данныезаполнения» могут быть только «счет» или неопределено, или Вы видите еще какие-то варианты?

    Reply
  5. Betis

    (3) spetzpozh, буду стараться)

    Reply
  6. Betis

    (2) slazzy,

    1) На самом деле для этого понадобится 1 строчка

    &НаСервере
    Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    Отказ = НЕ ЗначениеЗаполнено(Параметры.Основание);
    КонецПроцедуры

    1) вместо 2 процедур одна строчка? это вы загнули.

    Реквизиты накладной заполнить то надо как-то.

    предлагаете вместо моих 3 строчек

    Если Не ЗначениеЗаполнено(Объект.Счет) Тогда

    Отказ = Истина;

    КонецЕсли;


    одну

    Отказ = НЕ ЗначениеЗаполнено(Параметры.Основание);

    КонецПроцедуры

    сокращение строк кода это конечно хорошо, но надеюсь за это баллы не снимают.

    2) Кстати за такой синтаксис отрубают руки

    Запрос = Новый(«Запрос»);


    Я в шоке, надеюсь сможете обосновать (если конечно это была не шутка)

    3) Здесь согласен, упустил этот момент, спасибо!

    Reply
  7. slazzy

    (6)

    Я в шоке, надеюсь сможете обосновать (если конечно это была не шутка)

    Нет, не шутка. Подобное создание объектов запрещено. Это относится и ко всем остальным объектам в Вашем коде.

    http://its.1c.ru/db/v8std#content:2149184100:hdoc

    Реквизиты накладной заполнить то надо как-то.

    Ну значит 2 строчки ) всё равно у вас это сделано довольно странно. К примеру, Вы в ОбработкаЗаполнения выставляете Отказ = Истина, но зачем? В этой процедуре нет Отказа вообще.

    сокращение строк кода это конечно хорошо, но надеюсь за это баллы не снимают.

    С чего бы?

    Reply
  8. Betis

    (7) slazzy,

    1) К сожалению у меня доступа к ИТС, может как-то страничку скинете?

    2) Верно подмечено, отказа в обработке заполнения нету, зря я его сунул туда)

    3)С чего бы? Просто не слышал об этом, на экзамене дай боже сделать как удобно, думаю времени на анализ того как сократить код не останется.

    Reply
  9. vasyak319

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

    Reply
  10. slazzy

    (8) у меня эта ссылка работает и без доступа )

    но я скопирую текст оттуда


    Для программного создания прикладных объектов следует использовать методы соответствующих менеджеров (СоздатьЭлемент, СоздатьДокумент, СоздатьНаборЗаписей и т.д.).

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

    Правильно:

    ДокументПриходная = Документы.ПоступлениеТоваровУслуг.СоздатьДокумент();

    Неправильно:

    ДокументПриходная = Новый(«ДокументОбъект.ПоступлениеТоваровУслуг»);

    Конкретно эта цитата относится только к объектам, но в общем случае запрещается создавать что-то если вы изначально знаете тип и существует конструктор.

    То есть если можно написать Новый Запрос, то писать Новый(«Запрос») запрещено.

    Подразумеваю, что это привычка из семерки

    Reply
  11. Betis

    (10) slazzy, Я думаю Вы сделали неправильные выводы. Как Вы и сами верно выразились «Конкретно эта цитата относится только к объектам», а остальное Вы от себя додумали. Лично я впервые такой метод конструктора увидел в материалах Евгения Гилева, надо будет его тоже предупредить)

    Reply
  12. Betis

    (9) vasyak319,может Вы удивитесь, но в моем Синтакс-Помощнике как раз и описаны 2 варианта конструктора Новый.

    Reply
  13. vasyak319

    (12) вы бы посмотрели, на какое из ваших сообщений я ответил. Про Новый там речь не шла.

    Reply
  14. Betis

    (13) vasyak319,

    Прошу пардона, был невнимателен.

    СП глянул, увы не понял на что Вы намекаете.

    Еще раз возвращаюсь к Вашему первому комменту

    «ОбработкаЗаполнения написана неправильно, так как ДанныеЗаполнения при интерактивном вводе нового не всегда равны Неопределено, так что нужно проверять, что передан именно счёт.

    Дальше читать не стал.»

    Во всяком случае моя «неправильная» обработка заполнения у меня работает без ошибок. Тестил 2 варианта ввод на основании — тогда ДанныеЗаполнения= Документ.Cчет и при интерактивном вводе — тогда ДанныеЗаполнения=Неопределено. В процедуре обрабатывается каждый из варинтов , иных вариантов обнаружить не удалось.

    Reply
  15. slazzy

    (11)

    внимательнее читайте сообщения 🙂 в курсах Гилева данный метод создания объектов используется при динамическом создании объекта, тип которого изначально не известен, в 99.99% случаях это не так и всё известно заранее. Вам нужен запрос, вы делаете запрос.

    Найдите в любой типовой 1С конфигурации, где бы они создавали запрос как Вы.

    Во всяком случае моя «неправильная» обработка заполнения у меня работает без ошибок. Тестил 2 варианта ввод на основании — тогда ДанныеЗаполнения= Документ.Cчет и при интерактивном вводе — тогда ДанныеЗаполнения=Неопределено. В процедуре обрабатывается каждый из варинтов , иных вариантов обнаружить не удалось.

    На самом деле если в динамическом списке установлен отбор, то ДанныеЗаполнения будут Структура и туда передадутся данные, которые установлены в отборе. Поэтому vasyak319 сделал абсолютно верное замечание. Если у Вас что-то работает, это не значит, что это будет работать всегда 🙂

    и если кто-то где-то написал Сообщение = Новый(«СообщениеПользователю») то вовсе не значит, что надо так делать. Так делать не надо 🙂

    Reply
  16. Betis

    (15) slazzy, Во-первых спасибо Вам за Ваш труд)

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

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

    Reply
  17. slazzy

    (16)

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

    то есть 100% типовых конфигураций это не авторитетный источник?

    Есть ещё такая штука как читаемость и однотипность кода. Писать надо не так, как удобно, а так, как принято…Я разрабатываю типовые конфигурации(не в фирме 1С) и если я напишу подобный конструктор меня вероятно выгонят ))

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

    Вы можете создавать документ на основании из списка Счетов. Список счетов это динамический список и если в этом списке кто-то установит отбор, то Ваш код перестанет работать.

    Reply
  18. Betis

    (17) slazzy, Вы можете создавать документ на основании из списка Счетов. Список счетов это динамический список и если в этом списке кто-то установит отбор, то Ваш код перестанет работать

    Установил отбор, выбрал сразу несколько документов из списка — ничего не сломалось, ДанныеЗаполнения = первый документ типа счет из списка счетов. Ну да ладно, все равно больше так не буду.

    Кстати, написал письмо в УЦ №1 по-поводу конструктора Новый. Если ответят дам знать.

    Reply
  19. vasyak319

    (14)

    При интерактивном вводе нового из формы списка параметр является структурой, элементы которой соответствуют тем параметрам отбора формы списка, у которых способ сравнения Равно или ВСписке с единственным элементом списка. Если таких элементов отбор списка не содержит, данный параметр равен Неопределено
    Reply
  20. slazzy

    (18)

    точнее я слегка перепутал. Попробуйте установить отбор в списке договоров и создать договор из этого списка.

    Кстати, написал письмо в УЦ №1 по-поводу конструктора Новый. Если ответят дам знать.

    До чего ж упёртые бывают люди ))

    Reply
  21. Betis

    (19) slazzy, договоров нет, что Вы имеете в виду под договорами?

    Reply
  22. Betis

    (20) vasyak319, В форме списка устанавливал отбор на «=» (по сумме») и на «всписке» (на контрагентов). Ошибки не случилось.

    Reply
  23. slazzy

    (21) я просто туплю, извините :)) по работе договор делаю

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

    Reply
  24. Betis

    (23) slazzy, Все понял наконец-то, получилось сломать). Как Вы все успеваете и договора делать и меня подтягивать?)

    Reply
  25. TODD22

    (16)

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

    И в чём удобство?

    Если набрать «Сообщ» без кавычек и нажать ctrl+q сработает автоподстановка шаблона «СообщениеПользователю».

    Посмотрите как там создаётся объект.

    Reply

Leave a Comment

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