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




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2026-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='\

58 Comments

  1. evgeniti

    декартово произведение вроде бы вполне обходится без конструкций ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПО ИСТИНА

    select

    ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ), ДЕНЬ, 3*(a-1)+b-1 ) as megafunction

    , c as nomenkrlatura

    from

    (select 1 as a union select 2 union select 3) as t1,

    (select 1 as b union select 2 union select 3) as t2,

    (select ‘крокодил’ as c union select ‘красный’) as t3

    ——-

    да и если уж на то пошло почему бы не пихать вместо двух одинаковыйх строчек вида (select 1 as a union select 2 union select 3) — таблицу значений с цифрами, сформированную в коде, в качестве параметра

    Reply ↓
  2. Smaylukk

    Потому что изначально поставил себе цель сделать все одним запросом. Если делать табличку с цыферками — то ее перед запросом нужно сформировать, а при реализации на СКД — вообще такого сделать нельзя, только соединив два набора данных — объект (куда собственно таблица попадет) и запрос, но этот вариант уже реализован.

    Что же к Декартовому произведению таблиц — я указал первоисточник, откуда его взял. Можете почитать, почему автор сделал так — просто он делает как раз то, что мне нужно, а далее я не копал

    Reply ↓
  3. Angeros

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

    Reply ↓
  4. Angeros

    (1)Формировать в табличку в коде не самый быстрый и гибкий метод. Практика показывает делать это в запросе намного лучше и вообще если есть возможность избавится от параметра лучше это сделать, оно и отлаживать удобней.

    Reply ↓
  5. Smaylukk

    (3), вполне возможно. Я просто делал этот запрос по аналогии с регистрами сведений, когда из них нужно было получить такую же табличку(курсы валют, цены номенклатуры, …). Просто запрос работает да еще и не очень долго, а я этого и добивался. Если сделаете с методом дополнения с использованием 1 таблички — респект вам 🙂

    Reply ↓
  6. al_zzz

    А запрос точно рабочий? Запускаю в демке по позиции «Петр I Легкие» за период май 2007. При этом получаю в результате, что был на остатки только в последний день периода, хотя по ведомости есть приход от 5 мая 2007.

    Reply ↓
  7. Smaylukk

    Запрос точно рабочий. Текст запроса, при вставке в пост потерял несколько символов. Ну и плюс, таблица дата, которую я выложил имеет ограниченность в 36 символов. Попробуйте скачать сам отчет или поменять разрядность таблицы дат.

    Reply ↓
  8. al_zzz

    (7) Проверил на самом отчете, количество выдает только на последний день периода, если был всего один приход за период.

    Reply ↓
  9. Smaylukk

    (8) al_zzz, извините, не верно понял предыдущий комент. В тексте зпроса я выбираю НачальныйОстаток и соответственно, если был только один приход — в день прихода начальный остаток не изменится. Поменяйте его в тексте запроса на КонечныйОстаток(временная таблица Остатки) и все должно заработать верно.

    Спасибо за выявленную неточность

    Reply ↓
  10. akor77

    Запрос прекрасно работает. Нужно только добавить одно условие для соединения двух таблиц. Иначе даты с остатками будут «обрезаны» по всем товарам. Пошевелите мозгами сами. Я и так хорошо подсказал.

    Автору огромный респект!!!

    Reply ↓
  11. Smaylukk

    (10), спасибо, очень приятно 🙂

    Reply ↓
  12. uri1978

    Отчет точно рабочий?

    Привожу пример. Меняем дату начала и цифры в отчете разные:



    и

    По-моему опечатка в коде.

    Нужно заменить КоличествоНачальныйОстаток на КоличествоКонечныйОстаток. И тогда отчет заработает, остатки совпадут с «Ведомость по товарам организаций». Т.е. нужно:

     ОБЪЕДИНИТЬ ВСЕ
    
    ВЫБРАТЬ
    НАЧАЛОПЕРИОДА(ТоварыНаСкладахОстаткиИОбороты.Период, ДЕНЬ),
    ТоварыНаСкладахОстаткиИОбороты.Номенклатура,
    ТоварыНаСкладахОстаткиИОбороты.КоличествоКонечныйОстаток
    Reply ↓
  13. Smaylukk

    (12), как я уже говорил вот здесь (9), да — я там выбирал начальный остаток. Уже не помню зачем. Спасибо за внимательный анализ:)

    Хотя вот такая заковыка помогает получше узнать структура и принцип запроса

    Reply ↓
  14. uri1978

    Да, действительно не прочитал комментарии. Спасибо за обработку, натолкнула на правильное решение.

    Reply ↓
  15. Smaylukk

    (14), очень рад, что вам пригодилось

    Reply ↓
  16. Smaylukk

    Во второй временной таблице «ТаблицаДата» условие должно быть следующим:


    ГДЕ

    ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ), ДЕНЬ, t.n) <= &КонецПериода ;

    Последнее убирается при вставке в публикацию.

    Извините

    Reply ↓
  17. petrov_al

    Обратите внимание!!! Запрос корректно отрабатывает не всех ситуациях, например попробуйте например сформировать за период 01.12.2011 по 06.01.2012

    Вообщем нужно либо дорабатывать либо на помойку.

    Reply ↓
  18. petrov_al

    Анализируйте что выдает конкретно этот подзапрос

    ВЫБРАТЬ

    ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ), ДЕНЬ, t.n) КАК Дата

    ИЗ

    (ВЫБРАТЬ

    6 * (t1.a — 1) + t2.b — 1 КАК n

    ИЗ

    (ВЫБРАТЬ

    1 КАК a ОБЪЕДИНИТЬ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВЫБРАТЬ 6) КАК t1

    ВНУТРЕННЕЕ СОЕДИНЕНИЕ (ВЫБРАТЬ

    1 КАК b ОБЪЕДИНИТЬ ВЫБРАТЬ 2 ОБЪЕДИНИТЬ ВЫБРАТЬ 3 ОБЪЕДИНИТЬ ВЫБРАТЬ 4 ОБЪЕДИНИТЬ ВЫБРАТЬ 5 ОБЪЕДИНИТЬ ВЫБРАТЬ 6) КАК t2

    ПО (ИСТИНА)) КАК t

    ГДЕ

    ДОБАВИТЬКДАТЕ(НАЧАЛОПЕРИОДА(&НачалоПериода, ДЕНЬ), ДЕНЬ, t.n) <= &КонецПериода

    УПОРЯДОЧИТЬ ПО

    Дата

    Reply ↓
  19. Smaylukk

    (18) , если вы внимательно читали публикацию — то могли заметить, что в пунтке 2, где я описывал Декартово произведение таблиц — указано, что даный запрос возвращает 36 дней. Запрос вполне рабочий при определенных условиях. Выложен как вариант реализации данной задачи. Все расписано и указаны ссылки первоисточников, так что под свои нужды его очень быстро можно подстроить. Если же вы не в силах это сделать — обращайтесь к специалистам.

    Reply ↓
  20. aspirator23

    Или я не понял, или эта задача решается с использованием СКД.

    Получение остатков на каждую дату решается установкой периода День.

    Reply ↓
  21. Smaylukk

    (20) , возможно и решается. Но основной идеей этой публикации была реализация задачи БЕЗ использования каких-то инструментов кроме запроса.

    Если вам при проведении какого-то документа понадобится данная табличка — вы же не будете СКД туда цеплять 🙂

    Reply ↓
  22. aspirator23

    (21) Согласен, если действительно не нужен отчет.

    Reply ↓
  23. Созинов

    (20) aspirator23,

    не решается, у вас будут остатки не на каждый день. Для этого и выдумывают виртуальную таблицу дат.

    (21)

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

    Еще дополнение — запрос не считает дни, когда товар пришел днем и в этот же день был продан. Я тупо подставил регистр продаж в подзапрос по остаткам 3 объединением. Может кто подскажет как по нормальному сделать подсчет таких дней (утром и вечером нет остатка по товару, остаток только днем)?

    Reply ↓
  24. Smaylukk

    (23) , попробуйте брать НачальныйОстаток + Приход — по идее должно сработать.

    Reply ↓
  25. Гость

    Я выбираю остатки по контрагентам(задолженность), и у меня почему-то в таблице ОстаткиПериодами получаются нулевые периоды, за 1 апреля есть остаток, а за 2 нет….

    Reply ↓
  26. AntonH851

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

    Reply ↓
  27. wildwilduser

    подскажите пожалуйста, может чего недопонимаю

    но вот эта строчка

    МИНИМУМ(ДОБАВИТЬКДАТЕ(ЕСТЬNULL(ОстаткиКонец.НачалоПериода, ДОБАВИТЬКДАТЕ(&КонецПериода, СЕКУНДА, 1)), СЕКУНДА, -1)) КАК КонецПериода
    

    получает конец дня перед ОстаткиКонец.НачалоПериода. это верно?

    я полагаю что должен быть конец дня ОстаткиКонец.НачалоПериода.

    ещё раз возможно что то недопонимаю.

    Reply ↓
  28. Smaylukk

    (27), попробую объяснить:

    • В таблице ОстаткиКонец поле НачалоПериода всегда больше, чем в таблице Остатки.
    • Строка, что вы написали берет минимальную дату, которая больше НачалоПериода в таблице Остатки.
    • Далее, чтобы не было такого, что КонецПериода текущей строки и НачалоПериода следующей не были одинаковы (могут потом быть дублирования) нужно отнять 1 секунду.
    • Ну и последний штрих — для последней записи таблицы уже нет соответствия в таблице ОстаткиКонец, поэтому берем значение параметра &КонецПериода

    Как-то так

    Reply ↓
  29. wildwilduser

    т.е. в таблице ОстаткиПериодами получаем строки двежений, а ДатаНачала и ДатаКонца это даты между движениями по этим позициям?

    Reply ↓
  30. Smaylukk

    (29), Да. И если остаток не менялся за этот период, то мы можем на каждый день в этот промежуток поставить определенное значение.

    Reply ↓
  31. straus

    Касательно объединения в таблице остатков, это необходимо, только на мой взгляд параметр должен быть немного другим:

    РегистрНакопления.ТоварыНаСкладах.Остатки(КОНЕЦПЕРИОДА(&НачалоПериода, ДЕНЬ), ) КАК ТоварыНаСкладахОстатки
    Reply ↓
  32. Smaylukk

    (31), А разве послудеющее объединение

    РегистрНакопления.ТоварыНаСкладах.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, День, , ) КАК ТоварыНаСкладахОстаткиИОбороты
    

    не подтянет эти изменения?

    И вполне возможно, что для учета конечных остатков по дням ваш вариант лучше.

    Но в примере я решил (на свою голову) выбрать начальные остатки по дням, поэтому ваш пример мне не покажет правильной картины, если было движение в в день

    &НачалоПериода

    .

    Спасибо за отзыв

    Reply ↓
  33. straus

    простите за кучу правок, не ожидал, что так быстро ответят. Я пытался получить остатки на начало дня и активно испытывал Ваш запрос.

    тогда нужно совсем удалить объединение с таблицей остатков иначе первой строкой будет остаток именно на начало дня

    Reply ↓
  34. straus

    (32)

    Я получил начальные остатки просто сместив дату в таблице остатков на день вверх, по другому у меня не получилось

    Reply ↓
  35. Smaylukk

    (33) , так ведь начальный остаток и нужен на начало дня :).

    Но если у вас все получилось согласно вашим ожиданиям — тогда все ОК.

    Reply ↓
  36. straus

    так конечный остаток предыдущего дня и есть начальный остаток текущего или я что то не понимаю?

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

    Reply ↓
  37. kauksi

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

    Reply ↓
  38. ildarovich

    Не рекомендую эту статью к использованию. Ну не должна такая простая задача выливаться в запрос из более сотни строк! Более правильное в методологическом смысле решение (опирающееся на понимание устройства виртуального регистра остатков) можно найти в публикации Запрос по остаткам регистра накопления на каждый день, а еще более короткое — в моем комментарии к этой же статье.

    Reply ↓
  39. Smaylukk

    Ну сколько нужно повторять? Запрос написан без использования вспомогательных регистров для получения таблицы дат. Наилучшее решение (даже лучше вашего «короткого») — использовать производственный календарь, там точно есть все даты.

    А относительно количества строк — я расширенно показал, как сделать поставленную задачу. И заданием этой статьи было поделиться знаниями. И думаю это понятнее, чем «вот такой запрос, только даты берите там, где у вас каждый день регистр изменяется (не в обиду автора упомянутой публикации)».

    И на своей базе я не могу посмотреть тем запросом остатки на каждый день. Нет у меня такого регистра.

    После этого вы будете утверждать что мой вариант плохой?

    Reply ↓
  40. Smaylukk

    (37) ,что именно нужно поправить?

    Reply ↓
  41. ABudnikov

    Применил этот метод к данным по своим остаткам.

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

    Пример:

    Есть входящий остаток 50 шт. Период построения запроса с 01.09 по 10.09.

    Остаток менялся 05.09 на 45 шт и 08.09 на 30 шт.

    В результате таблица остатков выглядит следующим образом:

    01.09 — 00:00 | 04.09 — 23:59 | 50 шт — верно

    05.09 — 00:00 | 07.09 — 23:59 | 50 шт — не верно ведь остаток на 06.09 должен быть 45 шт

    08.09 — 00:00 | 08.09 — 23:59 | 45 шт — верно

    09.09 — 00:00 | 09.09 — 23:59 | 30 шт — верно

    Reply ↓
  42. Smaylukk

    (41) ABudnikov, в запросе вы берете НачальныйОстаток или КонечныйОстаток? Если брали запрос из публикации — то там Начальный остаток, о чем указано в статье и что соответствует вашим данным.

    Reply ↓
  43. ABudnikov

    (42) беру НачальныйОстаток — так же как и в статье.

    да и данные я понимаю как получились технически. Но получатся что логически остаток не верный для первой записи из соединения с таблицей остатков по дням — о чем я и написал

    Конечный остаток на 05.09 и соответственно начальный на 06.09 у меня 45 шт.

    А в результате работы запроса показывает что на 06.09 50 шт а не 45 шт.

    Reply ↓
  44. Smaylukk

    (43) ABudnikov, не согласен. Запрос в статье все верно показывает. Смотрим на ваш пример, но я немного расширю таблицу:

    Начало периода |Конец периода |Нач. ост.| Оборот|КонОст | Что берет запрос

    01.09 — 00:00 | 04.09 — 23:59 | 50 шт | 0 | 50 шт | 50 шт

    05.09 — 00:00 | 07.09 — 23:59 | 50 шт | -5 | 45 шт | 50 шт

    08.09 — 00:00 | 08.09 — 23:59 | 45 шт | -15 | 30 шт | 45 шт

    09.09 — 00:00 | 09.09 — 23:59 | 30 шт | 0 | 30 шт | 30 шт

    Reply ↓
  45. ABudnikov

    (44) Хорошо а теперь если эту таблицу соединить с таблицей дат, то получается что на начало 06.09 остаток 50 шт, что не является правильным ответом, т.к. 05.09 произошло списание 5 шт

    У Вас в статье написано: «Далее при соединении с таблицей дат, посмотрев в какой интервал остатков входит дата, получаем нужный остаток Главное правильно построить такую таблицу»

    Так вот получается что таблица периодов не отражает всю действительность.

    Reply ↓
  46. Smaylukk

    (45) ABudnikov, ну так выбирайте конечный остаток и будет вам счастье. Почему оно должно показать вам все правильно, если вы выбираете начальный остаток? Виртуальная таблица оборотов дает 4 даты — начало, конец и даты расходов. В день, когда был расход, начальный остаток не изменялся. Это касается 5 и 8 числа. Т.е. в вашей первоначальной таблице и 8 числа должно быть неправильно.

    Reply ↓
  47. ABudnikov

    (46) 🙂 так задача состоит в том, чтоб получить начальные остатки. Да и 8-го тоже не правильный начальный остаток.

    Т.к. у Вас в описано получение начальных остатков, я просто хотел указать что приведенный запрос не корректно решает описанную задачу.

    Reply ↓
  48. BTRVODKA

    Спасибо, за вашу публикацию!

    Reply ↓
  49. Mails79

    Спасибо.

    Весь фокус в формирование таблицы остатков по периодам.

    Сам бы долго соображал что нужно:)

    Reply ↓
  50. bulpi

    Имхо, ошибка в том, что Вы берете начальный остаток, а не конечный. Пример :

    Товар1,

    нач.остаток 01.01.14 — 5 шт, кон.остаток 3 шт.

    нач.остаток 10.01.14 — 3 шт

    У Вас получится, что с 02.01 по 09.01 нач.остаток 5. А на самом деле он 3!

    Reply ↓
  51. Smaylukk

    (50), да, вы правы. С начальными остатками я перемудрил. Не работает. И если честно, то завис — не пойму как сделать 🙂

    Reply ↓
  52. Smaylukk

    (47), да, вы были правы. Только сейчас до этого допер. Спасибо.

    Reply ↓
  53. Aleksey81

    Автор молодец. Очень полезный код выложил. Важно лишь отметить что в том виде, что он изложен можно использовать период не более 36 дней. Ограничение прямо выходит из способа формирования таблицы дат путем «комбинирования» двух массивов по 6 чисел.

    Reply ↓
  54. JorjKrut

    Ребята, вопрос: а чем вам не нравится стандартный механизм дополнения по периоду в итога? А потом выборку из результата запроса обходить с параметрами: ЗапросРезультат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам, «ПолеПериод», «ВСЕ»);

    Получаем остатки на каждый день таким образом без лишнего геморроя.)

    Reply ↓
  55. JorjKrut

    Кроме того, если дат не очень много, можно объединять таблицы с последовательным увеличением периода виртуальной таблицы остатков и оборотов на один день. См. пример ниже:

    Функция ПолучитьДанныеОстатки(ПериодОтчета)
    
    МассивДатОтчета   = Новый Массив;
    ДатаВМассив = НачалоДня(ПериодОтчета.ДатаНачала);
    ДатаОкончания = НачалоДня(ПериодОтчета.ДатаОкончания);
    
    Пока ДатаВМассив <= ДатаОкончания Цикл
    МассивДатОтчета .Добавить(ДатаВМассив);
    ДатаВМассив = КонецДня(ДатаВМассив) + 1;
    КонецЦикла;
    РазмерМассиваДат  = МассивДатОтчета.ВГраница();
    ЗапросТекстНачало =    «ВЫБРАТЬ
    | ВЫБОР
    |  КОГДА ТИПЗНАЧЕНИЯ(Добавлено_БанкиКассыПланОстаткиИОбороты.БанкКасса) ТИП(Справочник.Банки)
    |   ТОГДА «»БАНК»»
    |  ИНАЧЕ «»КАССА»»
    | КОНЕЦ КАК БанкИлиКасса,
    | Добавлено_БанкиКассыПланОстаткиИОбороты.Группа КАК Группа,
    | Добавлено_БанкиКассыПланОстаткиИОбороты.БанкКасса КАК БанкКасса,
    | Добавлено_БанкиКассыПланОстаткиИОбороты.РасчетныйСчет КАК РасчетныйСчет,
    | Добавлено_БанкиКассыПланОстаткиИОбороты.Огранизация КАК Огранизация,
    | Добавлено_БанкиКассыПланОстаткиИОбороты.Период КАК ДатаПоЗаявке,
    | Добавлено_БанкиКассыПланОстаткиИОбороты.СуммаНачальныйОстаток КАК СуммаОстатокНачало,
    | Добавлено_БанкиКассыПланОстаткиИОбороты.СуммаКонечныйОстаток КАК СуммаОстатокКонец
    |ИЗ
    | РегистрНакопления.Добавлено_БанкиКассыПлан.ОстаткиИОбороты(&НачалоПериода, &НачалоПериода, День, , ) КАК Добавлено_БанкиКассыПланОстаткиИОбороты»;
    ЗапросТекстОбъединить = Символы.ПС + «ОБЪЕДИНИТЬ ВСЕ» + Символы.ПС;
    ЗапросТекстИтоги = Символы.ПС + «ИТОГИ
    | СУММА(СуммаОстатокНачало),
    | СУММА(СуммаОстатокКонец)
    |ПО
    | ОБЩИЕ,
    | БанкИлиКасса,
    | Группа,
    | БанкКасса,
    | РасчетныйСчет,
    | Огранизация,
    | ДатаПоЗаявке»;
    
    ЗапросТекст = ЗапросТекстНачало;
    Для Индекс = 1 По РазмерМассиваДат Цикл
    ЗапросТекстДляДобавления = СтрЗаменить(ЗапросТекстНачало, «&НачалоПериода», «ДОБАВИТЬКДАТЕ(&НачалоПериода, ДЕНЬ, » + Строка(Индекс) + «)»);
    ЗапросТекст = ЗапросТекст + ЗапросТекстОбъединить + ЗапросТекстДляДобавления;
    КонецЦикла;
    ЗапросТекст = ЗапросТекст + ЗапросТекстИтоги;
    
    Запрос = Новый Запрос;
    Запрос.УстановитьПараметр(«НачалоПериода», ПериодОтчета.ДатаНачала);
    Запрос.УстановитьПараметр(«КонецПериода», КонецДня(ПериодОтчета.ДатаНачала)+1);
    Запрос.Текст = ЗапросТекст;
    ЗапросРезультат = Запрос.Выполнить();
    Возврат ЗапросРезультат;
    КонецФункции
    

    Показать

    Reply ↓
  56. Smaylukk

    (54) На момент написания публикации этот механизм давал пропуски, если не было движений по регистру. А здесь важно именно видеть остатки на каждый день.

    Как сейчас обстоят дела — не знаю, не мониторил.

    Reply ↓
  57. AndiA
    Reply ↓
  58. vis_tmp

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

    У вас так же?

    Reply ↓

Leave a Comment

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