Анализ продаж ABC(прибыль)-XYZ(спрос). Оптимизация отгрузок менеджерами. Отчёт. Авто-документ "Перемещение ТМЦ".




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

35 Comments

  1. Aleksey.Bochkov

    Шрифт = Сервис<<?>>.СоздатьШрифт(Имя,Высота,Жирность,Курсив,Подчеркивание,Зачеркивание,Наклон);

    {C:DOCUMENTS AND SETTINGSALEXEYРАБОЧИЙ СТОЛMANAGER_ANALYZER.ERT(524)}: Переменная не определена (Сервис)

    а где «СоздатьОбъект…»???

    Reply
  2. Aleksey.Bochkov

    «Если LoadAddIn(«FormEx.dll») <> 0 Тогда» в цикле.. очень смешно :)))

    Reply
  3. Aleksey.Bochkov

    Зря сделали автоматическую максимизацию окна при открытии… у меня вообще все сместилось и не понятно что откуда…

    Предусмотрите заполнение настроек X, Y, Z, A, B и С по умолчанию, т.к. я, например, при первом просмотре понятия не имею какие величины там должны быть.

    В общем у меня до формирования отчета не дошло… Смотреть не особо хочется, хотя и тема для меня актуальная.

    Reply
  4. Sprite

    то: albochkov

    // Для FORMEX в глобальном модуле:

    Перем Сервис Экспорт;

    // Переменнная служит для того, чтобы один раз создать объект «Сервис»

    // и в последствии не терять время на его создание в объектах конфигурации.

    // Для формирования значения цвета из составляющих RGB:

    Функция ПолучитьЦвет(Красный = 0,Зеленый = 0,Синий = 0) Экспорт

    // функция для формирования значения цвета из составляющих (RGB)

    Возврат Макс(0,Синий)*65536+Макс(0,Зеленый)*256+Макс(0,Красный);

    КонецФункции

    // Далее в глобадьном модуле:

    Процедура ПриНачалеРаботыСистемы()

    …………

    / /Для работы с Formex

    //пытаемся загрузить компоненту в формате штатной ВК

    Если ЗагрузитьВнешнююКомпоненту(«FormEx.dll») = 0 Тогда

    Предупреждение(«Неудачная попытка загрузить FormEx.dll»);

    СтатусВозврата(0);

    Возврат;

    КонецЕсли;

    Сервис = СоздатьОбъект(«Сервис»);

    //разрешаем использование раскраски таблиц

    Сервис.ВключитьРаскраскуТаблиц();

    ………..

    КонецПроцедуры //ПриНачалеРаботыСистемы()

    Reply
  5. Sprite

    то: albochkov

    // Если LoadAddIn(«FormEx.dll») <> 0 Тогда ……..

    Согласен. Вынес из цикла тремя строками выше. Хотя можно и полностью удалить условие в этой процедуре.

    Reply
  6. Sprite

    то: albochkov

    X, Y, Z, A, B и С — процентные значения относительно средних показателей нормы прибыли (A, B и С) и спроса (X, Y, Z)

    С моими товарами они принимают значения 30<A>100, 20<B>60, 5<C>30

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

    Информацию добавил в описание.

    Reply
  7. Sprite

    Максимизацию окна убрал. Выложил сборку manager_analyzer02.rar

    Reply
  8. viacht

    Мне кажеться на украинских конфах не пойдет

    Reply
  9. Sprite

    Украинские не смотрел. Если там существуют «Регистр.ОстаткиТМЦ» и «Регистр.ПартииНаличие», их измерения и ресурсы соответствуют выборке по Запросам в обработке — почему бы и нет…

    Reply
  10. Happyjack

    Если все будет как в описании, то непонятно где счет автору, куда денег прислать.

    Reply
  11. Sprite

    то: Happyjack

    Пока версия Beta — БЕСПЛАТНО! Всё по-честному. Знакомьтесь, пользуйтесь.

    Жду рекомендации и рейтинг.

    Reply
  12. viacht

    Регистры называются несколько иначе, попробую заменить названия и сообщу о результате.

    Reply
  13. Sprite

    Ок. Очень интересно получить отзыв. Готов помогать советами.

    Reply
  14. Sprite

    manager_analyzer 03

    Добавлен анализ дефицита товара при отгрузке со склада поставщика.

    Изменён порядок определения «Дней продаж». Вычисляем через ТЗ, а не в цикле Запроса.

    Отсечены документы «Перемещение ТМЦ».

    Рассчёт ведется исключительно по документам «Реализация».

    Подшлифованы данные в таблице отчёта.

    Reply
  15. skol

    Посмотрел manager_analyzer 03. Всё о чем писал раньше — так и осталось…

    Сегодня подумалось, что хорошо бы поменять подход…

    Сначала сформировать ABC-XYZ анализ, а из него по каждой конкретной позиции номенклатуры пускать Вашу обработку, т.к. ABC анализ уже покажет рейтинг товара. Кроме того возрастет скорость обработки (или один товар или множество).

    Главная заковыка у менеджеров — результаты ABC анализа. Ну получили — а чего с ним делать??? С группами A и B вроде понятно. А с C? Главная задача — сформировать категории товаров (или ассортиментную матрицу). А ещё главнее — сломать стереотипы менеджеров в подходе к анализу закупа. Ты им наизнанку уже всё вывернул. Доказываешь — товар не продается… По барабану… Извините — отвлекся…

    Попробую реализовать… Напишу.

    Reply
  16. Sprite

    to Skol:

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

    Когда задумал писать эту обработку, предполагал решить несколько задач:

    1. Произвести анализ ассортимента Компании. Оценить состояние товара в рознице относительно спроса и прибыльности. Результаты анализа использовать как аргументацию необходимости формирования ассортиментной матрицы.

    2. Поскольку такой анализ позволяет определиться с грамотным заказом товара для розничных магазинов — значит отгружать с главного склада только необходимое. Лишние товарные запасы — это Проблема. Проблема рассасывается по торговым точкам на кучку маленьких и не заметных проблемок. Задача сконцентрировать Проблему в одном месте (на Главном складе) и там её решать. Как решить проблему лишних товарных запасов, которые теперь явно видны? Конечно — уменьшать закупки, распродавать остатки. Это уже становится понятным даже тупым менеджерам.

    3. Для того, чтобы разгрузить менеджеров по подбору товара на отгрузку (у нас этим занимаются 3 чел. по 1 часу в день) создан документ «Перемещение ТМЦ».

    По товарам группы С…

    Методика подхода: Упрощённые методы планирования и контроля.

    Группа С может быть детализирована на С1 и С2. Например, существуют товары, доля которых в прибыли менее 1% — мы назовём её С1. Товары, доля прибыли которых стремится к 0% — С2. Такие товары целесообразно выделять поскольку они показывают «мёртвый» товарный запас. Это не означает, что такие товары не нужны — возможно, они являются частью экспозиции или зап. частями. Но в любом случае они подлежат отдельному анализу.

    Задайте вопрос: «Что они делают на моём складе? Почему они досих пор находятся в товарной номенклатуре?» А возможно они только введены в ассортимент и являются новыми растущими позициями?

    Вывод: После ABC-XYZ анализа ( прибыль- спрос). Используем стандарные возможности 1С. В карточке товара указываем минимально необходимый остаток для товаров, включаемых в ассортиментную матрицу. А дальше обработка будет автоматом включать необходимые товары в отгрузку.

    Reply
  17. skol

    А что входит в понятие «главный склад»? Если это распределительный центр для всех магазинов и на него идут поступления от поставщиков, и далее по магазинам, тогда подход не понятен . Строить работу надо, [/b] это мое мнение [/b], с системи заказов по поставщикам. Иначе какой смысл? Ненужный товар уже в Компании. И за него надо платить. Или… что такое «главный склад»?

    Reply
  18. Sprite

    to skol:

    Главный склад — это условное название основного склада Компании. Туда поступает товар от поставщиков. С него же товар перемещается на розничные склады (торговые точки). Мы говорим об анализе перемещения товара с Главного склада на розничные склады и об автоматическом формировании документа «Перемещение ТМЦ».

    Действительно, общая проблема оптимизации товарных остатков по компании, мной делится на 2 части. Вторая часть общей проблемы — это оптимизация заказа у поставщиков.

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

    1. Запрещаем поставку в магазин с Главного склада товара (который даёт мало прибыли и не пользуется спросом).

    2. Излишки товара не пользующегося спросом и дающие мало прибыли остаются на Главном складе.

    3. Обязательно буду включать оптимизацию системы заказов у поставщиков в следующую разработку.

    По поводу УЖЕ не нужного товара в Компании, за который надо платить… Согласитесь, это другая проблема! Его надо оплатить и реализовать!

    В общем случае ВАЖЕН РЕЗУЛЬТАТ. И становится не важным с чего начинать.

    С маленькой оговоркой… Почему-то считается что товар сначала должен быть оптимально закуплен. Если магазин открывается, то ДА! А если работает давно и статистика продаж наработана, то ОПТИМАЛЬНЫЙ ЗАКАЗ ОПРЕДЕЛЯЕТСЯ СПРОСОМ ПОКУПАТЕЛЯ и ПРИБЫЛЬЮ ПРОДАЖ!

    … А ход ваших мыслей очень правильный…

    Reply
  19. skol

    1. Запрещаем поставку в магазин с Главного склада товара (который даёт мало прибыли и не пользуется спросом).

    2. Излишки товара не пользующегося спросом и дающие мало прибыли остаются на Главном складе.

    ….

    Получается:

    1. Ваши менеджеры по закупкам товара у поставщиков продолжают работать в прежнем режиме. И везут и нужный и не нужный товар на Главный склад в прежних пропорциях.

    2. Компания платит и за нужный и не нужный товар.

    3. Вы (своей обработкой) оставляете ненужный товар на Главном складе, а нужный отправляете по магазинам.

    => Результат:

    Количество не нужного товара на Главном складе возрастает в арфметической прогресси. Места на Главном складе становится недостаточно. Открываем новый склад. 🙂

    Reply
  20. skol

    P.S. В понедельник слетаю, послушаю что по этому поводу Бузукова говорит…

    Reply
  21. Sprite

    Ну что Вы говорите!

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

    Сейчас мы говорим о первой — оптимизация отгрузок с Главного склада. Решение этой части проблемы — задача данной разработки.

    Что бы вторая проблема ( заказ товара у поставщика ) не мешала нам думать, считаем, что товар закупается Компанией ОПТИМАЛЬНО.

    По поводу кооментария о результате…

    => Результат:

    Количество не нужного товара на Главном складе возрастает в арфметической прогресси. Места на Главном складе становится недостаточно. Наконец-таки решаем закупать оптимальные количества!

    Что делать с уже закупленным товаром? Ответ старый — распродавать!

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

    поболтать было бы тоже интересно.

    Reply
  22. Sprite

    В корне меняю принцип подбора товара в документ «Перемещение ТМЦ»:

    Сначала создаётся ТЧ подобранных товаров в форме обработки.

    Отмечаются товары для переноса в документ.

    Выводятся динамические подсказки по ВК Roberta :http://infostart.ru/projects/1360/

    по каждой строке номенклатуры.

    Если увижу интерес в ветке форума и рейтинг — буду выкладывать для скачивания. 🙂

    В противном случае — по запросу в личку!

    Reply
  23. Sprite

    Что будет в предстоящей версии.

    1. Отдельная табличная часть формы обработки — для анализа номенклатуры. Очень удобно не только для транспортировки товаров в документ, но и для оперативного ABC-XYZ анализа.

    2. Динамические подсказки от Roberta (http://infostart.ru/projects/1360/) на табличной части.

    3. Благодаря отдельной ТЧ на форме обработки не требуется вмешательство в пользовательские конфигурации.

    4. Достигнута универсальность применения.

    5. Уделено внимание удобству восприятия данных.

    Полная Версия Stable будет выложена, по примеру ЧЕ, в качестве Новогоднего подарка на ограниченное количество дней. Следите за веткой форума.

    Советы пока ещё принимаются. 🙂

    ———————————————————————

    Reply
  24. blinick

    В комплексной будет работать

    Reply
  25. Sprite

    Для всех спрашивающих «Будет ли работать с …. Конфигурацией?»

    В обработке происходит анализ продаж по регистру «ПартииНаличие»

    Текст основного запроса:

    «//{{ЗАПРОС(Сформировать)

    |Период с ВыбНачПериода по ВыбКонПериода;

    |Фирма = Регистр.ПартииНаличие.Фирма;

    |Номенклатура = Регистр.ПартииНаличие.Номенклатура;

    |МОЛ = Регистр.ПартииНаличие.МОЛ.ТекущийЭлемент;

    // |СтатусПартии = Регистр.ПартииНаличие.СтатусПартии;

    |Партия = Регистр.ПартииНаличие.Партия;

    |ДатаПартии = Регистр.ПартииНаличие.ДатаПартии;

    |ЦенаПрод = Регистр.ПартииНаличие.ЦенаПрод;

    |Количество = Регистр.ПартииНаличие.Количество;

    // |КодОперации = Регистр.ПартииНаличие.КодОперации;

    |ПродСтоимость = Регистр.ПартииНаличие.ПродСтоимость;

    |Выручка = Регистр.ПартииНаличие.Выручка;

    |Док = Регистр.ПартииНаличие.ТекущийДокумент;

    |Функция КоличествоНачОст = НачОст(Количество);

    |Функция КоличествоПриход = Приход(Количество);

    |Функция КоличествоРасход = Расход(Количество);

    |Функция КоличествоКонОст = КонОст(Количество);

    |Группировка Номенклатура Упорядочить по Номенклатура.Наименование ;

    |Группировка МОЛ;

    |Группировка День;

    |Группировка Партия;

    |Группировка Док;

    |Группировка Выручка;

    |Условие(Фирма в ВыбФирма);

    //|Условие(МОЛ в СписокСкладов);

    //|Условие(МОЛ в СкладПолучатель.МОЛ); остатки только по складу получателю

    |Условие(Номенклатура в СписокЭлементовМФ);

    |»//}}ЗАПРОС

    ;

    Делайте выводы… 🙂

    А для чего выложена демка? Тестируйте!

    Reply
  26. Sprite

    Добавил превью ТЧ Анализа

    Полная Версия Stable будет выложена, по примеру ЧЕ, в качестве Новогоднего подарка на ограниченное количество дней. Следите за веткой форума.

    Советы пока ещё принимаются. 🙂

    Reply
  27. CheBurator

    Чур, я первый записался на бесплатную раздачу!

    Reply
  28. Sprite

    то: Сhe Burashka

    Замётано! Только кто-то обещал и протестировать:-) …. И советов надавать:-)

    Повторюсь, Ваше мнение для меня ценно!

    Reply
  29. Sprite

    Для оценки работы менеджеров, формирующих вручную документ «Перемещение ТМЦ», будет производиться анализ «верных попаданий» менеджером в оптимальное количество отгружаемой номенклатуры!

    Reply
  30. OlegDro

    выдает ошибки «Переменная не определена (Сервис)» и не обнаружена функция «ПолучитьЦвет», Formex.dll версии 2.0.5.82.

    Reply
  31. Sprite

    OlegDro

    //***********************************************

    // Для formex

    //***********************************************

    перем Сервис;

    Функция ПолучитьЦвет(Красный = 0,Зеленый = 0,Синий = 0) Экспорт

    // функция для формирования значения цвета из составляющих (RGB)

    Возврат Макс(0,Синий)*65536+Макс(0,Зеленый)*256+Макс(0,Красный);

    КонецФункции

    Reply
  32. CheBurator

    советую вместо десятичного представленния оперировать 16-ым

    Brush[0xFFCCCC] в нотации BGR — будет гораздо проще — и не надо вычилять кучи функций

    Reply
  33. Sprite

    b] Сhe Burashka [/b]

    Да чего-то уже привык так.

    А привычка — великая весЧь.

    По поводу «раздачи» обновлённой версии.

    Блин, до «после Нового Года» не выйдет. ЗАПАРКА.

    А подшлифовать ещё надо было бы. Кстати, сделал анализ качества «ручного» формирования документа. …Очень интересно….

    Reply
  34. m818rt

    Тоже ошибку выкидывает=(

    Reply
  35. SnegAvik

    Ошибка, а так порылся в коде, нашел интересные для себя вещи)))

    Reply

Leave a Comment

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