ТиС 7.7: Остатки ТМЦ в колонках по фирмам




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

21 Comments

  1. Ёпрст

    Весьма странный код..

    -Зачем 2 раза выполнять запрос ?

    -Чем обычная ведомость по остаткам не угодила ?

    -Зачем 2 раза Группировка Фирма в тексте запроса ?

    -Про Все ВошедшиеВЗапрос знаем ?

    Итого — в топку.

    Если (Наим.ПринадлежитГруппе(Наимен)=1) Тогда

    {.. .ОСТАТКИПОФИРМАМ.ERT(48)}: Значение не представляет агрегатный объект (ПринадлежитГруппе)

    Reply
  2. Ёпрст

    +1 Весьма странный фильтр.. гораздо проще типовой отчет переделать для разворота «направо» по любой группировке… там и МФ есть и настройка группировок и т.д.

    Reply
  3. tandy82

    Не спорю код может и не самый оптимальный. Все придет с опытом.

    На гениальность не претендую.

    Что значит «Итого — в топку» вроде все верно считает ?

    А ошибка в модуле при выборе какого поля появилась ?

    Reply
  4. tandy82

    Что касается запросов:

    1 запрос для того чтобы вывести названия фирм в шапку отчета

    2 запрос собственно для формирования данных

    можно конечно было сделать все в один запрос, но все равно сбор данных пришлось бы делать в ТЗ (для того чтобы собрать итоги по группам номенклатуры в разрезе колонок фирм, или Вы Ёпрст каким то другом способом это умеете делать?), так что использование Все ВошедшиеВЗапрос здесь погоды бы не сыграло.

    Если бы не требовалось собирать итоги по группам номенклатуры, то тогда не было необходимости в использовании ТЗ и можно было бы воспользоваться Все ВошедшиеВЗапрос

    Reply
  5. Ёпрст

    (4) Ты не поверишь, но умею.. И за 2 раза выполнить один и тот-же запрос — уволил бы к едрени фени.

    И сбор данных в ТЗ — не нужен. И таким способом как у вас вытягивать всю иерархию — не надо, это умеет сам запрос.

    И итоги в разрезе колонок фирмы — сделает вам тоже сам запрос.

    Reply
  6. Ёпрст

    +5 ОДИН … достаточно переделать ШТатную ведомость по останкам.. для разворота Направо.

    Добавив только Все ВошедшиеВЗапрос в группировку по фирме и вывод секций.. и всё.

    Reply
  7. Ёпрст

    Да, на будующее.. Посмотрите, что возвращает метод ПолноеНаименование().. будет вам еще очередное открытие..

    Reply
  8. tandy82

    Если вы мне подскажите, как получить итоги по группам номенклатуры в разрезе колонок Фирм через запрос, я буду очень вам благодарен. Еще раз посмотрел документацию и штатные обработки. Не могу понять как это можно сделать без ТЗ.

    По поводу ПолноеНаименование() — скажу честно не знал, написал свой вариант.

    Теперь знаю, спасибо.

    Reply
  9. Ёпрст

    (8) посмотрите штатную ведомость по остаткамТМЦ в ТиСе ..там всё есть.. и итоги по группам в том числе.

    Разница лишь в выводе «вниз» а не в «право»…

    Reply
  10. Ёпрст

    +9 Без ТЗ — Группировка Фирма Все ВошедшиеВЗапрос и привет..

    + 1 раз выполняешь запрос + 2 раза обходишь группировку фирма:

    один раз для формирования шапки, второй раз — при формировании всей таблицы..

    Обход

    Reply
  11. tandy82

    Ёпрст прочтите еще раз мое сообщение (8). Я уже посмотрел отчеты ТиС: «Остатки ТМЦ» и «Ведомость по остаткам ТМЦ»

    Мне вот интересно вы хоть сами то их смотрели? или так просто написали к слову…

    В отчет «Ведомость по остаткам ТМЦ»

    По группе номенклатуры не выводит итоги по складам (только элементам).

    Используется рекурсивный вызов процедуры ВывестиГруппировку(), в которой по порядку перебираются все выбранные в отчет группировки. Это отчет не выводит итогов по группам элементов номенклатуры в разрезе группировки Фирмы.

    Отчет «Остатки ТМЦ» действительно выводит итоги по группам номенклатуры в разрезе колонок Складов, но что мы видим в модуле — отчет полностью построен на первоначальном накоплении данных в ТЗ и последующем выводе этих данных на экран. Есть даже процедура РассчитатьИтогиПоГруппам(), которая опять таки накапливает данные в ТЗ.

    Запрос выполняется один раз но, по нему проходятся два раза:

    1ый раз когда формируется заголовки шапки

    2раз при помощи команды Запрос.ВНачалоВыборки() когда собираются данные в ТЗ

    По поводу вашего сообщения (4). Если вы посмотрите мой отчет. Запрос действительно выполняется 2 раза. Но если вы еще внимательней посмотрите на него, то увидите что там выполняется 2 разных запроса. Первый запрос выполняется по одной группировке, второй запрос по двум.

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

    Ваше стремление повернуть Отчет «Ведомость по остаткам ТМЦ» не поддается никакой логике. Проще уж переделать отчет «Остатки ТМЦ», там достаточно изменить название группировки «Склад» на «Фирма» по тексту модуля.

    Reply
  12. tandy82

    Ёпрст надеюсь у вас хватит смелости признать что вы были не правы и получить итоги по группам элементов 1ой группировки в разрезе 2ой группировки не возможно без использования ТЗ.

    Если вы это можете сделать в один запрос без использования ТЗ, как вы утверждаете это в сообщении (4), то докажите это?

    Reply
  13. tandy82

    (10) я так понимаю вы запрос видите следующий:

    Номенклатура = Регистр.ОстаткиТМЦ.Номенклатура;

    Фирма = Регистр.ОстаткиТМЦ.Фирма;

    Группировка Номенклатура;

    Группировка Фирма Все ВошедшиеВЗапрос;

    Каким же образом по группе элементов из группировки Номенклатура вы получите итоги по группировке Фирмы? Это запрос выведет:

    НаименованиеТМЦ Фирма1 Фирма2

    ————————————————————-

    Группа

    Элемент Значение11 Значение21

    Элемент Значение12 Значение22

    Для строки Группа1 он не выведет итогов по Фирма1 и Фирма2, которые должны быть Фирма1= Значение11+Значение12 и Фирма2 = Значение21+Значение22. Или вы утверждаете обратное. В 1с откройте данный запрос, посмотрите его результат…

    Reply
  14. Ёпрст

    (12) Не надо меня тут на слабо разводить…

    (13) конечно нет.

    Reply
  15. tandy82

    (14) причем тут ваше слабо, вы сослались на типовые отчеты из ТиС. У меня получение итогов сделано подобный образом.

    Объясните как можно сделать это по другому. Ответье за свои слова в сообщении (5)…

    Reply
  16. Anjelikast

    в отчете к номенклатуре желательно добавить и артикул

    Reply
  17. tandy82

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

    а Ёпрст так и молчит, видимо он посчитал что ответ (14) всех устраивает…

    сдулся дядя, а может надулся от своего самомнения… больше вони было…

    Видимо все таки СЛАБО и по другому сделать нельзя! 😉

    Жду ответа…

    Reply
  18. antares_of

    А в отчете имеется возможность выводить таблицу свернутую по фирмам. Так чтобы только итого было по номенклатуре, без фирм и без складов. Если нет подскажите плиз где такой есть)

    Reply
  19. 1c8.2

    у меня фирмы не выводит. Что можно исправить или посмотреть ?

    Reply
  20. tandy82

    (19) 1c8.2,

    какая у вас конфигурация ?

    Reply
  21. s_uu

    Очень нужный отчет, спасибо. А недовольных критиканов прошу приводить конструктивную критику и без оскорблений автора.

    Reply

Leave a Comment

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