Как в СКД получить средневзвешенное значение в итогах отчета




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

13 Comments

  1. Поручик

    Пока полезной не оказалась, но на будущее пригодится. Если сейчас не набежит местный бомонд и не разнесёт на корки.

    Reply
  2. anig99

    В книгах и статьях про ресурсы СКД всё это есть.

    Reply
  3. bayce

    Отчет может дать немного труднообъяснимый результат по менеджерам.

    Reply
  4. Petr54-ru

    (3) bayce,

    Все на специфику бизнеса завязано, специфика кривая, как турецкая сабля — работа реселлера в канале. Это всего лишь один из комплекта отчетов, которые «мотают» и менеджеры и руководство. Смысл отчета — видеть, что происходит и не падать ниже определенной планки по рентабельности. У всех вендоров практически непрерывно происходят акции, валютный курс тоже на месте не стоит, наценка в канале маленькая и пролететь мимо кассы очень просто, бдительность терять нельзя.

    Однако статья вовсе не про это, а про получение в СКД средневзвешенного значения в итогах. Такая задача где угодно может выскочить.

    Reply
  5. zqzq

    Вспомогательное поле ИМХО красивее добавлять на вкладке «Вычисляемые поля» в СКД. Там доступны расширенные функции СКД, функции общих модулей и т.д., а СКД само уже запрос сгенерирует, если есть обращение к БД в поле. +Запрос не захламляется.

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

    Вообще если оставить относящееся к СКД, то будет только нестандартное (не по умолчанию) вычисление ресурса. Более интересно было бы, например, особенности соединения наборов данных в СКД (при вычислении итогов по группировкам считает итоги ДО соединения и не задваивает количества, если ключ связи неуникальный). А вообще лучше Хрусталёву прочитать (+курс Гилёва для введения в тему).

    Reply
  6. ferre

    «Тот самый хрестоматийный пример: был закуплен товар тремя партиями одна из которых – 100 тонн по 70 ф. ст. за тонну, другая – 300 тонн по 80 ф. ст. за тонну и третья – 50 тонн по 95 ф. ст. за тонну, то в общей сложности он закупает 450 тонн товара; обычная средняя цена закупки составит (70 + 80 + 95) : 3 = 81,7 ф. ст. Средневзвешенная цена с учетом объемов каждой из партий равна (100 × 70) + (300 × 80) + (50 × 95) : 450 = 79,4 ф. ст. за тонну.»

    Решение (в ресурсах):

    СУММА(ВычислитьВыражениеСГруппировкойМассив(«Количество*Цена», «Партия»,,))/Сумма(Количество)

    ВычислитьВыражениеСГруппировкойМассив(«Количество*Цена», «Партия»,,) вернет массив из (100 × 70); (300 × 80); (50 × 95);

    Не забываем поставить для поля «Партия» — «обьязательное».

    ПС: с 8.2.14

    Если кому интерестно могу создать публикацию.

    Reply
  7. Petr54-ru

    (6) ferre,

    На мой взгляд была бы востребована публикация про «продвинутую» работу с ресурсами в СКД. В литературе в основном примеры с ресурсами вида:

    Поле Выражение

    Рожно Сумма(Рожно)

    В упомянутой в коментах книжке Хрусталевой — Е.Ю. Хрусталева «Разработка сложных отчетов в 1С Предприятии 8. Система компоновки данных (2008)», иная работа с ресурсами есть только в Примере №10 в Главе 4.

    Есть еще двухтомник «Профессиональная разработка в системе 1С:Предприятие 8 (1С Паблишинг 2012)», там есть во втором томе Глава 16 — «Сложные аналитические отчеты». Пример №17, — там тоже нетривиальная работа с ресурсами, и все. Во всяком случае, я больше ничего не видел. Я считаю, что информации по продвинутой работе с ресурсами крайне мало и статья с примерами, близкими к реальным пошла бы на ура. У меня пока хорошего материала из своей личной практики в нужном для статьи объеме нет.

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

    Reply
  8. IntSergey
    Возникает вопрос, — с какой рентабельностью отработал менеджер в отчетном периоде. Для корректного ответа на этот вопрос нужно вычислить средневзвешенное значение рентабельности.

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

    Для того чтобы в СКД получить средневзвешенное по рентабельности в конструкторе запроса создаем вспомогательное поле вида произвольное выражение, куда записываем произведение рентабельности на выручку. Назначаем этому полю псевдоним – ВспомогательноеПоле.

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

    Для колонки отчета «ПроцентРентабельности» прописываем выражение Сумма(ВспомогательноеПоле)/Сумма(Выручка).

    Ты будешь крайне удивлен результату

    Сумма(Валовая прибыль)/Сумма(Выручка)

    Мне кажется ты запутался.

    Средневзвешенная цена с учетом объемов каждой из партий равна (100 × 70) + (300 × 80) + (50 × 95) : 450 = 79,4 ф. ст. за тонну

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

    И считается она классически итого по сумме разделить на общее количество.

    Reply
  9. sapervodichka

    Может пригодиться, информация, по новым возможностям 8.3: В языке выражений системы компоновки данных реализованы следующие функции: ACos(), ASin(), ATan(), Sin(), Cos(), Tan(), Exp(), Log(), Log10(), Pow(), Sqrt(), Окр(), Цел(), ТипЗначения(),Тип().

    В языке выражений системы компоновки данных реализованы следующие агрегатные функции: Каждый(), Любой(), СтандартноеОтклонениеГенеральнойСовокупности(), СтандартноеОтклонениеВыборки(), ДисперсияВыборки(), ДисперсияГенеральнойСовокупности(), КовариацияГенеральнойСовокупности(), КовариацияВыборки(), Корреляция(), РегрессияНаклон(), РегрессияОтрезок(), РегрессияКоличество(), РегрессияR2(), РегрессияСреднееX(), РегрессияСреднееY(), РегрессияСреднееSXX(), РегрессияСреднееSYY(), РегрессияСреднееSXY().

    Reply
  10. echo77

    Автор, акцентируйте внимание на том что в ресурсах СКД может быть написано достаточно сложное выражение, отличающееся от СУММА(Ресурс) или КОЛИЧЕСТВО(Ресурс) — для новичков это хороший толчок в нужном направлении.

    Сам многое для себя открыл когда это узнал и кстати, первым где я это использовал это тоже был расчет процента по формуле СУММА(Показатель1)/СУММА(Показатель2)

    Reply
  11. Petr54-ru

    (10) echo77,

    Статья собственно про две фишки СКД, как я в заключении написал

    С технической точки зрения, некоторую сложность могут представлять два момента – создание в отчете вспомогательного поля, и возможность использования произвольного выражения в ресурсах СКД, для расчетов нужных нам итогов.

    Я с вами полностью согласен, пока лично в это не упрешься, осознание не придет. Есть пара книжек — Разработка сложных отчетов в «1С:Предприятии 8.2″. Система компоновки данных», ссылка — http://v8.1c.ru/metod/books/book.jsp?id=389 , там среди немалого количества примеров только один пример где в ресурсах есть выражение отличное от Сумма(Рожно) или Среднее(Рожно), есть еще книжка — Профессиональная разработка в системе 1С:Предприятие 8″, ссылка — http://v8.1c.ru/metod/books/book.jsp?id=401 , там тоже один единственный пример нетривиальной работы с ресурсами. Во всем объеме этих материалов по СКД информация о ресурсах просто теряется.

    Reply
  12. dim369

    (8) IntSergey,

    Средневзвешенная цена с учетом объемов каждой из партий равна [(100 × 70) + (300 × 80) + (50 × 95)] : 450 = 79,4 ф. ст. за тонну. Так будет правильнее с учетом последовательности операций 🙂

    Reply
  13. Aleksey.z

    А почему именно среднее арифметическое? Учитываете ли робастность?

    Reply

Leave a Comment

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