1с скд запрос в остатки не попадают движения последней секунды
1С 8.1 (8.1.13.41).
Регистр накопления, вид регистра Остатки.
Измерение Клиент, ресурс Сумма, реквизитов нет.
Ситуация:
10.01.2009 23:59:59, приход, клиент А, 100 руб.
Запрос:
ВЫБРАТЬ
ДСОстатки.Клиент
ИЗ
РегистрНакопления.ДС.Остатки(&НаДату) КАК ДСОстатки
ГДЕ
BI_ДСОстатки.Клиент = &Клиент
Результаты выполения запроса:
НаДату 10.01.2009 23:59:59 = 0
НаДату 11.01.2009 00:00:00 = 100
_______________________________________
Приход был последней секундой 10 янв., но 1С считает что приход был уже 11 янв. Как изменить запрос чтобы получить правильные результаты.
Очевидные решения вроде вычитания 1 секунды при проведении документа (если дата документа равна концу дня) или прибавление 1 секунды при построении запроса просьба не предлагать, ибо логически это неверно.
Так и делаю. Нужная дата - 10 января, т.к. нужны остатки на конец 10 января. Получаю 0, хотя ожидал получить 100.
"Запрос.УстановитьПараметр("НаДату", новый Граница(КонецДня(НужнаяДата),ВидГраницы.Включая));"
Всё получилось. Большое спасибо.
"Здравствуйте, возникла проблема при использовании границ в параметрах запроса.
Помогите, пожалуйста!
1С версия 8.2
В построителе запроса использую следующую конструкцию:
Построитель.Параметры.Вставить("начПериода", Новый Граница(НачалоДня(НачПериода), ВидГраницы.Включая));
Во время исполнения возникает ошибка:
*************************
: Ошибка при получении значения атрибута контекста (Результат)
Результат = Построитель.Результат;
по причине:
по причине:
<(150, 56)>: Неверные параметры в операции сравнения. Нельзя сравнивать поля
неограниченной длины и поля несовместимых типов.
И ПродажиОбороты2.Регистратор.ДокументОснование.Дата >>= &начПериода
*************************
Т.о. 1с не дает сравнивать в запросе построителя дату с границей.
Пробовала в запросе использовать конструкцию . Дата МЕЖДУ , при выполнении 1с выдает ту же самую ошибку.
"
Перепробовал несколько способов, найденных в интернете, но что-то никак не могу выйти на конец дня в данном случае.
Подскажите что и где прописать, чтобы отчет на конец дня выводил?
(1) для СКД проще всего добавить свой параметр для регистра остатков.
К примеру, если уже есть параметр Дата, то добавить новый параметр ДатаОстатки. Тип Дата(Дата и время). Выражение:
ДобавитьКДате(КонецПериода(&День,"День"),"Секунда",1)
И использовать его для остатков:
РегистрНакопления.ВзаиморасчетыСКонтрагентамиПоДокументамРасчетов.Остатки(&ДатаОстатки, ) КАК Взаиморасчеты
Либо РегистрНакопления.ВзаиморасчетыСКонтрагентамиПоДокументамРасчетов.Остатки(КОНЕЦПЕРИОДА(&Дата, ДЕНЬ), ) КАК Взаиморасчеты
Либо Запрос.УстановитьПараметр("Дата", КонецДня(Дата))
1) либо использовать объект "Граница" с видом границы "включая" - он специально для этого
2) либо тупо как я, когда лень - прибавляя секунду к концу дня или беря начало следующего дня (это одно и то же), потому как чаще всего в СКД приходится
ЗЫ. (2),(3) так в расчет остатков не попадет последняя секунда дня
ЗЫ. Если в СКД, то нагляднее завести отдельный параметр &ДатаОстатков, недоступный пользователю, который будет рассчитывается по формуле от даты отчета (чтобы не загромождать запрос).
(5) а так попадет начало (0:00:00) следующего дня. Тоже вариант - не вариант. Лучше уже Границу пользовать.
(6),(9) Не попадет. Остатки НА начало дня не учитывают никакие движения этого дня, движения нулевой секунды тоже.
ЗЫ. В этом, собственно, хитрость виртуальной таблицы остатков. Она берет остатки НА переданный момент. Если передать туда момент времени проведенного документа, до движения самого документа (сделанные этим моментом времени) учтены не будут. Если передать дату/время, то не будут учтены движения этой секундой. Т.е. получаются остатки "на начало" момента времени. Как-то странно даже азы расписывать :)
(16) Остатки те, что заказывали - на конец 1 апреля (начало второго). Дата/время документа-регистратора вообще не имеют никакого значения.
Я тебе могу все движения регистра за год перевесить на один помеченный на удаление документ в 2045 году, но все отчеты по регистру будут работать корректно (если до регистратора не разворачивать :)
Чисто для конкретности:
Виртуальная таблица Остатки() по-умолчанию берет начало секунды.
Виртуальная таблица Обороты() [ОстаткиИОбороты()] по-умолчанию берет конец секунды.
Но начальные остатки в виртуальной таблице остатков и оборотов рассчитываются точно также, как и в виртуальной таблице остатков - на начало секунды.
Просто уточняю, чтобы народ не запутался. Обороты и конечный остаток ессно рассчитываются включая границы интервала.
Если немножко подумать, то становится очевидным что это единственный возможный способ получения корректной оборотки (начальный остаток + обороты = конечный остаток)
Столкнулся в очередной раз с задачей создания отчета в СКД с выводом по периодам (месяцам) остатков по регистру накопления. Убил на решение несколько часов, перелопатил интернет, перепробовал всяческие варианты настроек полей, параметров и прочее, пока не пришел наконец к рабочему варианту. Оставляю себе в качестве шаблона, поскольку спустя время уверен, что опять все забуду. Надеюсь, кому-то еще поможет сэкономить время или просто напомнить себе те или иные особенности работы СКД.
В качестве примера выбран регистр "Расчеты с клиентами" (Управление торговлей 11, в.11.1.2). Необходимо вывести корректные конечные остатки по этому регистру на конец каждого месяца, причем даже если не было движений в течение определенного месяца. Задача "в лоб" не решается (можете проверить) - указав в качестве периода отчета, например, текущий год и выбрав в отборе клиента, у которого нет движений за этот год, но есть начальный остаток, мы увидим только первый и последний месяцы с корректным конечным остатком, остальные месяцы "провалились":
В инете можно найти рекомендации, как добиться желаемого.
Первое - помимо исходной таблицы остатков (не остатки и обороты, поскольку в данном случае меня интересуют только конечные остатки) надо добавить таблицу со всеми датами. Т.е., если меня интересует этот год, то надо получить список дат на конец каждого месяца этого года - 31 января 23:59:59, 28 февраля 23:59:59 . 31 декабря 23:59:59. Данная таблица с датами соединяется (НЕ объединяется) с основной таблицей (ИсходныеДанные).
В основной таблице добавляем реквизит &Период (у меня это Месяц) как на рисунке, не забываем его же вставить в параметры виртуальной таблицы. Соответственно, для вывода отчета "Период" (он же "Месяц") - это Измерение,
а для связи 2-х таблиц - это Параметр:
Здесь все "переменные" названы по-разному, чтобы не запутаться прежде всего самому, что к чему относится. Также обратите внимание, что здесь ВАЖЕН порядок связи: сначала таблица с датами, потом таблица с исходными данными (не забываем - в СКД связь на данной закладке ЛЕВАЯ).
ЗЫ. Ради интереса проверьте, что будет, если их переставить местами.
Окончательный вариант дает именно то, чего и добивались:
PS. Спасибо Мисте за код запроса, собирающего даты.
PPS. Да пусть не обидятся на меня те, кто решал и публиковал решение этой задачки, я вовсе не претендую на оригинальность, просто хочется свести все воедино прежде всего для самого себя, и чтобы всегда было под рукой.
Момент времени:
Фирма 1С описывает так:
Предназначен для получения и хранения момента времени для объекта в базе данных. Содержит дату и время, а также ссылку на объект базы данных. Используется в качестве значений свойств и параметров методов других объектов, имеющих тип МоментВремени.
Момент времени используется в тех случаях, когда важно различать моменты времени для объектов, имеющих одинаковую дату и время, например для сравнения положений документов на временной оси.
А своими словами:
Момент времени – комбинация даты и ссылки на документ. Позволяет разделить и упорядочить документы в пределах одной секунды, выстраивая все документы в однозначную последовательность. Получение данных при проведении на момент времени гарантирует, что будут учтены движения сделанные в ту же секунду что и проводимый документ, но находящиеся перед ним.
Но есть особенность – документы проведенные в одну и ту же секунду располагаются в произвольном порядке, а не в порядке их физического создания (как было в 7.7).
МоментВремени() – это момент непосредственно ПЕРЕД позицией документа (аналог РассчитатьРегистрыНа(ТекущийДокумент() в 7-рке), а если необходимо получить момент непосредственно после позиции документа, то используйте объект Граница
Код 1C v 8.х
При получение остатков:
"Момент времени" – виртуальное поле, не хранится в базе данных. Содержит объект МоментВремени (который включает в себя ДАТУ и ССЫЛКУ НА ДОКУМЕНТ)
таблица остатков не хранится в БД, а строится в момент обращения к ней.
1. подбирается больший или равный значению ПАРАМЕТР момент времени, на который РАССЧИТАНЫ остатки
2. на этот момент получаются остатки из таблицы итогов
3. если момент времени, на который считаются остатки, не совпадает с моментом времени итогов, то остатки ДОСЧИТЫВАЮТСЯ по движениям.
Граница:
Предназначен для получения и хранения границы некоторого интервала значений. Содержит граничное значение интервала, а также признак включения или исключения граничного значения в интервал.
Используется в качестве значений свойств и параметров методов других объектов, имеющих тип Граница.
Граница используется в тех случаях, когда важно указание включения или исключения граничного значения, например при получении остатков и оборотов регистров накопления, срезов и значений регистров сведений, для задания интервалов запросов.
ВидГраницы – Определяет набор видов границ по отношению к граничному значению:
ВидГраницы.Включая – Граница включает граничное значение.
ВидГраницы.Исключая – Граница исключает граничное значение.
Код 1C v 8.х
Пример получения остатков на дату документа, включая его движения
Код 1C v 8.х
Пример получения остатков на дату документа, но до его движений
Код 1C v 8.х
also Что-то вроде FAQ Отзывов (5) В закладки
Пользователь выбрал период формирования отчета с 1июля по 31. Почему при формировании отчета в него не попадают данные за 31 число?
На самом деле, это одна из самых распространенных ошибок при разработке отчетов. В 1С 8.х дата содержит время с точностью до секунды, и если в своем отчете Вы описываете параметры следующим образом:
то при формировании пользователем отчета с 1 по 31 июля, фактически параметры будут заполнены так: НачалоПериода = 01.07.2010. 0:00:00, КонецПериода = 31.07.2010. 0:00:00. Т.е. данные, отличные от начала дня 31-го числа в отчет не попадут.
Для того, чтобы в отчет попали данные и за весь день 31 июля, необходимо написать в поле Выражение параметра КонецПериода следующее:
КонецПериода = (&КонецПериода,”День”)
Тут КонецПериода() – функция языка выражений системы компоновки данных.
четверг, 5 июля 2018 г.
СКД. Граница периода
или в выражении параметра Период (тип Дата) указать конструкцию
ВЫБОР &Период КОГДА ДатаВремя(1,1,1) ТОГДА ДатаВремя(1,1,1) ИНАЧЕ ДОБАВИТЬКДАТЕ(КОНЕЦПЕРИОДА(&Период, "ДЕНЬ"), "СЕКУНДА", 1) КОНЕЦ
Всё это обусловлено тем, что остатки виртуальной таблицы получаются на начало секунды, тем самым при проведении документов мы будем получать актуальные остатки на момент перед датой документа, а не после.
skype: live:di-sem
@programmist_1C
Запретить СКД изменять запрос. СКД меняет запрос. СКД оптимизирует итоговый запрос.
Сегодня неожиданно столкнулся с такой проблемой. Был очень удивлен.
Сделал сложный запрос в консоли запросов. Этот запрос планировал использовать для отчета СКД.
Радостный добавил запрос в СКД и тут получаю другой результат.
До этого ни разу с такой проблемой не сталкивался и поэтому долго искал причину. СКД изменил запрос! Это. как бы помягче сказать очень неприятно!
В итоге обрезал место, где скд меняет запрос и через консоль СКД начал мучать отчет.
Вот простейший запрос. 2 временные таблицы и выборка.
Что делает запрос:
Нужно по менеджеру выбрать клиентов, которым он продал на сумму параметра &порогВыручкиПоТорговойТочке. Просуммировать сколько у каждого менеджера таких клиентов.
Как делает:
1 Из регистра накопления "ПродажиОбороты" выбирает записи за определенный период во временную таблицу "ПродажиЗаПериод".
2 Делает выборку Менеджер, Контрагент, Выручка, выч.поле "Торговая точка подходит под категорию"(если сумма выручки больше &порог то 1 иначе 0). Пишет выборку во временную таблицу "Торговые точки".
3 Делает выборку из "торговые точки". Группирует по менеджерам, суммирует поле "ТорговаяТочкаПодходитПодДиректорию".
ПродажиЗаПериод.Контрагент,
СУММА(ПродажиЗаПериод.Выручка) КАК Выручка
ПОМЕСТИТЬ торговыеТочки
ИЗ
ПродажиЗаПериод КАК ПродажиЗаПериод
СГРУППИРОВАТЬ ПО
ПродажиЗаПериод.Менеджер,
ПродажиЗаПериод.Контрагент
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
торговыеТочки.Менеджер КАК Менеджер,
СУММА(торговыеТочки.ТорговаяТочкаПодходитПодКатегорию) КАК ТорговыеТочки
ИЗ
торговыеТочки КАК торговыеТочки
СГРУППИРОВАТЬ ПО
торговыеТочки.Менеджер
Красным я выделил что удалит СКД. Можете сами проверить. Соответственно запрос становится совершенно неправильным.
Теперь выручка считается не по контрагентам, а просто по каждому менеджеру.
Вот сравнение через блокнот.
Причина найдена.
Удаляет он "ПродажиЗаПериод.Контрагент" потому что я не использую это поле далее. Логично. Мне нужно чтобы он не удалял группировку по "ПродажиЗаПериод.Контрагент".
Искал ответ в интернете.
Предложили такие способы. НЕ ПЫТАЙТЕСЬ ВСЕ ИХ СРАЗУ ПРОВЕРИТЬ, В КОНЦЕ ПРЕДЛОЖУ ПРОСТЕЙШЕЕ РЕШЕНИЕ.
1 В выборку добавлять не просто поле, а через выразить. Типо "Выразить(ПродажиЗаПериод.Контрагент как справочник.пользователи). НЕ СРАБОТАЛО
2 Вытащить это поле в конечную выборку и для поля в роли выбрать "обязательное". У меня 10 временных таблиц до конечной выборки, через все буду тащить? НЕ СТАЛ ПРОВЕРЯТЬ
3 Грузить в скд уже готовый набор данных. Вот это верный подход. Посмотреть его можно тут. Работать он точно будет. Возьму на вооружение.
Итак простейшее решение.
1 НЕ ДОБАВЛЯТЬ В ВЫБОРКУ ПОЛЯ, КОТОРЫЕ НЕ БУДЕТЕ ИСПОЛЬЗОВАТЬ ДАЛЬШЕ.
2 А КАК ЖЕ ДЕЛАТЬ ГРУППИРОВКУ? ЛЕГКО! ДЛЯ ЭТОГО НЕ НУЖНО ДОБАВЛЯТЬ ПОЛЕ В ВЫБОРКУ. НУЖНО ПРОСТО ПЕРЕЙТИ НА ВКЛАДКУ "ГРУППИРОВКА", ОТКРЫТЬ СПИСОК "ВСЕ ПОЛЯ" И ВЫБРАТЬ НУЖНОЕ ПОЛЕ. ВОТ ТОГДА СКД НЕ БУДЕТ УДАЛЯТЬ ВАШУ ГРУППИРОВКУ!
Очевидно, но т.к. я нигде не нашел такого решения, решил сделать эту статью.
Покажу на этом же примере.
Вот как нужно делать:
Этот запрос СКД не будет оптимизировать, т.к. теперь он сделан корректно.
Читайте также: