Выявление и работа с неликвидом (залежавшимся товаром) и дефицитом номенклатуры




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

22 Comments

  1. windows98a

    Ликвидность я так понял это оборачиваемость в месяц, но очень грубая. В идеале для расчета оборачиваемости должен вычисляться среднемесячный остаток, а не просто браться конечный остаток.

    У Вас инструмент для думающего менеджера.

    Чаще применяется более топорный способ: есть на остатке на конец периода, был на начало периода, нет продаж в периоде, первое поступление было раньше начала периода — вот он неликвид. Такой способ лучше подходит для людей которые не хотят, не умеют или не имеют времени думать. А таких большинство. Во всяком случае по моим наблюдениям:(

    Reply
  2. jobkostya1c8

    С таким методом

    был на начало периода, нет продаж в периоде, первое поступление было раньше начала периода — вот он неликвид

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

    Reply
  3. ogre2007

    (1) windows98a,

    Чаще применяется более топорный способ: есть на остатке на конец периода, был на начало периода, нет продаж в периоде, первое поступление было раньше начала периода — вот он неликвид.

    Таким способом неликвид не скоро найдется. При такой аналитике об оперативной работе с неликвидом речи не может быть.

    (2) kostyaomsk,

    Дальше уже фантазия автора по раскрашиванию в зависимости от срока «неликвидности» или еще что-нибудь. Удобнее же когда сразу в глаза бросается

    По моему опыту подстраивание системы под 1-2% номенклатуры неэффективно, пусть даже и неликвидной. А если у вас 30-40% неликвида, то проблема точно не в отсутствии раскрасок!

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

    Reply
  4. jobkostya1c8

    Все-таки нужна ли колонка, показывающая сколько дней лежит товар?

    Reply
  5. uvsd2014

    неликвид, потому что экономика неплановая, перепроизводство ненужных товаров, а кому-то может они нужны — информации не хватает. Вон в кап.странах апельсины уничтожают, чтобы не продавать по дешевой цене — это уже не нормально. Отдай их нуждающимся — зачем уничтожать? Что-то с такой экономикой не то..

    Reply
  6. ogre2007

    (4) kostyaomsk,

    Все-таки нужна ли колонка, показывающая сколько дней лежит товар?

    Честно говоря, я ценностью и объективностью этого показателя не проникся, в отличии от ПервойСистемы. Для меня это попытка круглое засовывать в квадратное. Считаю, что эту информацию нужно смотреть не в колонке, а в разрезе документов приходов. Возможно, со временем переосмыслю и добавлю.

    Reply
  7. jobkostya1c8

    (6) интересные решения.

    Reply
  8. ogre2007

    обновил версию, подробности в описании

    Reply
  9. premierex

    Как-то забыли в отчете про розницу… Операции в НТТ, например, не формируют движений по регистру ТоварыНаСкладах. ИМХО, логичней было бы строить запрос по остаткам на основе данных регистра накопления ПартииТоваровНаСкладах. В этом регистре хранятся остатки по всем складам в том числе розничным и НТТ.

    Периодичность расчета ликвидности жестко задана в месяцах. А если регулярность поставок измеряется неделями, например? Как выявить неликвид в интервале, меньшем месяца?

    Отборы, скорее всего надо было сделать универсальными, хотя бы отбор по номенклатуре. Зачастую в большой номенклатурной группе требуется анализ лишь по нескольким проблемным подгруппам. Делать отдельные отчеты для каждой подгруппы?

    И в заключении хотел бы отметить, что анализ не|ликвидности, корректнее было бы производить на основе показателей оборачиваемости товаров, которых в отчете и в помине нет.

    Reply
  10. ogre2007

    (9) premier,

    Операции в НТТ, например, не формируют движений по регистру ТоварыНаСкладах. ИМХО, логичней было бы строить запрос по остаткам на основе данных регистра накопления ПартииТоваровНаСкладах.

    Спасибо за конструктивную критику, давайте обсудим:

    В НТТ товары откуда попадают? Поставщик товары возит напрямую в НТТ? Не представляю себе НТТ, для которой строится такая аналитика по неликвидам — имхо разрыв шаблона 🙂 У нас на серьезных предприятиях неликвид через одно место вычисляют, а вы хотите его в НТТ видеть — круто! Лично в моих серых буднях в НТТ такой аналитики никогда не ведется. В общем случае она ведется по некоторому центральному складу, с которого мы делаем расход на НТТ. И на этот центральный склад обычно возит поставщик товары. И аналитику корректнее делать по общему складу, имхо. Как я понял ситуацию, если мы формируем точку заказа по центральному складу у нас все цифры должны быть корректны.

    И еще, я очень часто вижу проблемы с партиями на предприятиях — поэтому я пока против брать их в качестве основы.

    Периодичность расчета ликвидности жестко задана в месяцах. А если регулярность поставок измеряется неделями, например? Как выявить неликвид в интервале, меньшем месяца?

    Согласен, можно подумать. Отталкивался от месяца, т.к. неликвид у большинства смело вываливается за 6 месяцев, и детализация неделя-день — это пока суета на фоне имеющихся проблем.

    Зачастую в большой номенклатурной группе требуется анализ лишь по нескольким проблемным подгруппам

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

    И в заключении хотел бы отметить, что анализ не|ликвидности, корректнее было бы производить на основе показателей оборачиваемости товаров, которых в отчете и в помине нет.

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

    Reply
  11. ogre2007

    Обновил, оттестил, наслаждайтесь 🙂

    Reply
  12. lutikoff

    ХМ, а где хоть одно слово что это демо?

    Reply
  13. ogre2007

    (12) lutikoff, приношу извинения, не обновил. код открыт, вы можете отключить «заглушку».

    новую версию сегодня залью

    Reply
  14. Fenom

    Неплохо было бы в отборах сделать варианты «по группе из списка» «по списку» «не в группе из списка» и тд.

    это касается как отбора номенклатуры, так и отбора складов

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

    так же и по складам

    несколько неудобно

    Reply
  15. Fenom

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

    Чтобы не учитывать продажи между собственными организациями

    Reply
  16. ogre2007

    (14) Fenom, спасибо, учту в следующих разработках

    Reply
  17. sknarid

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

    Reply
  18. ogre2007

    (17) sknarid,

    У вас какая программа стоит на рознице: также УТ, Розница, Frontol… ? Есть центральная программа, хэд-офис, в которой собирается информация по движению товаров по розничным магазинам? Хорошо бы знать архитектуру информационной системы.

    Если УТ или ККМ (Frontol, Штрих, …), которая выгружает отчеты по продажам в центральный офис, где стоит УТ10.3, тогда обработку можно использовать в текущем виде. Если что то другое — пишите, обмозгуем 🙂

    Reply
  19. Gallakr

    Добрый день. Подойдет ли эта обработка для Комплексной автоматизации 1.1.44?

    Reply
  20. ogre2007

    (19) Gallakr, проверка совместимости не проводилась. Если есть потребность, можем проверить.

    Reply
  21. rounder

    что то я так и не понял как вывести отчет, чтобы хоть что то заполнил!

    демо отключил

    Reply
  22. German_Tagil

    не понял — что значит используете демоверсию с ограничением?

    скачал Работа с неликвидом и дефицитом 1.6.3

    Reply

Leave a Comment

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