<?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) lrs, Благодарю за комментарий. Скажите пожалуйста в какой конфигурации Вы использовали запрос? Мне очень интересна причина, по которой запрос у Вас не работает, но у меня пока недостаточно информации чтобы её понять. За прикрепленные снимки экрана тройная благодарность.
Все очевидно, вы соединяете таблицы по дате, но за даты, за которые не было движений остаток отсутствует, поэтому в итоговой таблице у вас дырки (т.е. по сути нулевые остатки, которые на самом деле не нулевые)
Для примера смотрите картинку, где слева ведомомсть по товарам на складах с разворотом по дням, а справа итог выполнения вашего запроса. (например, 2,3го числа конечный остаток соответствует остатку за 1е число, но ваша таблица показывает 0 за эти дни…)
PS. Чтоб быстрее разобраться, сделайте отбор по одной номенклатуре, по одному складу. И выберите ту позицию для анализа, по которой хотябы один день не было движений.
(3) lrs, понял что Вы имели в виду. Когда тестировал у себя такой проблемы не возникало. В приложении снимок моей ведомости и консоли, в запросе разумеется ничего не менял. Движение товаров также отсутствует за некоторые даты, но строк со значением NULL не появляется. Благодарю Вас за обратную связь, постараюсь разобраться с данной проблемой.
(4) В итоге вы уже пришли ни к остаткам на каждый день, а просто к виртуальной таблице остатков и оборотов. Вы все дальше от решения поставленной задачи))
Даже на титульной картинке у вас пропущены даты (в основном это выходные), когда не было движений)))
Пропущенных дат в итоговой таблице Вы не видите, потому что делаете отбор по основному поставщику, обращаясь а элементам, которые отсутствуют в построенной таблице, либо перенесите отбор в условия таблицы остатков и оборотов (Вот сюда: РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты(КОНЕЦПЕРИОДА(&Дата1), КОНЕЦПЕРИОДА(&Дата2), День, , Номенклатура.ОсновнойПоставщик = &ОсновнойПоставщик)), или уберите его на момент проверки..
(5) lrs, запрос был переосмыслен. Новый запрос возвращает остатки на каждый день даже если не было движений.
Добрый день! Решил переделать Ваш отчет так чтобы он показывал остатки по взаимозачетам на каждый месяц.
Регистр — ВзаиморасчетыСКонтрагентамиПоДокументамРасчетов, Периодичность — Регистратор.
Таблицу календаря беру Кросс-запросом.
В итоге всё получилось, но выяснился прискорбный глюк, который я не смог устранить —
Были движения по документу на НачалоПериода, то есть КонечныйОстаток и Оборот не равны нулю. То есть допустим НачалоПериода = 01.06.2016 00:00:00, и в точности в это же время прошла оплата по реализации ну скажем за апрель, то есть есть скажем ПКО или платежка за 01.06.2016 00:00:00.
В этом случае у нас получается на 01.06.2016 00:00:00 два остатка которые 1С почему то складывает! Итог получается больше на размер остатка на НачалоПериода! Заставить 1С разделить остатки мне не удалось, поэтому я просто сдвинул НачалоПериода на секунду.
В прикрепленной таблице — пример без группировки на суммы.
(7) Здравствуйте, если Вам не сложно пришлите пожалуйста запрос, который получился в итоге. Я попробую у себя его исполнить и найти причину.
Показать
(9) Прогнал запрос у себя. Да есть такое дело. Решение Вы уже описали. Если нужны остатки взаиморасчетов по дням например с 2.01.2017 по 1.27.2017 тогда параметр НачалоПериода устанавливаем на конец предыдущего дня, то есть 1.01.2017 23:59:59. В таком случае в результирующей таблице мы будем видеть корректные остатки начиная с 2.01.2017.
Это конечно не глюк, скорее специфика работы системы. Я когда-то разбирался, пытался понять из-за чего так происходит. Если память мне не изменяет, то такое поведение образуется из-за
Показать
В итоге у меня всё работает правильно и насколько я понял у Вас тоже, верно?
Это однозначно глюк и вот почему. есть такое понятие как Граница. первый остаток дается на границу исключая данное время, а второй — включая. Система должна точно определить, если ей дается время — она остаток должна брать либо включая либо исключая, но никак не складывая одно с другим!
К сожалению в данном случае граница в качестве периода мне не подходит, так как с ней не работают запросные функции работы с датами
интересный подход
(12)Не могу не согласиться)
Спрашивают этот запрос на каждом 2м собеседовании. Или его или срез последних на каждый день.
Задача интересная, но чисто с точки зрения алгоритмики.
Но нужно понимать что на подзапросе вылететь в Out of memory — ну очень просто.
А есть еще вопрос со звездочкой: а что делать если нам постоянно надо обращаться к остаткам (оборотам) на каждый день (например реальная задача — план закупок для большой сети который актуализируется чуть ли не раз в 10 минут).
Правильный ответ: Храните их расчитанными. Ибо как не получай эти данные — или запрос в цикле (хардкод в коде, неявные запросы в цикле при помощи СКД) или гигантские промежуточные результаты. Нельзя получить быстро, что не хранится. Да минусы у этого подхода: 1) рост базы 2) отставание актуальности данных на частоту выполнения регламентного задания. Плюс другой — при частом выполнении данного запроса будет очень сильная нагрузка на базу. И если база большая, или не большая, но период большой, то время выполнения данного запроса будет или не удовлетворительным или начнутся технологические проблемы.
Из своей практики: В реальной жизни данный запрос получается объединением данных за прошлые числа из расчитанного регистра и данные вирт таблиц за сегодня. Все работает более чем быстро.
Остаток на каждый месяц по счету 02 для бух корп
Показать
спасибо, вроде получилось
Для чего конструкция
КОГДА Движения.Период <= ДНИ.ДатаКалендаря
ТОГДА Движения.КоличествоОборот
ИНАЧЕ 0
КОНЕЦ
когда соединение идёт
Может просто Движения.КоличествоОборот?
Вот простой запрос по взаиморасчетам, все работает как надо
Показать