Расчет средних по периодам в запросе — это элементарно!




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

30 Comments

  1. Арчибальд

    Ну, что тут сказать… Остальное вы видели. ©

    Reply
  2. cool.vlad4

    (0) Безусловно молодец, но только можешь объяснить выкладку из рисунка, че-то не соображу с утра никак почему

    Reply
  3. ildarovich

    (2) Вот выкладка для числителя

    s1 + s2 + s3 + … + sn = (s0+d1) + (s1+d2) + (s2+d3) + … + (sn-1 + dn) =
    = (s0 + d1) + (s0 + d1 + d2) + (s0 + d1 + d2 + d3) + … + (s0 + d1 + d2 + d3 + … + dn) =
    = s0 * n + d1 * n + d2 * (n-1) + d3 * (n — 2) + dn * 1

    Из нее, кстати, следует, что в формуле (не в запросе) была неточность — забыл умножение s0 на n. Сейчас поправлю в статье.

    Reply
  4. cool.vlad4

    (3) Ну, вот блин, а я время потратил, бумагу перевел, думаю почему у меня не сходится;-)

    Reply
  5. ildarovich

    (4) Приношу извинения — торопился!

    Reply
  6. cool.vlad4

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

    Reply
  7. alexk-is

    (0) Про быстрые тэта-соединения можно посмотреть здесь http://infostart.ru/public/71130/#Pro_hitrye_zaprosy

    Пример 3

    Расчет периода по рабочим дням легко производится по производственному календарю. Расчет периода по банковским дням можно посмотреть здесь http://infostart.ru/public/68269/

    Reply
  8. losara1983

    Я как раз недавно возился с этой задачей, жаль не нашел вашего метода)

    Reply
  9. hogik

    (0)

    Сергей.

    Пора открывать цикл публикаций «Мы пишем з…» с единым логотипом. 😉

    Восторгаюсь Вашей головой…

    Reply
  10. maljaev

    Формула шокировала 🙂

    Надо будет все свои ТЗ к проектам снабжать аналогичными формулами вместо описания на «общечеловеческом» — для придания пущей важности проекту и уважения заказчика 🙂

    Reply
  11. bulpi

    Объясните тупому (возможно)

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

    Reply
  12. bulpi

    За красоту идеи в любом случае + без разговоров, но все таки ?

    Reply
  13. ildarovich

    (11) Дело в том, что посчитать остатки на каждый день в запросе просто не получится — остатки будут выдаваться только на периоды, по которым есть обороты. В запросе с итогами есть возможность «дополнить периодами», а в пакетном запросе — нет. В запросе люди выкручиваются как могут: гораздо более сложными способами. Примеры можно посмотреть:

    v8: Полные остатки по периоду во вложенном запросе

    v8: Полные остатки по периоду во вложенном запросе по начальному остатку

    Отчет «Среднесписочная численность» для ЗУП 2.5.25

    Reply
  14. bulpi

    (13)

    Спасибо. Про запрос без итогов я не подумал.

    Reply
  15. alexk-is

    Чем раскрашен запрос в публикации? Спрашиваю потому, что вижу это была не Разукрашка.

    Reply
  16. ildarovich

    (15) Не знаю, почему Вы так решили, но я пользовался именно ей.

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

    Reply
  17. alexk-is

    (16) Как почему? Конечно же по HTML-коду. Структура HTML-кода Разукрашки очень специфична, т.к. содержит большое количество различных способов оптимизации. Её очень легко узнать на тексте достаточно большого объема именно по наличию оптимизации.

    Другое дело, если этот HTML-код прошел нескольно уровней преобразования разными редакторами. Тогда от оптимизации уже ничего не останется. Обязательно добавится много мусора.

    Как минимум один уровень преобразования получается при вставке HTML-кода в публикацию на Infostart. Пусть незначительно, но код становится больше.

    Reply
  18. sommid

    спасибо.

    Reply
  19. Antony_2009

    Спасибо за публикацию! Скажите, пожалуйста, а возможно данный метод применить для платформы 1С 7.7?

    Reply
  20. ildarovich

    (19) Думаю, да. Постараюсь в ближайшие дни дополнить статью данным примером.

    Reply
  21. ildarovich

    (19)(20) После более тщательного изучения данного вопроса

    а возможно данный метод применить для платформы 1С 7.7?

    выяснилось следующее:

    1. В 7.7 нет возможности обработки данных в самом запросе, чтобы на выходе запроса сразу получить хронологическое среднее. Идеология 7.7 такова, что запрос является в основном средством получения данных, без их обработки, которая делается в коде.

    2. При задании периода «День» (например), результат запроса будет содержать столько строк, сколько дней в периоде и покажет остатки на каждый день. То есть проблемы запросов восьмерки «получения остатков на дни периода, в которых не было движений», в 7.7 нет. Среднее получается элементарной обработкой полученной в запросе таблицы значений: делением итога колонки на число строк.

    3. В то же время, есть ситуация, в которых имеет смысл применить прием, описанный в статье:

    Если в анализируемом периоде движений заданной номенклатуры существенно меньше числа подпериодов.

    Только в этом случае выгоднее использовать группировку «Документ» и метод, рассмотренный в статье.

    Так, что с примером для 77 сейчас торопиться не буду.

    Reply
  22. Antony_2009

    Спасибо большое за ответ! Вы правы по пункту 3. Например при расчете средней дебеторской задолженности (не каждый день происходят движения), а на получение остатков на каждый день ооочень много времени уходит в запросе. Чтож, буду пробовать по документам.

    Reply
  23. dusha0020

    Да уж. Действительно элементарно, Ватсон! Я бился над проблемой 3 часа, пока не нагуглил статью. Спасибо!

    Reply
  24. truba

    Спешу заметить про 3е ограничение метода. Если в данном примере надобно свернуть номенклатуру по объединяющему реквизиту. К примеру номенклатура1 и номенклатура2 по сути для анализирующего манагера ничем не отличаются, а метод даст движения (и средние) в разрезе каждой номенклатуры. В то время как среднее суммы не равно сумме среднего.

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

    Reply
  25. dpagon

    Спасибо за публикацию! Мне была поставлена аналогичная задача. Применил Ваш метод. Вроде бы есть одна неточность- приведу на примере:

    День 1 2 3 Расчет средней

    Остатки

    1 договор 1000 1000 1000 1000=1000*3(колво дней с остатками)/3(колво дней за период)

    2 договор 500 500 0 !!!500=500*3(колво дней с остатками-верно 2 дня)/3(колво дней за период)

    3 договор 0 300 300 200=300*2(колво дней с остатками)/3(колво дней за период)

    Думаю это из-за того, что и КоличествоКонечныйОстаток, и КоличествоОборот умножаем на РАЗНОСТЬДАТ(Период, &КонецПериода, ДЕНЬ) + 1)

    Попробывал

    СУММА(ВЫБОР КОГДА Период = &НачалоПериода

    ТОГДА КоличествоКонечныйОстаток*(РАЗНОСТЬДАТ(&НачалоПериода, Период, ДЕНЬ) + 1)

    ИНАЧЕ КоличествоОборот * (РАЗНОСТЬДАТ(Период, &КонецПериода, ДЕНЬ) + 1))

    конец / (РАЗНОСТЬДАТ(&НачалоПериода, &КонецПериода, ДЕНЬ) + 1)

    Но так вообще не то…

    Reply
  26. Longinoff

    Спасибо.

    Reply
  27. ildarovich

    Для случая, когда используется метод трапеции, то есть формула расчета среднего учитывает крайние значения с коэффициентом 1/2, данный метод следует слегка изменить. Как это сделать, описано в комментарии http://forum.infostart.ru/forum26/topic45819/message495419/#message495419.

    Reply
  28. zmit

    ildarovich умница. Сколько огромных запросов-расчетов я видел, а это в 3 строки

    Reply
  29. yalex9

    Спасибо!

    Reply
  30. SunShinne

    Автор спасибо!

    Reply

Leave a Comment

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