Продажи по оплате или в поисках истины…

Публикация № 280175

Разработка - Практика программирования

Продажи Продажи по оплате Оплаченные продажи Валовая прибыль Прибыль по оплате

Отчет "Валовая прибыль по оплате" и история его разработки для УТ 10, УПП 1.3 , УТП 1.2 (Россия, Украина, и наверное, для других стран тоже).

Это начало истории. После него появилось продолжение Валовая прибыль по оплате

Скачать отчет можно в продолжении.


Все началось с обычного запроса.

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

Поскольку лечение пилюлями не дало положительного результата, принимаем решение, что хирургическое вмешательство должно помочь. Идем в конфигуратор – и падаем в обморок от увиденного. Клубок запроса где-то на 100 км. размотать, который  уже не получится. 

Легенда (интернет) говорит, что данный отчет создал некий мудрец, который уже не общается с 1С, и который так и не довел этот отчет до ума.

Прошло много времени. Больше года

Все это время проблема всплывала несколько раз, но решение так не находилось, хотя некоторые нюансы прояснить удалось. Например, что для работы отчета «Продажи по оплате» нужно, что бы в договоре были выставлены фаги «вести по документам расчетов» или, что в отчет считает оплаченными только те продажи, которые были оплачены в период формирования отчета.  Все это постепенно привело к тому, что я решил делать свой отчет по оплаченным продажам

Последней каплей стало, дополнительное требование от пользователей, когда такой отчет должен выводится в произвольной валюте, которую должен выбирать пользователь. Причем есть требование к дате, на которую нужно делать переоценку показателей. Сумма продажи должна переоцениваться на дату оплаты, а себестоимость – на дату партии (документ оприходования).

Сначала были определены основные требования к отчету:

  1. Пользователя устраивает отчет «Валовая прибыль» по составу данных. Нужны: количество, сумма и себестоимость проданного товара, с детализацией до: подразделения, проекта, контрагента, заказа, номенклатуры, по дням, месяцам, годам и т.д.
  2. Отчет должен содержать данные о продажах, которые полностью оплачены.
  3. Оплата должна распределятся по отгрузкам с учетом заказов, если по договору взаиморасчеты ведутся по заказам или счетам. Если взаиморасчеты ведутся по договору в целом, тогда оплата распределяется в целом по договору.
  4. Отчет должен иметь все те же возможности по отбору, сортировке, группировке и т.д. что и отчет «Валовая прибыль». Желательно что бы отчет был разработан на базе «Универсального отчета», что бы сохранить юзабилити интерфейса на привычном уровне.
  5. Нужно иметь возможность указывать в отчете валюту и выполнять переоценку суммы продажи по курсу на дату оплаты, и себестоимости – по курсу на дату партии (документ оприходования). 

После определения требований, началась реализация.

Поскольку пользователи сами меня натолкнули на отчет «Валовая прибыль», возникла идея взять за основу запрос из этого отчета. Можно предположить, что отчет «Валовая прибыль» содержит в себе 100 % продаж за указанный период, из которых некоторая часть X%, это те, которые оплачены, а остальные не оплачены. Другими словами, если из этого отчета убрать записи с неоплаченными отгрузками мы и получим нужный результат.  

Алгоритм оказался не сложным:

  1. Находим на инфостарте шаблон отчета желательно на СКД, и похожим на универсальный. Обрабатываем его напильником для юзабилити.
  2. Создаем схему компановки, источник данных «Объект» (таблица, заполняемая программным путем). Добавляем поля и выполняем настройку внешнего вида отчета, таким образом, что бы он был похож на отчет «Валовая прибыль».
  3. Для того что бы программно заполнить СКД, берем и выдергиваем текст запроса из отчета «Валовая прибыль». Убираем из запроса расчет «валовой прибыли», «рентабельности» и «эффективности», поскольку эти показатели будут рассчитаны в СКД как вычисляемые поля. После таких манипуляций  в запросе останется только левое соединение таблицы регистра «ПродажиСебестоимость» с виртуальной таблицей «ПродажиОбороты», регистра «Продажи»,
  4. Результат запроса выгружаем в таблицу значений – «ТаблицаПродаж».
  5. Из таблицы продаж выгружаем в массивы: «МассивКонтрагентов», «МассивДоговоров» и «МассивЗаказов», соответствующие колонки. Данные массивы будут выступать в роли отбора для следующего запроса, для получения оплат.
  6. Далее выполняем еще один запрос к регистру «ВзаиморасчетыСКонтрагентам», с установленными отборами, для получения оплат (Приходы) по контрагентам, договорам, заказам, регистратору и сумме взаиморасчетов. Результат запроса так же выгружаем в таблицу значений – «ТаблицаОплат».
  7. Описываем процедуру, которая в цикле обойдет, все записи таблицы продаж и таблицы оплат и сформирует промежуточную таблицу – «СводнаяТаблица», которая будет содержать только оплаченные продажи. Погашение отгрузок оплатами будет выполнено по методу FIFO.
  8. Данные из «СводнаяТаблица» загружаем в СКД и программно выполняем компоновку данных и вывод в табличный документ.

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

 

УСЛОЖНЯЕМ.

После того как я добился корректной работы отчета в валюте упр. учета, и напильником отшлифовал шаблон универсального отчета на СКД, пришло время и для последней задачи, связанной с переоценкой показателей отчета в произвольную валюту.

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

Ох уж эта переоценка

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

1) Сумма продажи переоценивается в валюту отчета по курсу на дату оплаты. Что это означает для обработки данных? Для полного понимания картины нужно обратиться к истокам - регистрам, в которых эти данные хранятся

Итак, регистры "Продажи" и "Продажи себестоимость". При проведении расходных накладных, программа пишет в эти регистры следующие данные:

 - в регистр "Продажи себестоимость программа записывает себестоимость проданного товара, которая не пересчитывается, а берется, так сказать "готовой", в валюте упр. учета, из регистра учета партий. По сути задачи, данные в регистре "Продажи себестоимость" всегда переоценены в валюту упр. учета по курсу, на дату документа оприходования. Это полностью соответствует нашим требованиям, поэтому останавливаться на этом пункте нет смысла. Единственное что нужно отменить, так это то, что требованиями заложена необходимость иметь возможность пересчитывать себестоимость из валюты упр. учета в валюту отчета, аналогично, по курсу на дату оприходования. Но о том, как это реализовывалось, будет написано ниже.

  - в регистр "Продажи" записывается сумма расходной накладной, которая пересчитывается из валюты документа, в валюту упр. учета по курсу, полученному на дату расходной накладной. Именно на этом я хотел бы заострить внимание. Выходит так, что, если валюта упр. учета равна валюте регл. учета, тогда все решается достаточно просто. Берем сумму продажи и пересчитываем ее в валюту отчета, по курсу, полученному на дату оплаты. Но что будет, если валюта упр. учета будет отличатся от валюты регл. учета? Получится так, что при проведении расходной накладной, суммы в регистре продажи уже будут переоценены из валюты документа, в валюту упр. учета, по курсу продажи, а не оплаты. Поэтому решение, взять и просто пересчитать сумму продажи в валюту отчета, по курсу на дату оплаты, будет не верным, а результат ошибочным.

Для наглядности лучше привести пример и предположим что:

Валюта упр. учета USD
Валюта взаиморасчетов по договору с контрагентом Хк  EUR

 

Дата Валюта Курс
01.01.2014 USD 10 
02.01.2014  USD 15
01.01.2014  EUR 15
02.01.2014  EUR 19

 

Дата  Хоз. операция Сумма Валюта договора
01.01.2014 Продажа 1000.00 EUR
02.01.2014 Оплата 1000.00 EUR

 

Пользователь захотел сформировать отчет в USD, т.е. в валюте упр. учета

Это самый показательный пример, потому что, на первый взгляд, кажется, что здесь даже нечего переоценивать, однако это не так. Причина в том, что именно запишет расходная накладная в регистр "Продажи". А запишет она следующее: 1000.00 $ превратятся в 1500€ по кросс-курсу на 01.01.2014, т.е., на дату продажи. Идем дальше. 02.01.2014 пройдет оплата на 1000$, но программа запишет в упр.учет 1266.67€ по кросс-курсу на дату оплаты. В итоге имеем картину, когда в управленческом учете, продано на 1500€, а оплачено только на 1266.67€, хотя на самом деле взаиморасчеты закрыты.

Нужно понимать, что сравнивать приходится данные регистров: "Продажи" и "ВзаиморасчетыСКонтрагентами".

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

Вернемся к нашему примеру.

Выходит так, что при сравнении оплат и отгрузок программа подумает что, продажа не оплачена и данные не попадут в отчет. Так что же нужно предпринять, что бы получить нужный результат? Сначала нужно пересчитать сумму продажи из регистра "Продажи", из валюты упр. учета, в валюту взаиморасчетов, по курсу на дату продажи, т.е. "вернуть все в зад" на 01.01.2014. И только после этого можно будет сравнивать отгрузки с оплатами, в той валюте, в которой они реально происходили.  А теперь представим, что пользователь выбрал в отчете валюту, например, рубли? В этом случае предстоит еще раз пересчитать сумму продажи из валюты взаиморасчетов, в валюту отчета по курсу на дату оплаты. На самом деле вторую переоценку пройдется выполнять в любом случае, независимо от того какую валюту выберет пользователь.  

А теперь вспоминаем, что все это должно выполняться в запросе, одним махом. 

Облом первый

Оказалось, что запросом получить курс валюты на дату, которая вычисляется из второй таблицы, практически не возможно. Почему практически? Потому что теоретически это возможно. Это делается в два прохода, при помощи вложенного запроса или временной таблицы. Суть метода заключается в том, что бы обратится к регистру "курсы валют" и получить все записи, период у которых, меньше или равен, той дате, на которую нужно получить курс. После это выполнить агрегатную функцию «Максимум» с полем «Период» и таким образом запрос рассчитает максимальную дату (до нужной даты), на которую в регистре есть запись о курсе. Далее данный запрос соединяется с еще одним запросом к регистру «курсы валют» из которого, на полученную ранее дату, извлекается собственно курс и кратность нужной валюты.

Чтобы долго не писать проще показать -вот пример:

|ВЫБРАТЬ
|   Таб1.СсылкаДок,
|   Таб1.ДатаДок,
|   Таб1.ВалютаДок,
|   Таб2.Курс
|ИЗ
|   (ВЫБРАТЬ
|   ЗаказПокупателя.Ссылка КАК СсылкаДок,
|    ЗаказПокупателя.Дата КАК ДатаДок,
|    ЗаказПокупателя.ВалютаДокумента КАК ВалютаДок,
|    МАКСИМУМ(Валюты.Период) КАК ПериодДок
|   ИЗ
|    Документ.ЗаказПокупателя КАК ЗаказПокупателя
|    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК Валюты
|      ПО Валюты.Период

|      Валюты.Валюта = ЗаказПокупателя.ВалютаДокумента
|   СГРУППИРОВАТЬ ПО
|    ЗаказПокупателя.Ссылка) КАК Таб1
|    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК Таб2
|    ПО Таб1.ПериодДок = Таб2.Период И Таб1.ВалютаДок = Таб2.Валюта

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

В результирующей сводной таблице продаж, к которой я применил этот метод переоценки, у меня было около 100 000 записей. Для каждой этой записи нужно в этом же запросе выполнять переоценку, причем несколько раз. Данный метод работает так, что для получения курса, запрос выбирает все записи из регистра "курсы валют", до даты продажи или оплаты (из примера - до 01.01.2014, и еще раз до 02.01.2014). Таких записей у меня оказалось 730. Т.е в регистре курсы валют хранились записи за каждый рабочий день, начиная 01.01.2011, потому что в настройках пользователей указана, необходимость загружать курсы при входе в программу. И это типичная картина для большинства компаний, которые работают с валютой. А если учесть что, в некоторых случая, в один проход нужно делать две переоценки, уже получаем 1460 лишних записей, которые добавляются к каждой записи из таблицы продаж. Итого, для того что бы переоценить 100 000 записей запрос должен обработать 100 000 * 1460 = 146 000 000 записей. В итоге мой отчет просто перестал формироваться. Т.е. запрос выполнялся, но дождаться окончания я ни разу не смог, при чем, что один раз, я оставил формирование отчета на всю ночь, а на утро обнаружил, что 1С до сих пор о чем то думает. 

Сначала меня удивило, что не было переполнения памяти, но потом я понял, что эти 1460 записей не сохраняются в памяти постоянно, а выбираются порциями при каждом левом соединении, для расчета агрегатной функции "Максимум", а потом удаляются из памяти. Таким образом, в памяти постоянно находиться только 100 000 записей, а остальные загружаются и после использования удаляются. Но из-за того что это выполняется для каждой строки сводной таблицы продаж, производительность падает в сотни раз. По сути, происходит выполнение запроса внутри цикла при обходе записей другого запроса

Облом второй.

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

Суть метода заключается в следующем. В регистр сведений "КурсыВалют" необходимо добавить новый реквизит «СледующийПериод» тип значения дата. Именно реквизит, а не ресурс или измерение. После этого можно добавить новый общий модуль, например  «script_КурсыВалют» и подписку на событие «ПриЗаписи», регистра курсы валют. Дальше, в модуле общего модуля описать экспортную процедуру, которая будет отлавливать событие записи в регистр курсов, и заполнять новый реквизит «СледующийПериод». Другими словами, при вводе или загрузке нового курса на новую дату, программа будет дописывать в предыдущую запись, дату текущей записи. Т.е. каждая запись регистра будет содержать не только дату, но еще и дату следующей записи. Соответственно самая поздняя запись, в реквизите "СледующийПериод" будет содержать дату своей записи. 

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

Кому будет интересно пощупать, текст общего модуля лежит внизу, а вот пример использования:

|ВЫБРАТЬ
|   ПродажиСебестоимость.Номенклатура КАК Номенклатура,
|   ПродажиСебестоимость.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
|   ПродажиСебестоимость.ЗаказПокупателя КАК ЗаказПокупателя,
|   ВЫБОР
|       КОГДА ПродажиСебестоимость.ДокументДвижения <> НЕОПРЕДЕЛЕНО
|           ТОГДА ПродажиСебестоимость.ДокументДвижения
|       ИНАЧЕ ПродажиСебестоимость.Регистратор
|   КОНЕЦ КАК Регистратор,
|   ВЫБОР
|       КОГДА &ВалютаОтчета = &ВалютаУпр
|           ТОГДА ПродажиСебестоимость.Стоимость
|       ИНАЧЕ ПродажиСебестоимость.Стоимость * КурсыВалютУпр.Курс * КурсыВалютОтчета.Кратность / (КурсыВалютОтчета.Курс * КурсыВалютУпр.Кратность)
|   КОНЕЦ КАК СтоимостьОборот,
|   ВЫБОР
|       КОГДА &ВалютаОтчета = &ВалютаУпр
|           ТОГДА ПродажиСебестоимость.Стоимость
|       ИНАЧЕ ПродажиСебестоимость.НДС * КурсыВалютУпр.Курс * КурсыВалютОтчета.Кратность / (КурсыВалютОтчета.Курс * КурсыВалютУпр.Кратность)
|   КОНЕЦ КАК НДСОборот
|ИЗ
|   РегистрНакопления.ПродажиСебестоимость КАК ПродажиСебестоимость
|       ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК КурсыВалютОтчета
|       ПО ПродажиСебестоимость.ДокументОприходования.Дата >= КурсыВалютОтчета.Период
|           И ПродажиСебестоимость.ДокументОприходования.Дата < КурсыВалютОтчета.СледующийПериод
|           И (&ВалютаОтчета = КурсыВалютОтчета.Валюта)
|       ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК КурсыВалютУпр
|       ПО (&ВалютаУпр = КурсыВалютУпр.Валюта)
|           И ПродажиСебестоимость.ДокументОприходования.Дата >= КурсыВалютУпр.Период
|           И ПродажиСебестоимость.ДокументОприходования.Дата < КурсыВалютУпр.СледующийПериод
|ГДЕ
|   ПродажиСебестоимость.Период МЕЖДУ &НачПериода И &КонПериода
|
|СГРУППИРОВАТЬ ПО
|   ПродажиСебестоимость.Номенклатура,
|   ПродажиСебестоимость.ХарактеристикаНоменклатуры,
|   ПродажиСебестоимость.ЗаказПокупателя,
|   ВЫБОР
|       КОГДА ПродажиСебестоимость.ДокументДвижения <> НЕОПРЕДЕЛЕНО
|           ТОГДА ПродажиСебестоимость.ДокументДвижения
|       ИНАЧЕ ПродажиСебестоимость.Регистратор
|   КОНЕЦ,
|   ВЫБОР
|       КОГДА &ВалютаОтчета = &ВалютаУпр
|           ТОГДА ПродажиСебестоимость.Стоимость
|       ИНАЧЕ ПродажиСебестоимость.Стоимость * КурсыВалютУпр.Курс * КурсыВалютОтчета.Кратность / (КурсыВалютОтчета.Курс * КурсыВалютУпр.Кратность)
|   КОНЕЦ,
|   ВЫБОР
|       КОГДА &ВалютаОтчета = &ВалютаУпр
|           ТОГДА ПродажиСебестоимость.Стоимость
|       ИНАЧЕ ПродажиСебестоимость.НДС * КурсыВалютУпр.Курс * КурсыВалютОтчета.Кратность / (КурсыВалютОтчета.Курс * КурсыВалютУпр.Кратность)
|   КОНЕЦ"

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

Золотая середина.

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

Запрос, который формировал сводную таблицу, а потом перерос в СКД, я вообще разделил на два отдельных. Отдельно СКД с запросом к регистру  "Продажи" и отдельно СКД с запросом к регистру "Продажи себестоимость".  Это позволило вообще не париться с отборами. В форме настройки отчета присутствует отбор, который связан с компоновщиком настроек, которые просто копируются во все СКД.  

В результате выполнения обеих СКД формируются две таблицы значений: "Продажи" и "Себестоимость". 

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

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

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

Дальше обычным запросом выбираем оплаты из регистра ВзаиморасчетыСКонтрагентами и выгружаем их в таблицу значений «Оплаты».

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

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

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

Дата Хоз. операция Сумма Валюта
10.01.2014 продажа 20 000.00 руб.
11.01.2014 оплата 1 15 000.00 руб.
12.01.2014 оплата 2   5 000.00 руб.

 

Имеем две оплаты, которые вместе, полностью погашают продажу. 

То, что алгоритм распределяет эти оплаты на отгрузку по методу FIFI, я думаю и так понято, поэтому на этом моменте я останавливаться не буду. Только отмечу, что алгоритм выполнит переоценку суммы продажи частями. Одна часть на 15 000 переоценится по курсу на дату 11.01.2014, вторая часть на 5 000 по курсу на дату 12.01.2014. Но это еще не все, дальше интереснее.  

Основная суть заключается в том, что отчет формируется до номенклатуры. А как распределить частичную оплату на номенклатуру? Какая номенклатура в этом случае оплачена, а какая нет?

Так вот алгоритм считает, что вся номенклатура оплачена, но не на все количество. В процессе вычислений алгоритм рассчитывает коэффициент. Это отношение суммы платежа, к сумме продажи (15 000 / 20 000 = 0,75 и 5 000 / 20 000 = 0,25 соответственно). Получается, что программа будет знать, что накладная оплачена двумя платежами на 75% и 25%. Дальше алгоритм перемножит каждую продажу (сумма количество, себестоимость) на каждый коэффициент (0,75 и 0,25). Каждый из полученных результатов будет пересчитан в валюту отчета по своему курсу, и только после этого вся сводная таблица будет помещена в СКД, где разложенные строки свернутся по, выбранным пользователем, группировкам.

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

На разработку потрачено 6 рабочих дней или 50 часов

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

 

P. S.

На третий день разработки у меня был комичный случай. Вечером второго дня я лег спать около полуночи, сразу после окончания одного из вариантов этого отчета с чувством полной моральной удовлетворенности. Ночью мне приснился сон, в котором я показываю этот отчет пользователю. Пользователь формирует отчет по контрагенту JBS, взаиморасчеты с которым ведутся в USD, и находит, что сумма продажи рассчитывается не правильно. Тогда мы с пользователем выписываем все исходные данные на бумагу и находим ошибку в алгоритме переоценки, которую я описал выше в примере. Проснулся я в 6 утра, в состоянии головняка и сразу двинулся к компьютеру. Запустил 1С, сформировал отчет и увидел именно ту же ошибку, с теми же данными и у этого же контрагента, только причину я уже знал....

 

 

 

 

 

Скачать файлы

Наименование Файл Версия Размер
Текст общего модуля

.txt 9,21Kb
20.05.14
29
.txt 1 9,21Kb 29 Скачать

Специальные предложения

Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. krava_vlad 130 21.05.14 02:45 Сейчас в теме
недавно делал что то подобное.

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

Если заказ на 10 000
отгрузка на 6 000
Оплата на 4 000
Валовая прибыль по отгрузке 1 500

то есть премия начисляется от 1000 грн.

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

А как ваш отчет посчитает прибыль если будут такие условия
Если заказ на 10 000
отгрузка на 6 000
Оплата на 8 000
Валовая прибыль по отгрузке 1 500


2. script 226 21.05.14 03:37 Сейчас в теме
Отчет выводит только полностью оплаченные отгрузки. Продажи проверяются за период отчета, оплата проверяется за весь период (без ограничений)
Сумма заказа не учитывается, но сам заказ участвует в распределении оплаты по отгрузкам.
Если было продано на 10 000, а возвращено на 2 000, тогда программа посчитает что продано на 8 000.
Если отчет обнаружит оплату по данному контрагенту + договору + заказу, на 8000 и более, эти данные будут отображены в отчете, иначе - нет.
Кроме того отчет не расчитывает прибыль по какому то своему алгоритму. Принцып полностью идентичен отчету Валовая прибыль.
Считайте что это отчет валовая прибыль, из которого убрали те продажи, которые не были полностью оплаченными.

В вашем примере оплата больше чем отгрузка, значит данные попадут в отчет. А прибыль расчитается как сумма продажи - себестоимость.
Суть в том что если вы будете делать отчет в валюте, тогда сумма продажи пересчитается по курсу на дату оплаты, а себестоимость на дату партии.
3. gull22 87 21.05.14 12:53 Сейчас в теме
4. ildarovich 7143 21.05.14 14:04 Сейчас в теме
Задача интересная, комплексная. И распределение оплаты по FIFO и интерполяция курсов валюты. И решение, на мой взгляд, хорошее, практичное. Без вкусовщины. Что-то циклом, что-то запросом, что-то в СКД. Так на самом деле и нужно на практике. Ну а в теории комбинаций вариантов много и для предельного ускорения еще не все перепробованы.
Немного оказалось в кучу все перемешано, но тут, чтобы все по полочкам разложить еще столько же времени, наверное, понадобится.

Если обсуждать отдельно переоценку, то хочу спросить: а не файловая ли база была, когда решения не дождались? В SQL такого, кажется, быть не должно. По своей сути эта задача вроде бы не затратная по времени. Кроме того, этой проблемы бы не было вообще, если бы сначала построить и проиндексировать таблицу курсов валют на все возможные даты заданного диапазона. В худшем случае (без использования индекса по периоду для поиска даты актуального курса) должна быть примерно 730х730/2 трудоемкость. Это существенно меньше, чем 100000х730/2.

Метод распределения оплаченности по номенклатуре нравится. Более того, я предлагаю такой же метод применять для распределения оплаты между документами и если их время совпадает (ссылка).
6. script 226 22.05.14 00:29 Сейчас в теме
(4) ildarovich,

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

База файловая = 4 ГБ. Перед формированием отчета выполнялся перезапуск приложения.
Итоги при формировании отчета за один квартал:
- переоценка в запросе с индексированием = 59 сек.
- переоценка в цикле при обходе результата запроса = 60 сек.
Итоги при формировании отчета за один год:
- переоценка в запросе с индексированием = 6 мин. 35 сек.
- переоценка в цикле при обходе результата запроса = 4 мин 25 сек.
Получили замедление при использовании переоценки в запросе с индексированием ВТ.
Можно добавить в статью как третий облом
7. ildarovich 7143 22.05.14 03:20 Сейчас в теме
(6) Там что-то еще вмешивается. Не может (кажется) построение таблицы валют на каждую дату за два года с индексированием и затем обращение к этой таблице по индексу период-валюта для поиска значения курса отнимать две с лишним минуты. Приведите, пожалуйста, фрагмент запроса построения таблицы курсов валют. Возможно, вы не уловили идею. Сколько он в консоли выполняется?
5. DAnry 7 21.05.14 20:36 Сейчас в теме
Делал похожий отчет (правда без переоценки). Дополнительно рассчитывалось кимисионное вознаграждение менеджера, как процент от валовой прибыли (каждый менеджер имел свой процент вознаграждения). Результат еще группировался по менеджерам. В моем варианте надо было учитывать и частично оплаченные продажи. Делал следующим образом рассчитывал коэффициент оплаты документа продажи, полную валовую прибыль от продажи, после этого валовую прибыль по оплате - умножением полной валовой прибыли от продажи на коэффициент оплаты. Да, в отчете учитывались возвраты от покупателей и бартерные сделки (взаимозачет между договорами поставки и продажи).
8. script 226 22.05.14 09:58 Сейчас в теме
Запрос.Текст = "ВЫБРАТЬ
	|	КурсыВалют.Период КАК Период,
	|	КурсыВалют.Валюта КАК Валюта,
	|	КурсыВалют.Курс,
	|	КурсыВалют.Кратность
	|ПОМЕСТИТЬ КурсыВалют
	|ИЗ
	|	РегистрСведений.КурсыВалют КАК КурсыВалют
	|
	|ИНДЕКСИРОВАТЬ ПО
	|	Период,
	|	Валюта
	|;
	|
	|////////////////////////////////////////////////////////////­////////////////////
	|ВЫБРАТЬ
	|	КурсыВалют.Период КАК НачалоПериода,
	|	МИНИМУМ(ЕСТЬNULL(КурсыВалютКопия.Период, ДАТАВРЕМЯ(3999, 1, 1))) КАК КонецПериода,
	|	КурсыВалют.Валюта КАК Валюта,
	|	КурсыВалют.Курс,
	|	КурсыВалют.Кратность
	|ПОМЕСТИТЬ ТаблицаКурсов
	|ИЗ
	|	КурсыВалют КАК КурсыВалют
	|		ЛЕВОЕ СОЕДИНЕНИЕ КурсыВалют КАК КурсыВалютКопия
	|		ПО (КурсыВалютКопия.Период > КурсыВалют.Период)
	|			И (КурсыВалютКопия.Валюта = КурсыВалют.Валюта)
	|
	|СГРУППИРОВАТЬ ПО
	|	КурсыВалют.Период,
	|	КурсыВалют.Валюта,
	|	КурсыВалют.Курс,
	|	КурсыВалют.Кратность
	|
	|ИНДЕКСИРОВАТЬ ПО
	|	НачалоПериода,
	|	КонецПериода,
	|	Валюта
	|;
	|
	|////////////////////////////////////////////////////////////­////////////////////
Показать
9. script 226 22.05.14 10:02 Сейчас в теме
Вот так использую. Пробовал и через ВНУТРЕННЕЕ СОЕДИНЕНИЕ, особенной разницы не заметил.
	|			РегистрНакопления.ПродажиСебестоимость КАК ПродажиСебестоимость
	|				ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаКурсов КАК КурсыВалютУпр
	|				ПО (КурсыВалютУпр.Валюта = &ВалютаУпр)
	|					И (КурсыВалютУпр.НачалоПериода <= ПродажиСебестоимость.ДокументОприходования.Дата)
	|					И (КурсыВалютУпр.КонецПериода > ПродажиСебестоимость.ДокументОприходования.Дата)
	|				ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаКурсов КАК КурсыВалютОтчета
	|				ПО (КурсыВалютОтчета.Валюта = &ВалютаОтчета)
	|					И (КурсыВалютОтчета.НачалоПериода <= ПродажиСебестоимость.ДокументОприходования.Дата)
	|					И (КурсыВалютОтчета.КонецПериода > ПродажиСебестоимость.ДокументОприходования.Дата)
Показать
10. script 226 22.05.14 10:06 Сейчас в теме
Разницу, которуя описал это разница выполнения всего отчета, просто остальной алгортм не изменяется - изменяется только способ получения продаж. Запросом с переоценкой или двумя разными СКД, выгрузкой в ТЗ и переоценкой в цикле.

В отчете присутствует функция "ПолучитьТаблицуПродаж" - возвращает таблицу значений сформированную по регистрам: "продажи" и "продажи себестоимость" (запрос такой же как в отчете валовая прибыль, но без рассчета рентабельности эффективности и самой валовой прибыли). Внутри процедуры нужно выполнить переоценку сумм из валюты упр. учета в валюту отчета с условиями.
Сумма продажи переоценивается из валюты упр. учета в валюту взаиморасчетов по договору на дату продажи. Себестоимость пересчитывается из валюты. упр. учета в валюту отчета на дату документа оприходования.

Вариант 1: все сделано в одном запросе с индексированной таблицей. Пример постом выше.
Результат (Левое соединение) 2 мин. 08 сек.
Результат (Внутр соединение) 2 мин. 60 сек.

Вариант 2: Отдельно работает СКД с таблицей регистра "ПродажиОбороты". Отдельно - с таблицей регистра "Продажи себестоимость". Далее результаты обеих СКД выгружаются в таблицы значений. Далее обычный цикл и переоценка. Далее, таблицы помещаются в МВТ и объединяются запросом и опаять выгружаются в ТЗ.
Результат 1 мин. 15 сек.

Удивительное рядом...
11. script 226 22.05.14 11:15 Сейчас в теме
Весь текст запроса, который формирует переоцененную таблицу продаж. (Можно закинуть в консоль отчетов)
ВЫБРАТЬ
	КурсыВалют.Период КАК Период,
	КурсыВалют.Валюта КАК Валюта,
	КурсыВалют.Курс,
	КурсыВалют.Кратность
ПОМЕСТИТЬ КурсыВалют
ИЗ
	РегистрСведений.КурсыВалют КАК КурсыВалют

ИНДЕКСИРОВАТЬ ПО
	Период,
	Валюта
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	КурсыВалют.Период КАК НачалоПериода,
	МИНИМУМ(ЕСТЬNULL(КурсыВалютКопия.Период, ДАТАВРЕМЯ(3999, 1, 1))) КАК КонецПериода,
	КурсыВалют.Валюта КАК Валюта,
	КурсыВалют.Курс,
	КурсыВалют.Кратность
ПОМЕСТИТЬ ТаблицаКурсов
ИЗ
	КурсыВалют КАК КурсыВалют
		ЛЕВОЕ СОЕДИНЕНИЕ КурсыВалют КАК КурсыВалютКопия
		ПО (КурсыВалютКопия.Период > КурсыВалют.Период)
			И (КурсыВалютКопия.Валюта = КурсыВалют.Валюта)

СГРУППИРОВАТЬ ПО
	КурсыВалют.Период,
	КурсыВалют.Валюта,
	КурсыВалют.Курс,
	КурсыВалют.Кратность

ИНДЕКСИРОВАТЬ ПО
	НачалоПериода,
	КонецПериода,
	Валюта
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	ПродажиСебестоимость.Номенклатура КАК Номенклатура,
	ПродажиСебестоимость.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
	ПродажиСебестоимость.ЗаказПокупателя КАК ЗаказПокупателя,
	ВЫБОР
		КОГДА ПродажиСебестоимость.ДокументДвижения <> НЕОПРЕДЕЛЕНО
			ТОГДА ПродажиСебестоимость.ДокументДвижения
		ИНАЧЕ ПродажиСебестоимость.Регистратор
	КОНЕЦ КАК Регистратор,
	ВЫБОР
		КОГДА &ВалютаОтчета = &ВалютаУпр
			ТОГДА ПродажиСебестоимость.Стоимость
		ИНАЧЕ ПродажиСебестоимость.Стоимость * КурсыВалютУпр.Курс * КурсыВалютОтчета.Кратность / (КурсыВалютОтчета.Курс * КурсыВалютУпр.Кратность)
	КОНЕЦ КАК СтоимостьОборот,
	ПродажиСебестоимость.ДокументОприходования.Дата КАК ДокументОприходованияДата,
	КурсыВалютОтчета.Валюта,
	КурсыВалютУпр.Валюта КАК Валюта1,
	КурсыВалютУпр.НачалоПериода,
	КурсыВалютУпр.КонецПериода,
	КурсыВалютОтчета.НачалоПериода КАК НачалоПериода1,
	КурсыВалютОтчета.КонецПериода КАК КонецПериода1
ПОМЕСТИТЬ ТаблицаРегистраПродажиСебестоимость
ИЗ
	РегистрНакопления.ПродажиСебестоимость КАК ПродажиСебестоимость
		ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаКурсов КАК КурсыВалютУпр
		ПО (КурсыВалютУпр.Валюта = &ВалютаУпр)
			И (КурсыВалютУпр.НачалоПериода <= ПродажиСебестоимость.ДокументОприходования.Дата)
			И (КурсыВалютУпр.КонецПериода > ПродажиСебестоимость.ДокументОприходования.Дата)
		ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаКурсов КАК КурсыВалютОтчета
		ПО (КурсыВалютОтчета.Валюта = &ВалютаОтчета)
			И (КурсыВалютОтчета.НачалоПериода <= ПродажиСебестоимость.ДокументОприходования.Дата)
			И (КурсыВалютОтчета.КонецПериода > ПродажиСебестоимость.ДокументОприходования.Дата)
ГДЕ
	ПродажиСебестоимость.Период МЕЖДУ &НачПериода И &КонПериода

СГРУППИРОВАТЬ ПО
	ПродажиСебестоимость.Номенклатура,
	ПродажиСебестоимость.ХарактеристикаНоменклатуры,
	ПродажиСебестоимость.ЗаказПокупателя,
	ВЫБОР
		КОГДА ПродажиСебестоимость.ДокументДвижения <> НЕОПРЕДЕЛЕНО
			ТОГДА ПродажиСебестоимость.ДокументДвижения
		ИНАЧЕ ПродажиСебестоимость.Регистратор
	КОНЕЦ,
	ВЫБОР
		КОГДА &ВалютаОтчета = &ВалютаУпр
			ТОГДА ПродажиСебестоимость.Стоимость
		ИНАЧЕ ПродажиСебестоимость.Стоимость * КурсыВалютУпр.Курс * КурсыВалютОтчета.Кратность / (КурсыВалютОтчета.Курс * КурсыВалютУпр.Кратность)
	КОНЕЦ,
	ПродажиСебестоимость.ДокументОприходования.Дата,
	КурсыВалютОтчета.Валюта,
	КурсыВалютУпр.Валюта,
	КурсыВалютУпр.НачалоПериода,
	КурсыВалютУпр.КонецПериода,
	КурсыВалютОтчета.НачалоПериода,
	КурсыВалютОтчета.КонецПериода

ИНДЕКСИРОВАТЬ ПО
	ДокументОприходованияДата,
	КурсыВалютОтчета.Валюта,
	КурсыВалютОтчета.НачалоПериода,
	КурсыВалютОтчета.КонецПериода,
	КурсыВалютУпр.НачалоПериода,
	КурсыВалютУпр.КонецПериода,
	КурсыВалютУпр.Валюта
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	ПродажиОбороты.Проект КАК Проект,
	ПродажиОбороты.Подразделение КАК Подразделение,
	ПродажиОбороты.Контрагент КАК Покупатель,
	ПродажиОбороты.ДоговорКонтрагента КАК ДоговорПокупателя,
	ПродажиОбороты.Номенклатура КАК Номенклатура,
	ПродажиОбороты.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
	ПродажиОбороты.ЗаказПокупателя КАК ЗаказПокупателя,
	ПродажиОбороты.Организация КАК Организация,
	ПродажиОбороты.Регистратор КАК Регистратор,
	ПродажиОбороты.Период КАК Период,
	ПродажиОбороты.КоличествоОборот КАК Количество,
	ПродажиОбороты.КоличествоОборот * ЕСТЬNULL(ПродажиОбороты.Номенклатура.ЕдиницаХраненияОстатков.Коэффициент, 1) / ЕСТЬNULL(ПродажиОбороты.Номенклатура.ЕдиницаДляОтчетов.Коэффициент, 1) КАК КоличествоЕдиницОтчетов,
	ПродажиОбороты.КоличествоОборот * ЕСТЬNULL(ПродажиОбороты.Номенклатура.ЕдиницаХраненияОстатков.Коэффициент, 1) КАК КоличествоБазовыхЕдиниц,
	ПродажиОбороты.СтоимостьОборот КАК Стоимость,
	ПродажиОбороты.НДСОборот КАК СтоимостьНДС,
	ПродажиОбороты.СтоимостьОборот + ПродажиОбороты.НДСОборот КАК СтоимостьСНДС,
	ПродажиОбороты.СтоимостьОборот + ПродажиОбороты.НДСОборот КАК СтоимостьВВалютеДоговора,
	ЕСТЬNULL(ТаблицаРегистраПродажиСебестоимость.СтоимостьОборот, 0) КАК Себестоимость
ПОМЕСТИТЬ ПродажиИСебестоимость
ИЗ
	РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, Регистратор, {(Организация).* КАК Организация, (Проект).* КАК Проект, (Подразделение).* КАК Подразделение, (Контрагент).* КАК Покупатель, (ДоговорКонтрагента).* КАК ДоговорПокупателя, (ЗаказПокупателя).* КАК ЗаказПокупателя}) КАК ПродажиОбороты
		ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаРегистраПродажиСебестоимость КАК ТаблицаРегистраПродажиСебестоимость
		ПО (ТаблицаРегистраПродажиСебестоимость.Номенклатура = ПродажиОбороты.Номенклатура)
			И (ТаблицаРегистраПродажиСебестоимость.ХарактеристикаНоменклатуры = ПродажиОбороты.ХарактеристикаНоменклатуры)
			И (ТаблицаРегистраПродажиСебестоимость.ЗаказПокупателя = ПродажиОбороты.ЗаказПокупателя)
			И (ТаблицаРегистраПродажиСебестоимость.Регистратор = ПродажиОбороты.Регистратор)

ИНДЕКСИРОВАТЬ ПО
	Номенклатура,
	ХарактеристикаНоменклатуры,
	ЗаказПокупателя,
	Регистратор
;

////////////////////////////////////////////////////////////­////////////////////
УНИЧТОЖИТЬ ТаблицаРегистраПродажиСебестоимость
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	ВложенныйЗапрос.Проект,
	ВложенныйЗапрос.Подразделение,
	ВложенныйЗапрос.Покупатель,
	ВложенныйЗапрос.ДоговорПокупателя КАК ДоговорПокупателя,
	ВложенныйЗапрос.Номенклатура,
	ВложенныйЗапрос.ХарактеристикаНоменклатуры,
	ВложенныйЗапрос.ЗаказПокупателя,
	ВложенныйЗапрос.Организация,
	ВложенныйЗапрос.Регистратор,
	ВложенныйЗапрос.Период КАК Период,
	СУММА(ВложенныйЗапрос.Количество) КАК Количество,
	СУММА(ВложенныйЗапрос.КоличествоЕдиницОтчетов) КАК КоличествоЕдиницОтчетов,
	СУММА(ВложенныйЗапрос.КоличествоБазовыхЕдиниц) КАК КоличествоБазовыхЕдиниц,
	СУММА(ВложенныйЗапрос.Стоимость) КАК Стоимость,
	СУММА(ВложенныйЗапрос.СтоимостьНДС) КАК СтоимостьНДС,
	СУММА(ВложенныйЗапрос.СтоимостьСНДС) КАК СтоимостьСНДС,
	СУММА(ВложенныйЗапрос.СтоимостьВВалютеДоговора * (КурсыВалютУпр.Курс * КурсыВалютВзаиморасчетов.Кратность) / (КурсыВалютВзаиморасчетов.Курс * КурсыВалютУпр.Кратность)) КАК СтоимостьВВалютеДоговора,
	СУММА(ВложенныйЗапрос.Себестоимость) КАК Себестоимость,
	НАЧАЛОПЕРИОДА(ВложенныйЗапрос.Период, ДЕНЬ) КАК ПериодДень,
	НАЧАЛОПЕРИОДА(ВложенныйЗапрос.Период, НЕДЕЛЯ) КАК ПериодНеделя,
	НАЧАЛОПЕРИОДА(ВложенныйЗапрос.Период, ДЕКАДА) КАК ПериодДекада,
	НАЧАЛОПЕРИОДА(ВложенныйЗапрос.Период, МЕСЯЦ) КАК ПериодМесяц,
	НАЧАЛОПЕРИОДА(ВложенныйЗапрос.Период, КВАРТАЛ) КАК ПериодКвартал,
	НАЧАЛОПЕРИОДА(ВложенныйЗапрос.Период, ПОЛУГОДИЕ) КАК ПериодПолугодие,
	НАЧАЛОПЕРИОДА(ВложенныйЗапрос.Период, ГОД) КАК ПериодГод
ПОМЕСТИТЬ ПродажиИСебестоимостьУровень2
ИЗ
	ПродажиИСебестоимость КАК ВложенныйЗапрос
		ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаКурсов КАК КурсыВалютВзаиморасчетов
		ПО ВложенныйЗапрос.ДоговорПокупателя.ВалютаВзаиморасчетов = КурсыВалютВзаиморасчетов.Валюта
			И (КурсыВалютВзаиморасчетов.НачалоПериода <= ВложенныйЗапрос.Период)
			И (КурсыВалютВзаиморасчетов.КонецПериода > ВложенныйЗапрос.Период)
		ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаКурсов КАК КурсыВалютУпр
		ПО (КурсыВалютУпр.Валюта = &ВалютаУпр)
			И (КурсыВалютУпр.НачалоПериода <= ВложенныйЗапрос.Период)
			И (КурсыВалютУпр.КонецПериода > ВложенныйЗапрос.Период)

СГРУППИРОВАТЬ ПО
	ВложенныйЗапрос.Проект,
	ВложенныйЗапрос.Подразделение,
	ВложенныйЗапрос.Покупатель,
	ВложенныйЗапрос.ДоговорПокупателя,
	ВложенныйЗапрос.Номенклатура,
	ВложенныйЗапрос.ХарактеристикаНоменклатуры,
	ВложенныйЗапрос.ЗаказПокупателя,
	ВложенныйЗапрос.Период,
	ВложенныйЗапрос.Организация,
	ВложенныйЗапрос.Регистратор

ИМЕЮЩИЕ
	(СУММА(ВложенныйЗапрос.Количество) <> 0
		ИЛИ СУММА(ВложенныйЗапрос.Стоимость) <> 0
		ИЛИ СУММА(ЕСТЬNULL(ВложенныйЗапрос.Себестоимость, 0)) <> 0)

ИНДЕКСИРОВАТЬ ПО
	Период,
	ДоговорПокупателя
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	ПродажиИСебестоимостьУровень2.Проект,
	ПродажиИСебестоимостьУровень2.Подразделение,
	ПродажиИСебестоимостьУровень2.Покупатель,
	ПродажиИСебестоимостьУровень2.ДоговорПокупателя,
	ПродажиИСебестоимостьУровень2.Номенклатура,
	ПродажиИСебестоимостьУровень2.ХарактеристикаНоменклатуры,
	ПродажиИСебестоимостьУровень2.ЗаказПокупателя,
	ПродажиИСебестоимостьУровень2.Организация,
	ПродажиИСебестоимостьУровень2.Регистратор,
	ПродажиИСебестоимостьУровень2.Период,
	ПродажиИСебестоимостьУровень2.Количество,
	ПродажиИСебестоимостьУровень2.КоличествоЕдиницОтчетов,
	ПродажиИСебестоимостьУровень2.КоличествоБазовыхЕдиниц,
	ПродажиИСебестоимостьУровень2.Стоимость,
	ПродажиИСебестоимостьУровень2.СтоимостьНДС,
	ПродажиИСебестоимостьУровень2.СтоимостьСНДС,
	ВЫРАЗИТЬ(ПродажиИСебестоимостьУровень2.СтоимостьВВалютеДоговора КАК ЧИСЛО(15, 2)) КАК СтоимостьВВалютеДоговора,
	ПродажиИСебестоимостьУровень2.Себестоимость,
	ПродажиИСебестоимостьУровень2.ПериодДень,
	ПродажиИСебестоимостьУровень2.ПериодНеделя,
	ПродажиИСебестоимостьУровень2.ПериодДекада,
	ПродажиИСебестоимостьУровень2.ПериодМесяц,
	ПродажиИСебестоимостьУровень2.ПериодКвартал,
	ПродажиИСебестоимостьУровень2.ПериодПолугодие,
	ПродажиИСебестоимостьУровень2.ПериодГод
ИЗ
	ПродажиИСебестоимостьУровень2 КАК ПродажиИСебестоимостьУровень2
Показать
12. ildarovich 7143 22.05.14 16:14 Сейчас в теме
(11) я имел ввиду другой метод, вот его примерная реализация на примере вашего запроса. Главное в том, чтобы для каждой нужной даты заранее посчитать курсы. Чтобы не использовать неравенство в соединении. Неравенство в соединении в файловой базе - это наверняка всегда поиск по всей таблице без помощи индексов.

ВЫБРАТЬ РАЗЛИЧНЫЕ
	ДниПродаж.Период
ПОМЕСТИТЬ ДниПродаж
ИЗ
	РегистрНакопления.ПродажиСебестоимость.Обороты(, , День, ) КАК ДниПродаж
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	ДниПродаж.Период,
	КурсыВалют.Валюта КАК Валюта,
	МАКСИМУМ(КурсыВалют.Период) КАК ПериодКурса
ПОМЕСТИТЬ ДниКурсовПродаж
ИЗ
	ДниПродаж КАК ДниПродаж
		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК КурсыВалют
		ПО (КурсыВалют.Период <= ДниПродаж.Период)

СГРУППИРОВАТЬ ПО
	ДниПродаж.Период,
	КурсыВалют.Валюта
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	ДниКурсовПродаж.Период,
	ДниКурсовПродаж.Валюта,
	ЕСТЬNULL(КурсыВалют.Курс, 0) КАК Курс,
	ЕСТЬNULL(КурсыВалют.Кратность, 1) КАК Кратность
ПОМЕСТИТЬ ТаблицаКурсов
ИЗ
	ДниКурсовПродаж КАК ДниКурсовПродаж
		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КурсыВалют КАК КурсыВалют
		ПО ДниКурсовПродаж.ПериодКурса = КурсыВалют.Период
ИНДЕКСИРОВАТЬ ПО
	Период,
	Валюта
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	ПродажиСебестоимость.Номенклатура КАК Номенклатура,
	ПродажиСебестоимость.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
	ПродажиСебестоимость.ЗаказПокупателя КАК ЗаказПокупателя,
	ВЫБОР
		КОГДА ПродажиСебестоимость.ДокументДвижения <> НЕОПРЕДЕЛЕНО
			ТОГДА ПродажиСебестоимость.ДокументДвижения
		ИНАЧЕ ПродажиСебестоимость.Регистратор
	КОНЕЦ КАК Регистратор,
	ВЫБОР
		КОГДА &ВалютаОтчета = &ВалютаУпр
			ТОГДА ПродажиСебестоимость.Стоимость
		ИНАЧЕ ПродажиСебестоимость.Стоимость * КурсыВалютУпр.Курс * КурсыВалютОтчета.Кратность / (КурсыВалютОтчета.Курс * КурсыВалютУпр.Кратность)
	КОНЕЦ КАК СтоимостьОборот,
	ПродажиСебестоимость.ДокументОприходования.Дата КАК ДокументОприходованияДата,
	КурсыВалютОтчета.Валюта,
	КурсыВалютУпр.Валюта КАК Валюта1,
	КурсыВалютУпр.Период,
	КурсыВалютОтчета.Период КАК Период1
ПОМЕСТИТЬ ТаблицаРегистраПродажиСебестоимость
ИЗ
	РегистрНакопления.ПродажиСебестоимость КАК ПродажиСебестоимость
		ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаКурсов КАК КурсыВалютУпр
		ПО (КурсыВалютУпр.Валюта = &ВалютаУпр)
			И (КурсыВалютУпр.Период = НАЧАЛОПЕРИОДА(ПродажиСебестоимость.ДокументОприходования.Дата, ДЕНЬ))
		ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаКурсов КАК КурсыВалютОтчета
		ПО (КурсыВалютОтчета.Валюта = &ВалютаОтчета)
			И (КурсыВалютОтчета.Период = НАЧАЛОПЕРИОДА(ПродажиСебестоимость.ДокументОприходования.Дата, ДЕНЬ))
ГДЕ
	ПродажиСебестоимость.Период МЕЖДУ &НачалоПериода И &КонецПериода

СГРУППИРОВАТЬ ПО
	ПродажиСебестоимость.Номенклатура,
	ПродажиСебестоимость.ХарактеристикаНоменклатуры,
	ПродажиСебестоимость.ЗаказПокупателя,
	ВЫБОР
		КОГДА ПродажиСебестоимость.ДокументДвижения <> НЕОПРЕДЕЛЕНО
			ТОГДА ПродажиСебестоимость.ДокументДвижения
		ИНАЧЕ ПродажиСебестоимость.Регистратор
	КОНЕЦ,
	ВЫБОР
		КОГДА &ВалютаОтчета = &ВалютаУпр
			ТОГДА ПродажиСебестоимость.Стоимость
		ИНАЧЕ ПродажиСебестоимость.Стоимость * КурсыВалютУпр.Курс * КурсыВалютОтчета.Кратность / (КурсыВалютОтчета.Курс * КурсыВалютУпр.Кратность)
	КОНЕЦ,
	ПродажиСебестоимость.ДокументОприходования.Дата,
	КурсыВалютОтчета.Валюта,
	КурсыВалютУпр.Валюта,
	КурсыВалютУпр.Период,
	КурсыВалютОтчета.Период

ИНДЕКСИРОВАТЬ ПО
	ДокументОприходованияДата,
	КурсыВалютОтчета.Валюта,
	КурсыВалютОтчета.Период,
	КурсыВалютУпр.Период,
	КурсыВалютУпр.Валюта
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	ПродажиОбороты.Проект КАК Проект,
	ПродажиОбороты.Подразделение КАК Подразделение,
	ПродажиОбороты.Контрагент КАК Покупатель,
	ПродажиОбороты.ДоговорКонтрагента КАК ДоговорПокупателя,
	ПродажиОбороты.Номенклатура КАК Номенклатура,
	ПродажиОбороты.ХарактеристикаНоменклатуры КАК ХарактеристикаНоменклатуры,
	ПродажиОбороты.ЗаказПокупателя КАК ЗаказПокупателя,
	ПродажиОбороты.Организация КАК Организация,
	ПродажиОбороты.Регистратор КАК Регистратор,
	ПродажиОбороты.Период КАК Период,
	ПродажиОбороты.КоличествоОборот КАК Количество,
	ПродажиОбороты.КоличествоОборот * ЕСТЬNULL(ПродажиОбороты.Номенклатура.ЕдиницаХраненияОстатков.Коэффициент, 1) / ЕСТЬNULL(ПродажиОбороты.Номенклатура.ЕдиницаДляОтчетов.Коэффициент, 1) КАК КоличествоЕдиницОтчетов,
	ПродажиОбороты.КоличествоОборот * ЕСТЬNULL(ПродажиОбороты.Номенклатура.ЕдиницаХраненияОстатков.Коэффициент, 1) КАК КоличествоБазовыхЕдиниц,
	ПродажиОбороты.СтоимостьОборот КАК Стоимость,
	ПродажиОбороты.НДСОборот КАК СтоимостьНДС,
	ПродажиОбороты.СтоимостьОборот + ПродажиОбороты.НДСОборот КАК СтоимостьСНДС,
	ПродажиОбороты.СтоимостьОборот + ПродажиОбороты.НДСОборот КАК СтоимостьВВалютеДоговора,
	ЕСТЬNULL(ТаблицаРегистраПродажиСебестоимость.СтоимостьОборот, 0) КАК Себестоимость
ПОМЕСТИТЬ ПродажиИСебестоимость
ИЗ
	РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода, Регистратор, {(Организация).* КАК Организация, (Проект).* КАК Проект, (Подразделение).* КАК Подразделение, (Контрагент).* КАК Покупатель, (ДоговорКонтрагента).* КАК ДоговорПокупателя, (ЗаказПокупателя).* КАК ЗаказПокупателя}) КАК ПродажиОбороты
		ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаРегистраПродажиСебестоимость КАК ТаблицаРегистраПродажиСебестоимость
		ПО (ТаблицаРегистраПродажиСебестоимость.Номенклатура = ПродажиОбороты.Номенклатура)
			И (ТаблицаРегистраПродажиСебестоимость.ХарактеристикаНоменклатуры = ПродажиОбороты.ХарактеристикаНоменклатуры)
			И (ТаблицаРегистраПродажиСебестоимость.ЗаказПокупателя = ПродажиОбороты.ЗаказПокупателя)
			И (ТаблицаРегистраПродажиСебестоимость.Регистратор = ПродажиОбороты.Регистратор)

ИНДЕКСИРОВАТЬ ПО
	Номенклатура,
	ХарактеристикаНоменклатуры,
	ЗаказПокупателя,
	Регистратор
;

////////////////////////////////////////////////////////////­////////////////////
УНИЧТОЖИТЬ ТаблицаРегистраПродажиСебестоимость
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	ВложенныйЗапрос.Проект,
	ВложенныйЗапрос.Подразделение,
	ВложенныйЗапрос.Покупатель,
	ВложенныйЗапрос.ДоговорПокупателя КАК ДоговорПокупателя,
	ВложенныйЗапрос.Номенклатура,
	ВложенныйЗапрос.ХарактеристикаНоменклатуры,
	ВложенныйЗапрос.ЗаказПокупателя,
	ВложенныйЗапрос.Организация,
	ВложенныйЗапрос.Регистратор,
	ВложенныйЗапрос.Период КАК Период,
	СУММА(ВложенныйЗапрос.Количество) КАК Количество,
	СУММА(ВложенныйЗапрос.КоличествоЕдиницОтчетов) КАК КоличествоЕдиницОтчетов,
	СУММА(ВложенныйЗапрос.КоличествоБазовыхЕдиниц) КАК КоличествоБазовыхЕдиниц,
	СУММА(ВложенныйЗапрос.Стоимость) КАК Стоимость,
	СУММА(ВложенныйЗапрос.СтоимостьНДС) КАК СтоимостьНДС,
	СУММА(ВложенныйЗапрос.СтоимостьСНДС) КАК СтоимостьСНДС,
	СУММА(ВложенныйЗапрос.СтоимостьВВалютеДоговора * (КурсыВалютУпр.Курс * КурсыВалютВзаиморасчетов.Кратность) / (КурсыВалютВзаиморасчетов.Курс * КурсыВалютУпр.Кратность)) КАК СтоимостьВВалютеДоговора,
	СУММА(ВложенныйЗапрос.Себестоимость) КАК Себестоимость,
	НАЧАЛОПЕРИОДА(ВложенныйЗапрос.Период, ДЕНЬ) КАК ПериодДень,
	НАЧАЛОПЕРИОДА(ВложенныйЗапрос.Период, НЕДЕЛЯ) КАК ПериодНеделя,
	НАЧАЛОПЕРИОДА(ВложенныйЗапрос.Период, ДЕКАДА) КАК ПериодДекада,
	НАЧАЛОПЕРИОДА(ВложенныйЗапрос.Период, МЕСЯЦ) КАК ПериодМесяц,
	НАЧАЛОПЕРИОДА(ВложенныйЗапрос.Период, КВАРТАЛ) КАК ПериодКвартал,
	НАЧАЛОПЕРИОДА(ВложенныйЗапрос.Период, ПОЛУГОДИЕ) КАК ПериодПолугодие,
	НАЧАЛОПЕРИОДА(ВложенныйЗапрос.Период, ГОД) КАК ПериодГод
ПОМЕСТИТЬ ПродажиИСебестоимостьУровень2
ИЗ
	ПродажиИСебестоимость КАК ВложенныйЗапрос
		ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаКурсов КАК КурсыВалютВзаиморасчетов
		ПО ВложенныйЗапрос.ДоговорПокупателя.ВалютаВзаиморасчетов = КурсыВалютВзаиморасчетов.Валюта
			И (КурсыВалютВзаиморасчетов.Период = НАЧАЛОПЕРИОДА(ВложенныйЗапрос.Период, ДЕНЬ))
		ЛЕВОЕ СОЕДИНЕНИЕ ТаблицаКурсов КАК КурсыВалютУпр
		ПО (КурсыВалютУпр.Валюта = &ВалютаУпр)
			И (КурсыВалютУпр.Период = НАЧАЛОПЕРИОДА(ВложенныйЗапрос.Период, ДЕНЬ))

СГРУППИРОВАТЬ ПО
	ВложенныйЗапрос.Проект,
	ВложенныйЗапрос.Подразделение,
	ВложенныйЗапрос.Покупатель,
	ВложенныйЗапрос.ДоговорПокупателя,
	ВложенныйЗапрос.Номенклатура,
	ВложенныйЗапрос.ХарактеристикаНоменклатуры,
	ВложенныйЗапрос.ЗаказПокупателя,
	ВложенныйЗапрос.Период,
	ВложенныйЗапрос.Организация,
	ВложенныйЗапрос.Регистратор

ИМЕЮЩИЕ
	(СУММА(ВложенныйЗапрос.Количество) <> 0
		ИЛИ СУММА(ВложенныйЗапрос.Стоимость) <> 0
		ИЛИ СУММА(ЕСТЬNULL(ВложенныйЗапрос.Себестоимость, 0)) <> 0)

ИНДЕКСИРОВАТЬ ПО
	Период,
	ДоговорПокупателя
;

////////////////////////////////////////////////////////////­////////////////////
ВЫБРАТЬ
	ПродажиИСебестоимостьУровень2.Проект,
	ПродажиИСебестоимостьУровень2.Подразделение,
	ПродажиИСебестоимостьУровень2.Покупатель,
	ПродажиИСебестоимостьУровень2.ДоговорПокупателя,
	ПродажиИСебестоимостьУровень2.Номенклатура,
	ПродажиИСебестоимостьУровень2.ХарактеристикаНоменклатуры,
	ПродажиИСебестоимостьУровень2.ЗаказПокупателя,
	ПродажиИСебестоимостьУровень2.Организация,
	ПродажиИСебестоимостьУровень2.Регистратор,
	ПродажиИСебестоимостьУровень2.Период,
	ПродажиИСебестоимостьУровень2.Количество,
	ПродажиИСебестоимостьУровень2.КоличествоЕдиницОтчетов,
	ПродажиИСебестоимостьУровень2.КоличествоБазовыхЕдиниц,
	ПродажиИСебестоимостьУровень2.Стоимость,
	ПродажиИСебестоимостьУровень2.СтоимостьНДС,
	ПродажиИСебестоимостьУровень2.СтоимостьСНДС,
	ВЫРАЗИТЬ(ПродажиИСебестоимостьУровень2.СтоимостьВВалютеДоговора КАК ЧИСЛО(15, 2)) КАК СтоимостьВВалютеДоговора,
	ПродажиИСебестоимостьУровень2.Себестоимость,
	ПродажиИСебестоимостьУровень2.ПериодДень,
	ПродажиИСебестоимостьУровень2.ПериодНеделя,
	ПродажиИСебестоимостьУровень2.ПериодДекада,
	ПродажиИСебестоимостьУровень2.ПериодМесяц,
	ПродажиИСебестоимостьУровень2.ПериодКвартал,
	ПродажиИСебестоимостьУровень2.ПериодПолугодие,
	ПродажиИСебестоимостьУровень2.ПериодГод
ИЗ
	ПродажиИСебестоимостьУровень2 КАК ПродажиИСебестоимостьУровень2
Показать


Отлаживать не стал, думаю, идея понятная. Если дальше оптимизировать именно эту часть, то нужно предварительно обсчитать во временной таблице не курсы двух валют на нужную дату, а коэффициент пересчета на эту дату, чтобы не делать двух соединений каждый раз. Нужно ограничить диапазон выборки дат в первом запросе, "различные" не нужны. Еще в нижней части запроса нужно бы разобраться (я подробно не вникал) - там индексирование может быть лишним.
13. script 226 23.05.14 20:56 Сейчас в теме
(12) ildarovich,
Правильно ли я понял?
Суть метода в том, что бы, сначала, подготовить таблицу в которой, заранее, собрать курсы да дату каждой продажи. А потом просто соединятся с ней левым соединением с условием таблицакурсов.период =продажа. период?

Получиться так, что таблица курсов будет иметь записи только за период продаж, а не за весь период до даты окончания отчета. Это хорошая идея - нужно пробовать. Спасибо.
14. itar59 87 25.06.14 16:29 Сейчас в теме
Хотелось бы уточнить -- валютный пересчет идет по какому курсу: на день оплаты? на день выписки счета? на момент отгрузки?
у нвс эти даты могут очень сильно (до полугода) отличаться
мы бы заказали внедрение, но этот аспект должен быть учтен.
18. script 226 25.06.14 18:06 Сейчас в теме
(14) itar59,
Пример:
01.01.2014 - оплата = 1000
01.02.2014 - отгрузка = 1500
10.03.2014 - оплата = 500.00

Действия отчета:
Если период в отчете будет установлен такой, в который попадает дата 10.03.2014. данные попадут в отчет
потому что именно в эту дату закрылась сделка.
Сумма отгрузки будет переоценена в валюту отчета следующим образом:
1500 будут разделены на две суммы 1000 и 500 соответственно.
1000 грн переоценится на дату 01.01.2014 г.
500 грн.переоценится на дату 10.03.2014 г.

Здесь нужно пояснить что в отчет выводится и номенклатура, по этому разделить отгрузку нужно до номенклатуры.
Но в оплатах нет данных какая номенклатура оплачена. Для этого применяется спец. прием.
Считается что каждый платеж оплачивает всю номенклатуру из накладной, но не на все количество.
Т.е. если в накладной будет одна строка с количеством = 1 шт. на сумму 1500.00, тогда программа составит соотношения по количеству платежей
500 :1500 = 0,33333333 = 500 * курс на (01.01.2014)
1000:1500 = 0,66666666 = 1000 * курс на (10.03.2014)
В дальнейшем количество (1 шт.) и сумма (1500.00) будет умножена на эти коэффициенты по порядку (по дате платежа), Полученный результат и будет означать какая часть накладной оплачена. Именно эта часть будет переоценена на дату платежа.

Себестоимость переоценится на дату партии. Если партий было несколько, тогда на дату каждой партии отдельно.
Остальные показатели - как обычно.

15. itar59 87 25.06.14 16:30 Сейчас в теме
да, и как насчет оплаты безналом от юр лица? в гривнах
16. itar59 87 25.06.14 16:33 Сейчас в теме
Попадут ли в отчет товары отгруженные РАНЕЕ отчетного периода, но оплаченные в текущем?
17. script 226 25.06.14 17:46 Сейчас в теме
В этот не попадут.
На этой неделе я создам новую публикацию, в которой выложу новый отчет, который решает именно эту задачу, а так же описпние, как продолжение истории из этой публикации.
23. itar59 87 08.07.14 18:20 Сейчас в теме
(17(17)
каковы перспективы доработаной версии?
19. script 226 25.06.14 18:18 Сейчас в теме
Как программ определяет когда сделка полностью закрылась.

1. В отчете указывается некоторый период (01.01.2014 - 10.03.2014)
2. На дату начала отчета (01.01.2014), порграмма получает сальдо по контрагенту, договору, сделке(если взаиморасчеы ведутся по заказам/счетам - иначе по пустой сделке). Данные выгружаются в таблицу.
3. Далее, для комбинации Контрагент\Договор\Сделка, программа получает все "Оплаты", по контрагентам, договорам и сделкам из таблицы в п.1. (за все периоды работы в программе по дату окончания отчета 10.03.2014) - это движения в рег. взаиморасчеты со знком "минус".
4. Для комбинации Контрагент\Договор\Заказ покупателя\Номенклатура\ .... программа получает все "Продажи" (за все периоды работы в программе по дату окончания отчета 10.03.2014) - это движения в регистре "Продажи", по тому же принципу.
Пункты 1-4 выполняются одним пакетны запросом и индексированием.
5. После получения данных об отгрузках и оплтах, порграмма выполняет погашение отгрузок оплатами по ФИФО.
6. Те даты, когда очередная отгрузка была полностью погашена очередной оплатой, программа запоминает как "ДатуЗакрытия"
7. Кроме погашения по ФИФО алгоритм выполняет переоценку сумм и заполняет итоговую таблицу, которая содержит полностью оплаченные продажи, а также дату когда эта продажа была полностью оплачена (колонка "Дата закрытия").
8. Итоговая таблица подается процессору СКД, в котором наложен фильтр на колонку "Дата закрытия", данные которого (фильтра) беруться из даты начала и окончания отчета.
20. itar59 87 26.06.14 12:15 Сейчас в теме
Спасибо за ясный подробный ответ.
в принципе мы готовы купить, когда появится вариант, о котором вы упоминали ранее..

как насчет оплаты безналом от юр лица? в гривнах
21. itar59 87 26.06.14 13:50 Сейчас в теме
- в регистр "Продажи себестоимость программа записывает себестоимость проданного товара, которая не пересчитывается, а берется, так сказать "готовой", в валюте упр. учета, из регистра учета партий. По сути задачи, данные в регистре "Продажи себестоимость" всегда переоценены в валюту упр. учета по курсу, на дату документа оприходования.

по существу (у нас товар импортный) мы будем иметь таможенную стоимость?
22. script 226 26.06.14 15:14 Сейчас в теме
(21) itar59,
КАК РАБОТАЕТ УТП, УТ, УПП.
Пример:
- Приход - 01.01.2014 - Товар1 - Прих. накл1 - 1шт. - 2000грн.
- Приход - 01.02.2014 - Товар1 - Прих. накл2 - 1шт - 200 EUR.
- Продажа 10.02.2014 - Товар1 - Расх. накл1 - 2шт. - 5000грн.
Валюта упр. учета установлена. USD.
// ПОКУПКА
При проведении прих. накл. в регистры Продажи и продажи себестоимость ничего не записывается.
но записывается в регистр Партиит товаров упр. учет.
- Приход - Прих. накл1 - товар1 - 1шт. = (2000грн / курс USD * кратность) на 01.01.2014 (дата прих1)
- Приход - Прих. накл2 - товар1 - 1шт. = (200EUR пересчитается по крос курсу в USD) на 01.02.2014 (дата прих2)
В итоге в регистре партии товаров в упр. учете будет содержаться информация о двух партиях товара1 в USD.
//ПРОДАЖА
При проведении расх. накл1, программа записывает в регистры:
1.Партии товаров(упр.): списание товаров будет произмедено по готовой, рассчитаной ранее USD стоимости.
- Расход - Прих. накл1 - товар1 - 1шт. = (2000грн / курс USD * кратность) на 01.01.2014
- Расход - Прих. накл2 - товар1 - 1шт. = (200EUR пересчитается по крос курсу в USD) на 01.02.2014
2.Продажи: Товар1 - 2шт. (5000грн. * курс USD / кратность) на дату продажи (10.02.2014)
3.Продажи себестоимость: здесь интереснее...
Программа просто скопирует, те движения, которые сделает расх.накл1 в регистре Партии товаров упр. учет. в п.1.

// КАК СРАБОТАЕТ МОЙ ОТЧЕТ ПРИ ОПРЕДЕЛЕНИИ СЕБЕСТОИМОСТИ, ЕСЛИ:
- валюта отчета = валюте упр. учета (USD).
В этом случае отчет ничего пересчитывать не будет, а возьмет готовые цыфры и только просумирует себестоимость 2шт.
- валюта отчета отличается от валюты упр. учета (напр. EUR)
В этом случает отчет пересчитает сумму каждой партии из валюты упр. учета USD в валюту отчета EUR по крос-курсу на дату партии. После этого полученные себестоимости так же суммируются.

Все это выполняется одним пакетным запросом с индексированием.
После выполнения запроса данные выгружаются в таюблицу значений "Таблица себестоимости".
После этого похожим образов формируется таблица "Продажи"
Далее две таблицы загружаются в МенеджерВременныхТаблиц и передаются в запрос, в которым таблицы себестоимости и продаж объединяются, аналогично тому, как это сделано в отчете "Валовая прибиль".
После выполнения такого запроса, данные из него выгружаются в таблицу значений "Сводная таблица", по которой и происходит погашение оплатами по методу ФИФО. По сути сводная таблица содержит все продажи и дальнейшая обработка, удаляет из нее записи о продажах, которые не оплачены. В итоге в "сводной таблице" остаются только оплаченные продажи, по тем контрагентам, по которым было сальдо на начало отчета, и по тем, по котовым были движения в периоде формирования отчета.
24. snorchik 01.02.19 13:44 Сейчас в теме
Здравствуйте ! А может кто-нибудь кинуть erf файл этого отчета?
Оставьте свое сообщение

См. также

Вам нравятся запросы в 1С? Промо

Практика программирования Разработка v8 v8::Запросы 1cv8.cf Абонемент ($m)

Речь не только о том, что простейший запрос с "легальным" оформлением растянется на пол-экрана, речь еще обо всем, что нужно написать "в нагрузку" к тексту запроса. Все эти "Новый Запрос", "УстановитьПараметр" и последующие пляски с обработкой результата... Пора с этим заканчивать!

1 стартмани

03.07.2019    21074    5    m-rv    88    

Интерактивная справка по объектам 1С (автономное расширение)

Практика программирования Работа с интерфейсом v8 ERP2 Абонемент ($m)

База знаний, подключаемая к объектам основной базы. Ведётся интерактивно, формируется в виде статей прямо в 1С (текст, картинки, таблицы, ссылки). Есть возможность прикрепления файлов, привязки к объектам 1С, возможности рейтинга и комментирования пользователями.

3 стартмани

29.09.2020    6478    30    sapervodichka    33    

Конвейер проверки качества кода

Инструментарий разработчика Практика программирования Математика и алгоритмы v8 1cv8.cf Абонемент ($m)

Jenkinsfile для выполнения проверки качества кода. Собирает информацию с АПК, EDT и BSL-LS. Сопоставляет ошибки с гит-репозиторием, выгруженным ГитКонвертором. Отправляет в Сонар.

3 стартмани

04.09.2019    25413    22    Stepa86    46    

Алгоритмы поиска пути в графе

Практика программирования Разработка v8 1cv8.cf Абонемент ($m)

Реализуем алгоритмы поиска пути в графе на платформе 1С 8.3, такие как алгоритм А*, поиск в ширину, жадный поиск, алгоритм Дейкстры и вконце волновой.

1 стартмани

09.07.2019    17885    11    RonX01    10    

ВСТАВИТЬ В Справочник.Номенклатура (Код, Наименование) ЗНАЧЕНИЯ ("001", "Новый товар") Промо

Практика программирования v8 v8::Запросы 1cv8.cf Абонемент ($m)

Вас не обманывают ваши глаза, это запрос на изменение данных! И это работает без прямого доступа к БД, регистрации и смс.

1 стартмани

01.06.2018    30813    86    m-rv    57    

Работа с публикациями "Инфостарт"

Практика программирования О сообществе WEB v8 УУ Абонемент ($m)

Работа с рублевыми публикациями на сайте "Инфостарт": ведение клиентов, заказов, обновление файлов публикации, рассылка обновлений.

1 стартмани

13.09.2018    22056    13    RocKeR_13    16    

HTTP Сервисы: Путь к своему сервису. Часть 3

Инструментарий разработчика Практика программирования v8 1cv8.cf Абонемент ($m)

Продолжение статьи «HTTP Сервисы: Путь к своему сервису. Часть 2». В предыдущих частях мы использовали только Get, в этой части поговорим о других методах и длительных операциях.

1 стартмани

27.08.2018    38510    56    dsdred    17    

Позиционирование в помещении с помощью нейросети по сигналу Wi-Fi. Интерактивная карта склада в 1С с показом позиции

Инструментарий разработчика Практика программирования v8 Абонемент ($m)

Данная публикация содержит в себе редактор и интерактивную карту склада или иного помещения, на которой в реальном времени отображается позиция устройства, координаты которого вычисляются по уровням сигнала нескольких роутеров Wi-Fi. В статье и приложенным к ней разработкам предлагаются инструменты и методика для реализации вычисления точной геопозиции внутри помещений с помощью нейронной сети. Конфигурация написана на релизе 1С:Предприятие 8.3.12.1412, клиентское приложение имеет минимальный уровень совместимости SDK -16.

5 стартмани

09.08.2018    28551    26    informa1555    26    

Заполняем по шаблону (по умолчанию) Промо

Практика программирования v8 v8::УФ 1cv8.cf Абонемент ($m)

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

1 стартмани

08.02.2018    28646    19    mvxyz    17    

Работа с данными выбора

Практика программирования Работа с интерфейсом v8 Россия Абонемент ($m)

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

1 стартмани

17.07.2018    48706    17    kalyaka    16    

Полезные примеры составления схемы компоновки данных #2

Практика программирования v8 v8::СКД 1cv8.cf Абонемент ($m)

Еще один набор примеров как решить частные задачи в СКД

1 стартмани

22.05.2018    31544    11    SITR-utyos    13    

Печатная форма, сделанная как расширение конфигурации для БП 3.0. Новые возможности БСП

Практика программирования Универсальные печатные формы v8 БП3.0 Абонемент ($m)

Печатные формы на внешних обработках скоро канут в лету. На смену им приходят ПФ, реализованные в виде расширений конфигурации. Не нашел на сайте примеров таких расширений. Привожу пример подобного расширения для БП 3.0.

1 стартмани

06.12.2017    27359    54    kwazi    6    

Нечеткий поиск одним запросом Промо

Практика программирования v8 1cv8.cf Абонемент ($m)

Использование механизма полнотекстового поиска в 1С не всегда оправдано, т.к. построение индекса и поддержание его в актуальном состоянии может значительно нагружать систему. Предлагаемая реализация нечеткого поиска методом N-грамм выполняется одним запросом, что позволяет производить поиск в любой таблице и не требует предварительного построения индекса.

1 стартмани

28.12.2015    28137    71    vasvl123    9    

Паузы при исполнении кода (Sleep для 1С)

Практика программирования v8 v8::УФ 1cv8.cf Абонемент ($m)

Решил проверить все найденные варианты паузы для 1С. В результате получилась обработка для тестирования и небольшая статья с итогом.

1 стартмани

28.11.2017    46740    12    swimdog    42    

Макет в СКД - пример всех возможных типовых вариантов

Практика программирования Инструментарий разработчика v8 v8::СКД 1cv8.cf Абонемент ($m)

Макет СКД: наглядное представление того, что, как и куда выводится при типовых настройках.

1 стартмани

09.11.2017    22216    76    freelancer    4    

Telegram-боты

Практика программирования v8 Абонемент ($m)

Описание теории, разбор архитектуры и пример реализации telegram-ботов. Сразу скажу, со структурированием изложения мало что могу поделать. :) редакция от 18.07.2018 Правки последней редакции выделены жирным.

1 стартмани

01.09.2017    33116    132    PLAstic    59    

1С: Предприятие + корпоративный чат, как наладить оперативные уведомления за 10 минут Промо

Практика программирования v8 Абонемент ($m)

Как сделать автоматические уведомления о разных событиях из 1С в корпоративный чат MyChat для сотрудников компании

1 стартмани

14.08.2016    48501    36    Demanoidos    60    

Умный дом на 1С + ардуино

Практика программирования v8 Абонемент ($m)

Конфигурация для автоматизации быта программиста 1C и не только. В данной статье будет рассказано, как можно использовать 1С для задач, не входящих в стандартные рамки этой платформы. Например, управление домом. В качестве периферии для подключения будет использован микроконтроллер (МК) Ардуино, но на нём не будет никакой логической нагрузки, весь процесс будет проходить на сервере 1С. Работа с пинами ввода/вывода происходит напрямую из 1С.

1 стартмани

07.08.2017    23104    21    sasha777666    63    

Расширения конфигураций 1С: учимся перехватывать методы

Практика программирования v8 v8::УФ 1cv8.cf Абонемент ($m)

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

1 стартмани

30.05.2017    131965    13    signum2009    48    

Регулярные выражения – это просто. Построитель и отладчик регулярных выражений

Инструментарий разработчика Практика программирования v8 1cv8.cf Абонемент ($m)

Предлагается к использованию построитель регулярных выражений. Выполненный в виде внешней обработки, он позволит строить сложно-структурированные выражения на основе параметрического описания, тестировать их, и в результате получить программный код 1С.

1 стартмани

13.03.2017    31834    113    romasna    49    

Быстрое определение интервалов в запросе Промо

Практика программирования v8 Абонемент ($m)

В статье описывается новый метод определения интервалов между данными различных записей в запросе. В отличие от общеизвестного метода, время работы предлагаемого метода зависит от объема данных ЛИНЕЙНО. Это обеспечивает ему значительный выигрыш по быстродействию на больших объемах данных. В качестве иллюстрации возможностей метода приведен отчет, показывающий гистограмму распределения времени между продажами.

1 стартмани

01.10.2015    52055    35    ildarovich    41    

Распознавание текста с помощью нейросетей Google Cloud Vision и 1С

Практика программирования v8 1cv8.cf Абонемент ($m)

Возможности Google Cloud Vision в распознавании текста.

1 стартмани

08.02.2017    29716    127    kiv1c    18    

Графическая схема. Управление при помощи XDTO.

Практика программирования v8 Абонемент ($m)

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

2 стартмани

16.01.2017    22699    105    Alxby    23    

Простой редактор плана помещения JavaScript

Практика программирования Работа с интерфейсом v8 1cv8.cf Абонемент ($m)

На ресурсе сейчас очень много решений, которые позволяют редактировать карты, используя географические схемы. Так же много решений, которые позволяют редактировать объекты онлайн веб-карт. Мне же нужно было простое решение, для того чтобы расставить квадратные объекты на плане, показать их пользователю. Ну и распечатать, опять же. Я решил написать простенький редактор на JavaScript с использованием библиотеки Raphael.

1 стартмани

23.11.2016    21389    96    igel9780    22    

Хранение файлов в томах на диске (для УПП 1.3) Промо

Практика программирования v8 УПП1 Абонемент ($m)

Доработка типовой УПП 1.3 в плане хранения присоединенных файлов вне базы данных

2 стартмани

05.06.2016    58078    10    wowik    32    

Работа с двоичными данными на примере чтения файлов изображений. Новые возможности 8.3.9

Практика программирования WEB v8 1cv8.cf Россия Абонемент ($m)

В статье приводятся новые функции по работе с двоичными данными, появившимися в версии платформы 8.3.9 , на примере анализа формата и размера изображений. А также пример отправки изображения через API ВКонтакте с помощью новых объектов (без использования ОбъединитьФайлы())

1 стартмани

14.11.2016    26463    16    Anton64    22    

Загрузка файлов на сервер с прогрессом и докачкой

Практика программирования v8 1cv8.cf Россия Абонемент ($m)

Пример использования новых возможностей платформы 8.3.9 по низкоуровневой работе с двоичными данными для инкрементальной передачи файлов на сервер.

1 стартмани

04.10.2016    13553    53    mrstomak    21    

Несколько шаблонов для доработки типовых конфигураций

Практика программирования Инструментарий разработчика v8 v8::УФ Абонемент ($m)

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

1 стартмани

03.10.2016    36983    95    json    25    

HTTP-сервис: отчеты [Расширение]

Практика программирования Работа с интерфейсом v8 1cv8.cf Абонемент ($m)

Это HTTP-сервис, который возвращает почти любой отчет в HTML, XLSX или в JSON. Сохраните вариант отчета, получите на него ссылку и можно получить данные без захода в 1С. Работает в конфигурациях на основе БСП 2.3.3+, для отчетов на СКД и в 1С 8.3.8+

2 стартмани

30.08.2016    27184    137    Stepa86    15    

Недокументированное использование стандартных форм Upd.

Практика программирования v8 v8::УФ 1cv8.cf Абонемент ($m)

Вам не хватает возможностей в платформе 1С или у Вас нет времени на углубленное изучение платформы 1С? Рассмотрены возможности использования стандартных форм, вызываемых из платформы.

1 стартмани

26.07.2016    28606    77    ZhokhovM    60    

БСП 2.3 и БСП 3.0: Просто про выполнение внешней обработки в фоне (c индикацией прогресса выполнения)

Инструментарий разработчика Практика программирования БСП (Библиотека стандартных подсистем) v8 1cv8.cf Абонемент ($m)

Простое пояснение о том, как сделать внешнюю обработку с фоновым выполнением и индикацией процесса для любой конфигурации на основе БСП 2.3.2. UPDATE 20/09/19: добавлен вариант обработки с индикацией процента выполнения и статусом выполнения для БСП 3.0.

1 стартмани

18.05.2016    62446    184    rozer    65    

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

Практика программирования Учет ТМЦ Учет ТМЦ v8 1cv8.cf УУ Абонемент ($m)

Запрос формирует остатки товаров на каждый день в пределах выбранного периода.

1 стартмани

26.04.2016    59606    19    arakelyan    19    

Еще один способ расчета остатков на каждый день в запросе

Математика и алгоритмы Практика программирования v8 Абонемент ($m)

Предлагается новый способ расчета остатков на каждый день (час, минуту, секунду) в запросе. Способ не требует предварительного формирования таблицы дат и также подходит для расчета курсов валют, цен номенклатуры и других периодических сведений на каждую дату периода. На больших объемах данных предлагаемый способ может превосходить по быстродействию ранее известные методы из-за линейной (в лучшем случае) зависимости трудоемкости от длины периода.

1 стартмани

24.04.2016    34933    49    ildarovich    23    

Вывод печатных форм с запросом данных в форму "Печать документов" из подсистемы БСП "Печать".

Практика программирования БСП (Библиотека стандартных подсистем) v8 1cv8.cf Абонемент ($m)

Все не раз видели, как в типовых конфигурациях, построенных на основе БСП (Библиотека стандартных подсистем), печатные формы, построенные на основе Табличного документа, выводятся в специальную форму "ПечатьДокументов". Эта форма входит в состав подсистемы "Печать" из БСП. При разработке своих печатных форм, иногда необходимо запросить у пользователя дополнительные данные необходимые для печати. Тут встает вопрос, как в этом случае вывести печатную форму в форму "Печать документа". В этой статье я рассмотрю, как реализовать вывод печатной формы в упомянутую форму из подсистемы "Печать", в случае если мы хотим перед выводом печатной формы запросить у пользователя дополнительные данные. Здесь будут рассмотрены два случая: когда реализуется печатная форма с использованием подсистемы "Дополнительные отчеты и обработки" и когда печатная форма добавляется в конфигурацию в режиме конфигуратора, т.е. вносятся изменения в типовую конфигурацию.

1 стартмани

29.03.2016    91216    181    lopatin    14    

Выполнение JavaScript кода из 1С в объекте Поле HTML Документа (HTML 5) и вызов события в 1С ПриНажатии

Практика программирования v8 1cv8.cf Россия Абонемент ($m)

Пример выполнения JS кода из 1С в Поле HTML Документа под управляемыми формами, с удобным получением результата в 1С(С помощью вызова привязанного события ПриНажатии к элементу ПолеHTMLДокумента)

1 стартмани

22.03.2016    81951    160    igo1    54    

Количество дней недели (понедельников/вторников/...) в заданном диапазоне одним запросом

Практика программирования v8 Абонемент ($m)

При реализации периодического авто-заполнения маршрутных листов по графику (недельному) необходимо было просчитать стоимость всего периода, с условием выездов только по определенным дням. Заморачиваться с обходом результата не хотелось. Пришлось написать "Небольшой" запрос.

1 стартмани

03.03.2016    18530    1    Alexander.Shvets    5    

Простые радости жизни программиста 1С: выбор типа значения

Работа с интерфейсом Практика программирования v8 1cv8.cf Абонемент ($m)

Предлагаемая в работе обработка включает обычную и управляемую формы, которые максимально точно реализуют функциональность системного диалога выбора типа в толстом клиенте обычное приложение (включая оформление диалога). Эти формы имеют дополнительные интерфейсные удобства и могут быть использованы в качестве альтернативных диалогов выбора типа.

1 стартмани

17.02.2016    50521    53    yuraos    17    

Отображение прогресса выполнения длительных операций в БСП и их отладка в текущем сеансе.

Практика программирования БСП (Библиотека стандартных подсистем) v8 1cv8.cf Абонемент ($m)

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

1 стартмани

17.02.2016    55929    179    balanton    23    

Яндекс.Деньги "Благотворительность"

Инструментарий разработчика Практика программирования v8 1cv8.cf Абонемент ($m)

Яндекс.Деньги теперь в 1С. Форма для приема благотворительных взносов. Форму легко сделать и вставить на любую страницу сайта или блога. Платежи будут приходить на ваш кошелек. На форме есть три способа платежа: из кошелька, с банковской карты, с баланса мобильного.

1 стартмани

16.02.2016    23582    8    Tatitutu    5    

Мастер рассылки e-mail 2.2 для управляемых форм

Практика программирования Email v8 v8::УФ ERP2 БП3.0 УТ11 Абонемент ($m)

Для пользователей: переделанный из старый разработки под 8.2 с использованием библиотеки Мастер рассылки e-mail 2.2 (ERP, УТ, БП) (Только управляемые формы), который теперь может запускаться под любой версией платформы с разрешенными или запрещенными модальными/синхронными вызовами в конфигурации. Также удобный выбор e-mail и их владельцев с помощью отбора динамического списка по любым критериям и галочки исключения.

1 стартмани

29.12.2015    37276    20    milkers    4    

Передача больших пакетов через веб-сервисы

Практика программирования Администрирование данных 1С Внешние источники данных v8 Абонемент ($m)

Реализация механизма передачи больших пакетов через веб-сервисы. С его помощью передать файл размером в несколько гигабайт не составит проблем.

1 стартмани

06.12.2015    57475    48    YPermitin    19