Видеолекция: Подготовка к сертификации 1С:Специалист по платформе 8. Часть 2.




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

23 Comments

  1. Русский

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

    Reply
  2. zaic

    Посмотрел первую часть, очень понравилось. Мастер-классы эти будут очень полезны всем. А тем, кому за свой счет курсы дороги, вообще необходимы. Все очень доходчиво с акцентом на основных моментах. Спасибо большое.

    А сертификаты многим вообще не нужны..

    Reply
  3. anton23rus

    дайте ссылочку на первую часть пожалуйста!!!

    Reply
  4. anton23rus

    т.е на решение первого билета!!!

    Reply
  5. GROOVY
  6. GROOVY

    добавил третью часть

    Reply
  7. manan

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

    Reply
  8. GROOVY

    Все зависит от задачи. По хорошему, так как записи в регистре «ЦеныПоставщиков» подчинены регистратору, то физически документ «Приходная» не проведется с дублями строк. => надо запретить создавать дубли и как следствие не придутся ничего группировать при формировании запроса.

    Reply
  9. manan

    еще сдается мне, что в запросе для дока «Расходная» в обработке проведения для целей ФИФО упорядочить нужно не по Остатки.Партия.Дата, а по Остатки.Партия.МоментВремени. правда не настаиваю 😉

    Reply
  10. clareon

    а не лучше ли в обработке проведения одним циклом обойти все

    Выборка = Запрос.выполнить ().выбрать();

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

    Если Выборка.Количество > Выборка.КоличествоОстаток ТОгда

    Сообщить («На складе » + Склад + » недостаточно номенклатуры » + Выборка.Номенклатура + » для списания!»);

    Отказ = True;

    Продолжить;

    endif;

    Движение = Движения.ОстаткиНоменклатуры.Добавить();

    Движение.ВидДвижения = ВидДвиженияНакопления.Расход;

    Движение.Номенклатура = Выборка.Номенклатура;

    Движение.Регистратор = Ссылка;

    Движение.Склад = Склад;

    Движение.Количество = Выборка.Количество;

    Движение.Сумма = Выборка.Количество / Выборка.КоличествоОстаток * Выборка.СуммаОстаток;

    Движение.Период = Дата;

    enddo;

    если Отказ тогда

    Возврат;

    КонецЕсли;

    «или я не прав где то?

    Reply
  11. GROOVY

    (10) А у меня все в цикле обходится, только движения не формируются если возведен флаг Отказ.

    Reply
  12. clareon

    (11) ну так и должно быть, если отказ — значит отменяется транзакция (которая неявно начинается при проведении ), следовательно, изменения не записываются.

    Reply
  13. GROOVY

    (12) Так а зачем их формировать, если транзакция все равно отмениться? Может я не понимаю предмет нашего спора?

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

    Reply
  14. clareon

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

    Reply
  15. clareon

    GROOVY, так это ваша лекция («(11)А у меня все в цикле обходится») ?

    Reply
  16. clareon

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

    Reply
  17. clareon

    Павел есть 2 вопроса по лекции: 1) Почему запретили оперативное проведение «Расходной накладной»?

    2) Если списать 0 шт. несуществующего товара — ошибка «Деление на ноль», надо ли добавить контроль такой ситуации?

    Reply
  18. clareon

    Павел, когда идте расчет процента скидки, попробуйте сделать его когда объем продаж больше 10 000, судя по вашему запросу скидка будет НУЛЛ, мне кажеться там ошибка.

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

    ВЫБРАТЬ

    ЕСТЬNULL ( МАКСИМУМ (ШкалаСкидокСрезПоследних.Процент), 0) КАК Процент

    ИЗ

    РегистрНакопления.Продажи.Обороты(&Дата1, &Дата2, , Контрагент = &Контрагент) КАК ПродажиОбороты

    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ШкалаСкидок.СрезПоследних(&МоментВремени, ) КАК ШкалаСкидокСрезПоследних

    ПО ПродажиОбороты.СуммаОборот > ШкалаСкидокСрезПоследних.ОбъемЗакупки

    «

    Reply
  19. clareon

    Кроме того, скидка определяется при открытии на дату (или момент) документа, Если теперь пользователь изменит дату на заднее число — то текущая скидка перестанет быть актуальной (в лекции пересчета нет), что тоже ошибочно.

    Reply
  20. GROOVY

    (20) В регистре болжна быть верхнаяя граница указана 99999999999, тогда все тип топ работает.

    (19) В лекциях нигде нет защиты от дурака, это не цель лекций.

    Reply
  21. clareon

    Спасибо за коменты, учимся дальше… !

    Reply
  22. manan

    в расчетной задаче в регистре расчета ДополнительныеНачисления неправильно настроена зависимость по базе. Должна быть по периоду регистрации.

    Reply
  23. GROOVY

    (22) C нетерпением жду объяснений. Почему?

    Reply

Leave a Comment

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