<?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='\
Если ДатаДок > ПоследняяЗакупка Тогда
{…1П ДЕФЕКТУРА.ERT(168)}: Операции сравнения на больше-меньше допустимы только над значениями совпадающих базовых типов (число, строка, дата)
1П ДЕФЕКТУРА.ERT(203)}: Поле агрегатного объекта не обнаружено (КоличествоКонОст)
отчет не функционирует
Сейчас посмотрю.
2 ELENAB: Не все так плохо 🙂
2 valent:
Первая ошибка: связана с тем, что я не предусмотрел вариант, когда в партии не указан приходный документ. Видимо у вас метод расчета себестоимости «по среднему»?
Вторая ошибка: тоже моя ошибка, всегда формировал отчет при условии, что дата остатков совпадает с датой конца периода анализа, поэтому просмотрел эту ошибку. Исправлено.
Пожалуйста проверьте.
Спасибо всем, кто принял и принимает участие в тестировании моих разработок.
Жду новых комментариев!
«Дамы и Господа! Не забываем «плюсовать» рейтинг и оставлять комментарии! В противном случае — при несоответствии рейтинга количеству скачиваний — доступ к обработке будет ограничен.»
А какое реальное соответствие рейтинга и количество скачиваний?
А то я вот тоже подумываю закрыть доступ к обработкам!?
2 Starik: «А какое реальное соответствие рейтинга и количество скачиваний?»
:))) Да кто ж его знает?
Просто вначале, когда я размещал первые обработки, качать — качали, а рейтингов и комментариев не оставлялли. Стало как-то грустно, закрыл доступ и повесил этот призыв — оставлять комментарии. Результат через некоторое время проявился, стали иногда оставлять комментарии и рейтинг плюсовать, открыл обратно доступ ко всем обработкам и больше не закрывал. Призыв помещаю в каждую разработку — эффект не очень большой, но все-таки есть. Всем, кто откликнулся на него, мои — огромное спасибо и признательность!
так посмотрел я отчетик прикольный понравился, неплохо былобы добавить еще и разбивку по складам.
и еще почемуто в поставщике вместо справочника контрагентов поподаешь в виды свойств.
)))
Упс! При исправлении прошлой ошибки внес новую 🙂 Исправил 🙂
Уважаемые, пожалуйста скачайте новую версию отчета. Предыдущая версия ВРЕТ!
Сорри 🙂
—
Pan Klyaxa: «и еще почемуто в поставщике вместо справочника контрагентов поподаешь в виды свойств»
Отчет-то делал для себя, поэтому отбор по «основному свойству номенклатуры» назвал «поставщик», т.к. у меня основное свойство номенклатуры — поставщик товара.
А вот с разбивкой по складам — увы. Отчет строится по регистру «Партии», а в нем нет измерения «склад». Если МОЛ реально не используется в учете, то можно вместо склада использовать МОЛ, присвоив каждому складу своего уникального МОЛ. Тогда отбор по МОЛ будет аналогичен отбору по складу.
Если б еще колонку добавить «Количество дней продажи», которая бы показывала на какое количество дней продаж хватает существующих остатков…. )
И еще:
А можно как-то получить реальное количество дней продаж в заданном периоде?
2 valent:
про колонку «Количество дней продажи» — хорошая идея, сделаю 🙂
а вот про «реальное количество дней продаж в заданном периоде» — не очень понял, что под этим подразумевается?
2 valent:
Добавлено 🙂
про колонку «реальное количество дней продаж в заданном периоде» вопрос снимается здесь.
Просто интересно, можно ли получить реальное количество дней продажи, т.е. для примера: если за 30 дней анализируемого периода продажи были только 1, 5, 10 (всего 3 дня).
2 valent:
Теперь понятно, имеете ввиду количество тех дней, в которые непосредственно были продажи товара. Можно, конечно, а практический смысл?
2 wolfsoft:
проследить востребованность товара.
А по регистру продаж аналогичный отчет не получится?
2 valent:
По поводу востребованности товара: мне думается, что это не очень подходящий показатель, хотя… может ты и прав, может кому-то нужен этот показатель. Подумаю, наверное добавлю.
По поводу регистра «Продажи» — в принципе, можно, но есть ряд моментов:
1. там только обороты, определить дейстительное количество дней, которое товар был в продаже, не получится — нет остатков, хотя можно брать из запроса по регистру остатков;
2. нет информации о дате закупки;
3. нет отбора по МОЛ.
Блин, старею 🙂
Окончательно исправил ошибку, которую внес при «исправлении прошлой ошибки».
Уважаемые, пожалуйста скачайте новую версию отчета.
Сорри 🙂
А все можно было бы построить на одном запросе к регистрам ОстаткиТМЦ. Будет быстрее.
«//{{ЗАПРОС(Сформировать)
|Период с ВыбНачПериода по ВыбКонПериода;
|Обрабатывать НеПомеченныеНаУдаление;
|Без итогов;
|Номенклатура = Регистр.ОстаткиТМЦ.Номенклатура;
|Количество = Регистр.ОстаткиТМЦ.Количество;
|Внутреннее = Регистр.ОстаткиТМЦ.Внутреннее;
|Функция КоличествоНачОст = НачОст(Количество);
|Функция КоличествоРасход = Расход(Количество);
|Функция КоличествоКонОст = КонОст(Количество);
|Группировка Номенклатура без упорядочивания без групп;
|Группировка День;
|Условие(Внутреннее<>1);
Вы, извините, глупость сморозили 😉 Сами-то подумайте, отчет еще раз посмотрите, попробуйте, используя свой запрос, получить такой же отчет. Думаю, быстро сами все поймете 🙂
2 lordmb: Не претендую на самое оптимальное решение, наверняка можно как-то оптимизировать, но точно не так, как Вы предложили 🙂
to: wolfsoft
Глупость — не глупость, но я надеялся, не надо будет разжевывать мою мысль. 🙂
И на моей работе мой отчет используется (и выполняется в разы быстрее твоего) 🙂
До твоего отчета мне надо добавить пару мелочей, но суть-то таже самая:
Среднесуточные продажи = продажи/кол-во дней наличия.
У тебя
Если (ОстатокКолво > 0) или (Запрос.КоличествоПриход > 0) Тогда
ДнейВПродаже = ДнейВПродаже + 1;
КонецЕсли;
У меня ДнейВПродаже вычисляется методами ТаблицыЗначений:
ТЗ.НоваяКолонка(«КолвоДней»);
ТЗ.Заполнить(1,,,»КолвоДней»);
ТЗ.Свернуть(«Номенклатура»,»КоличествоРасход,КолвоДней,КоличествоКонОст»);
Короче, думай про меня как хочешь.
2 lordmb: Спасибо, за ап 🙂
По твоей мысли, которую ты не хочешь разжевывать, мои вопросы, которые мне бы тоже не хотелось разжевывать, так как они очевидны:
1. Как твоим ОДНИМ запросом получить отчет, когда, например, анализируем продажи за сентябрь-октябрь 2006 года, а остатки берем текущие на 24-11-2006?
2. Как твой запрос учитывает возвраты?
3. Как твоим запросом получить выручку?
4. Как твоим запросом получить дату и документ последней закупки и последней продажи?
И т.д. и т.п.
Если это называется — «пара мелочей» — то не вижу смысла продолжать обсуждение.
2 lordmb: И еще добавлю, я не хотел Вас оскорбить или обидеть, и я не думаю о Вас плохо 🙂 Нормальный процесс обсуждения 🙂 В принципе, можно подумать про свертку (Ваш предыдущий пост), но в моем случае это скорее всего не ускорит работу, потому что обход группировки все равно делать надо… А основные «тормоза» в отчете появились именно после добавления тех мелочей, которые я перечислил ниже, до этого он работал намного быстрее.
Посмотрим-понюхаем-пощупаем….
Обработка просто СУПЕР ! То что нужно, большинству работников занимающихся заявками для поставщиков , я лишь добавила вывод цены товаров не учавствовший в продажах, и все идеально !
Огромное спасибо !!!!!
Обновлено. Исправлен небольшой глюк при расчете количества дней продажи.
А добавить Иришкины <<вывод цены товаров не учавствовший в продажах>>? Плохая мысль?
2 VV: В моей работе мне это не нужно. Обратитесь к Иришке 😉
Здорово. Чуть-чуть «подкручу» и все будет хорошо. Ставлю «плюс»
Будут вопросы, благодарности прошу к нам на сайт.
>>В противном случае — при несоответствии рейтинга количеству скачиваний — доступ к обработке будет ограничен.
А что, если я скачал, а оказалась фигня, то я тоже должен «+» ставить?
Полезная обработка. Буду на её основе учиться программировать в 1С.
Классная обработка
Я пошел другим путём.Проанализировав по каждой розничной точке сколько чего продается за неделю, поставил минимальный остаток товара на каждую номенклатурную позицию. И заявку делаю согласно минимального остатка по конкретной розничной точке. А если на сезонную закупку (зимние тех. жидкости для автомобилей, например) уже рассчитываю из предыдущей сезонной продажи. Хотя торговля — такой процесс, что предсказать бывает сложно: 2 года назад закупил стеклооомыватель, что и к лету остался, а в прошлую зиму еще и дозаказывали такое же количество 2 раза.