Работаем с датами в запросе




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

38 Comments

  1. MoneG2

    Решение интересное, но есть более простое 😉

    http://www.forum.mista.ru/topic.php?id=388253 (23 пост)

    Reply
  2. a-novoselov

    (0) Да уж, чего-то перемудрил с преобразованием. Намного проще ‘цифры строкой’ в параметре запросу передать и не мучаться, раз уж «1С Язык запросов, чем-то похожий на SQL» не умеет типы преобразовывать.

    Reply
  3. alexk-is

    (2) А если так?

    Reply
  4. a-novoselov

    (3) Да так тоже очень изящно, молоток. Просто, как ты сам же любишь говорить, не взрывай мозг, делай проще.

    Reply
  5. RailMen

    не дай бог такое увидеть в чей-то базе

    Reply
  6. RailMen

    а само решение интересное

    Reply
  7. Поручик

    (5) Это ещё не самое худшее, что можно увидеть в чьей-то базе.

    Не дай бог увидеть в чьей-то базе то, что есть в других некоторых базах, вот где жесть.

    Reply
  8. AlexO

    А что за задачи такие — выбрать даты? Откуда, что за даты?

    Reply
  9. CheBurator

    Что есть «банковский день»?

    Reply
  10. CheBurator

    (10) если говорить прямо: лабуда. что значит «обычно банковский день продолжается с 10 до 16 часов.», а необычно? каким законодательным актом устанавливается банковский день?

    Reply
  11. alexk-is

    (11) Наверное, ни какого законодательного акта нет. Это скорее экономический термин чем законодательный. Но его некоторые используют при заключении договоров, оговаривая короткие сроки оплаты.

    Reply
  12. shea

    как соединить 2 таблицы в запросе, при этом у таблиц нет общих реквизитов? можно добавить нуда колонку, например 1, 2 3…. и в другую также, потом по этим соединить?

    Reply
  13. alexk-is

    (13) Какой должен быть результат?

    Reply
  14. SergeyGladyshev

    Долго искал, как вывести даты из определенного диапазона, а тут нашел! Автору статьи респект!

    Reply
  15. sa1m0nn

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

    Но считаю самым оптимальным в плане производительности и разработки вот такой:

    ВЫБРАТЬ ДатаКалендаря ИЗ РегистрСведений.РегламентированныйПроизводственныйКалендарь ГДЕ ДатаКалендаря МЕЖДУ &ДатаНачала И &ДатаОкончания

    Минус — только один, производственный календарь должен присутствовать в конфигурации, и должен быть заполнен.

    Reply
  16. AndrewEv

    2739 — год конца света

    Reply
  17. dem_mad

    Спасибо! Решение интересное.

    Reply
  18. velichutin

    Как пример использования дат в запросе хороший. В своей повседневной работе стал использовать. Нету структурированности в данной статье, а так все здорово!! Спасибо.

    Reply
  19. iotkin

    Спасибо! С удовольствием плюсую!!!

    Reply
  20. bolush

    спасибо круто все

    Reply
  21. N_aix

    Решение интересное особенно в том плане, что месяц можно выводить как вздумется, цифрой, строкой…

    Reply
  22. sumixam

    Сейчас нашел наконец то что и нужно мне

    Reply
  23. k1us181b

    ГДЕ Десятки.Цифра * 10 <<?>> РАЗНОСТЬДАТ(&НачалоПериода, &КонецПериода, ДЕНЬ)

    непонятно немного 🙁

    Reply
  24. alexk-is

    (25) Вернул пропавшие знаки на их место

    Reply
  25. aspirator23

    А как соединить в запросе строковое поле и поле даты?

    Что-то такое:

    ТекстЗапроса=

    …..

    Документ.Номер+» от «+Документ.Дата

    ….

    Через Выразить, подстрока.. не получается

    Reply
  26. alexk-is

    (27) Нужно дату преобразовать к строке и тогда соединить.

    Конечно, это проще сделать после выполнения запроса.

    Reply
  27. aspirator23

    (28) Нагуглил решение как в запросе дату к строке преобразовать. В первом посте именно на него ссылаются.

    Reply
  28. profych1

    Как пример использования дат в запросе хороший. В своей повседневной работе стал использовать. Нету структурированности в данной статье, а так все здорово!! Спасибо.

    Reply
  29. Magister

    Расчет даты оплаты в банковских дней — работает неправильно.

    Передаю дату: 14.03.2013 00:00:00 (четверг)

    Банковских дней — 1.

    Получаю: 17.03.2013 00:00:00 (воскресенье!)

    Передаю банковских дней — 6.

    Получаю: 24.03.2013 00:00:00 (опять воскресенье!)

    Reply
  30. alexk-is

    (31) Magister, после очередного обновления потерялись все знаки сравнения…

    Reply
  31. Magister

    (32) Спасибо за оперативность, вижу уже исправлено 🙂

    Правда я и сам успел уже дойти до исправления.

    Reply
  32. Al-X

    Спасибо ! Мне Пригодится ))))

    Reply
  33. PLAstic

    Вчера прочитал эту статью, сегодня понадобилось сделать то же самое (просто календарик). Не понравился пример, за пару минут наваял свой текст запроса. Получилось красивее, имхо. Увеличение диапазона на порядок требует добавления лишь одной строки в текст запроса.

    ВЫБРАТЬ
    0 КАК Единица
    ПОМЕСТИТЬ ВТЕдиницы
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
    1
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
    2
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
    3
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
    4
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
    5
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
    6
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
    7
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
    8
    
    ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
    9
    ;
    
    ////////////////////////////////////////////////////////////­////////////////////
    ВЫБРАТЬ
    Сотни.Единица * 100 + Десятки.Единица * 10 + Единицы.Единица КАК Дней
    ПОМЕСТИТЬ ВТДоТысячи
    ИЗ
    ВТЕдиницы КАК Единицы,
    ВТЕдиницы КАК Десятки,
    ВТЕдиницы КАК Сотни
    ;
    
    ////////////////////////////////////////////////////////////­////////////////////
    ВЫБРАТЬ
    ДОБАВИТЬКДАТЕ(&ДатаНач, ДЕНЬ, ВТДоТысячи.Дней) КАК Период
    ИЗ
    ВТДоТысячи КАК ВТДоТысячи
    ГДЕ
    ДОБАВИТЬКДАТЕ(&ДатаНач, ДЕНЬ, ВТДоТысячи.Дней) <= &ДатаКон
    

    Показать

    Reply
  34. venger
    Reply
  35. venger

    Ну, или получше решение можно предложить?

    Reply
  36. alexk-is

    (37) venger, предлагаю взять исправленный вариант из статьи 🙂

    Уже терялись знаки сравнения. Видимо не все правильно восстановил. Поправил.

    Reply
  37. venger

    (38) Спасибо:-))) Шикарно! И все даты в списке в начале периода, в независимости от того, какое время у входящих параметров.

    Reply

Leave a Comment

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