Есть такие сущности как Группа, Сегмент, Вид номенклатуры. Типовыми средствами такой гибкости не достичь, поэтому ставим перед собой задачу модифицировать конфигурацию, чтобы настраивать распределение с учетом:
- ГРУППЫ
- СЕГМЕНТА
- ВИДА
Так выглядит типовая форма.
А вот так – после модификации:
Итак, последовательность шагов:
- Если конфигурация находится на поддержке, то для модификации нам надо включить возможность изменения, а также для регистра сведений «НастройкаРаспределенияПоНаправлениямДеятельности» и документа «РасчетСебестоимостиТоваров» выставить правило пользователя – «Объект редактируется с сохранением поддержки».
Так выглядит регистра сведений до изменений.
Добавляем в регистр необходимые нам измерения:
- ГруппаНоменкатуры – тип «Справочник.Номенклатура»
- СегментНоменклатуры – тип «Справочник.СегментыНоменклатуры»
- ВидНоменклатуры – тип «Справочник.ВидыНоменклатуры»
А также реквизит – ИспользуетсяРасширеннаяАналитика, тип «Булево»
Он позволит нам разделять штатные настройки от добавленых.
Настраиваем форму. Для этого я вывела на нее команду «Использовать расширенную аналитику» в виде гиперссылки – позволяющую при нажатии на нее скрывать группу «Расширенная аналитика», если все дополнительные поля пустые. Таким образом приводя ее в исходный вид.
прим. ПолеВида* - поле картинки "СтатусыПодключенияКомпонентыОбменаДанными";
При изменении любого из полей расширенной аналитики, делается проверка на корректность данных. Например, если мы выбрали определенный сегмент и указали номенклатуру, то она должна быть в составе этого сегмента. Или, при указанной номенклатуре мы добавляем вид номенклатуры, то у указанной номенклатуры реквизит "вид номенклатуры" должен быть таким же. В большинстве случаев поле Номенклатура не указывается вообще, поэтому проверка не производится.
Модуль формы изменился следующим образом:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если ТипЗнч(Запись.СпособРаспределения) = Тип("СправочникСсылка.НаправленияДеятельности") Тогда
ВариантУказанияНаправленияДеятельности = 0;
Иначе
ВариантУказанияНаправленияДеятельности = 1;
КонецЕсли;
УстановитьВидимостьПолей();
УстановитьПараметрыВыбораПартнера();
// --> модификация Mumla
УстановитьВидимостьПолейРасширеннойАналитики();
Элементы.ГруппаСегментаНоменклатуры.Видимость = ПолучитьФункциональнуюОпцию("ИспользоватьСегментыНоменклатуры");
ПроверитьПоУмолчанию();
КонецПроцедуры
// --> модификация Mumla
&НаКлиенте
Процедура ИспользоватьРасширенныйВид(Команда)
Скрыть = НЕ Элементы.РасширеннаяАналитика.Видимость;
УстановитьВидимостьПолейРасширеннойАналитики(Скрыть);
КонецПроцедуры
&НаСервере
Процедура УстановитьВидимостьПолейРасширеннойАналитики(Скрыть = Ложь)
ИспользуетсяРасширенная = ИспользуетсяРасширеннаяАналитика(запись);
Элементы.РасширеннаяАналитика.Видимость = Скрыть ИЛИ ИспользуетсяРасширенная;
КонецПроцедуры
&НаСервере
Процедура ПроверитьВидНоменклатуры()
ВидНоменклатуры = Запись.Номенклатура.ВидНоменклатуры;
Если ЗначениеЗаполнено(Запись.Номенклатура) И ЗначениеЗаполнено(Запись.ВидНоменклатуры) Тогда
ПолеВидаНоменклатуры = (Запись.ВидНоменклатуры = Запись.Номенклатура.ВидНоменклатуры);
Иначе
ПолеВидаНоменклатуры = Истина;
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПроверитьСегментНоменклатуры()
СегментНоменклатуры = Запись.СегментНоменклатуры;
Номенклатура = Запись.Номенклатура;
Если ЗначениеЗаполнено(Номенклатура) И ЗначениеЗаполнено(СегментНоменклатуры) Тогда
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ ПЕРВЫЕ 1
| 1 КАК Поле1
|ИЗ
| РегистрСведений.НоменклатураСегмента КАК НоменклатураСегмента
|ГДЕ
| НоменклатураСегмента.Сегмент = &Сегмент
| И НоменклатураСегмента.Номенклатура = &Номенклатура";
Запрос.УстановитьПараметр("Номенклатура", Номенклатура);
Запрос.УстановитьПараметр("Сегмент", СегментНоменклатуры);
Результат = Запрос.Выполнить();
ПолеСегментаНоменклатуры = НЕ Результат.Пустой();
Иначе
ПолеСегментаНоменклатуры = Истина;
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПроверитьГруппуНоменклатуры()
ГруппаНоменклатуры = Запись.ГруппаНоменклатуры;
Номенклатура = Запись.Номенклатура;
Если ЗначениеЗаполнено(Номенклатура) И ЗначениеЗаполнено(ГруппаНоменклатуры) Тогда
ПолеГруппыНоменклатуры = Номенклатура.ПринадлежитЭлементу(ГруппаНоменклатуры);
Иначе
ПолеГруппыНоменклатуры = Истина;
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПроверитьПоУмолчанию()
ПроверитьВидНоменклатуры();
ПроверитьСегментНоменклатуры();
ПроверитьГруппуНоменклатуры();
КонецПроцедуры
&НаКлиентеНаСервереБезКонтекста
Функция ИспользуетсяРасширеннаяАналитика(запись)
Возврат ЗначениеЗаполнено(запись.ВидНоменклатуры) ИЛИ
ЗначениеЗаполнено(запись.СегментНоменклатуры) ИЛИ
ЗначениеЗаполнено(запись.ГруппаНоменклатуры);
КонецФункции // ()
&НаКлиенте
Процедура ВидНоменклатурыПриИзменении(Элемент)
Запись.ИспользуетсяРасширеннаяАналитика = ИспользуетсяРасширеннаяАналитика(запись);
ПроверитьВидНоменклатуры();
КонецПроцедуры
&НаКлиенте
Процедура СегментНоменклатурыПриИзменении(Элемент)
Запись.ИспользуетсяРасширеннаяАналитика = ИспользуетсяРасширеннаяАналитика(запись);
ПроверитьСегментНоменклатуры();
КонецПроцедуры
&НаКлиенте
Процедура ГруппаНоменклатурыПриИзменении(Элемент)
Запись.ИспользуетсяРасширеннаяАналитика = ИспользуетсяРасширеннаяАналитика(запись);
ПроверитьГруппуНоменклатуры();
КонецПроцедуры
&НаКлиенте
Процедура НоменклатураПриИзменении(Элемент)
ПроверитьПоУмолчанию();
КонецПроцедуры
&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
Если не ПолеВидаНоменклатуры Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Данные поля не соответствует указаной номенклатуре";
Сообщение.Поле = "ПолеВидаНоменклатуры";
Сообщение.Сообщить();
отказ = истина;
КонецЕсли;
Если не ПолеСегментаНоменклатуры Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Данные поля не соответствует указаной номенклатуре";
Сообщение.Поле = "ПолеСегментаНоменклатуры";
Сообщение.Сообщить();
отказ = истина;
КонецЕсли;
Если не ПолеГруппыНоменклатуры Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Данные поля не соответствует указаной номенклатуре";
Сообщение.Поле = "ПолеГруппыНоменклатуры";
Сообщение.Сообщить();
отказ = истина;
КонецЕсли;
КонецПроцедуры
Итак форма записи регистра готова. Переходим к документу.
Нас будет интересовать процедура модуля объекта "РаспределитьВыручкуПоНаправлениямДеятельности".
Здесь нужно лишь изменить код запроса. Приведу его полностью:
"ВЫБРАТЬ
| НастройкаРаспределения.ИспользуетсяРасширеннаяАналитика,
| ТаблицаВыручки.Подразделение КАК Подразделение,
| ТаблицаВыручки.Организация КАК Организация,
| ТаблицаВыручки.Номенклатура КАК Номенклатура,
| ТаблицаВыручки.Партнер КАК Партнер,
| ТаблицаВыручки.СуммаВыручки КАК СуммаВыручки,
| ТаблицаВыручки.Себестоимость КАК Себестоимость,
| НастройкаРаспределения.СпособРаспределения КАК СпособРаспределения,
| ВЫБОР
| КОГДА ТаблицаВыручки.Партнер = НастройкаРаспределения.Партнер
| ТОГДА 1000000
| ИНАЧЕ 0
| КОНЕЦ + ВЫБОР
| КОГДА ТаблицаВыручки.Подразделение = НастройкаРаспределения.Подразделение
| ТОГДА 100000
| ИНАЧЕ 0
| КОНЕЦ + ВЫБОР
| КОГДА ТаблицаВыручки.Номенклатура = НастройкаРаспределения.Номенклатура
| ТОГДА 10000
| ИНАЧЕ 0
| КОНЕЦ + ВЫБОР
| КОГДА ТаблицаВыручки.Организация = НастройкаРаспределения.Организация
| ТОГДА 1
| ИНАЧЕ 0
| КОНЕЦ КАК Приоритет,
| НастройкаРаспределения.ГруппаНоменклатуры,
| НастройкаРаспределения.СегментНоменклатуры,
| НастройкаРаспределения.ВидНоменклатуры
|ПОМЕСТИТЬ ВтРасширенная
|ИЗ
| (ВЫБРАТЬ
| ВыручкаИСебестоимость.Подразделение КАК Подразделение,
| АналитикаПоПартнерам.Организация КАК Организация,
| АналитикаНоменклатуры.Номенклатура КАК Номенклатура,
| АналитикаПоПартнерам.Партнер КАК Партнер,
| СУММА(ВыручкаИСебестоимость.СуммаВыручкиОборот) КАК СуммаВыручки,
| СУММА(ВыручкаИСебестоимость.СебестоимостьОборот) + СУММА(ВыручкаИСебестоимость.СуммаДополнительныхРасходовОборот) КАК Себестоимость
| ИЗ
| РегистрНакопления.ВыручкаИСебестоимостьПродаж.Обороты(
| &НачалоПериода,
| &КонецПериода,
| ,
| ТипЗапасов В (ЗНАЧЕНИЕ(Перечисление.ТипыЗапасов.Товар), ЗНАЧЕНИЕ(Перечисление.ТипыЗапасов.Услуга))
| И АналитикаУчетаПоПартнерам В
| (ВЫБРАТЬ
| АналитикаПартнерам.КлючАналитики
| ИЗ
| РегистрСведений.АналитикаУчетаПоПартнерам КАК АналитикаПартнерам
| ГДЕ
| АналитикаПартнерам.Организация В (&МассивОрганизаций))) КАК ВыручкаИСебестоимость
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.АналитикаУчетаНоменклатуры КАК АналитикаНоменклатуры
| ПО ВыручкаИСебестоимость.АналитикаУчетаНоменклатуры = АналитикаНоменклатуры.КлючАналитики
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.АналитикаУчетаПоПартнерам КАК АналитикаПоПартнерам
| ПО ВыручкаИСебестоимость.АналитикаУчетаПоПартнерам = АналитикаПоПартнерам.КлючАналитики
|
| СГРУППИРОВАТЬ ПО
| АналитикаПоПартнерам.Организация,
| ВыручкаИСебестоимость.Подразделение,
| АналитикаПоПартнерам.Партнер,
| АналитикаНоменклатуры.Номенклатура
|
| ИМЕЮЩИЕ
| (СУММА(ВыручкаИСебестоимость.СуммаВыручкиОборот) <> 0
| ИЛИ СУММА(ВыручкаИСебестоимость.СебестоимостьОборот) <> 0
| ИЛИ СУММА(ВыручкаИСебестоимость.СуммаДополнительныхРасходовОборот) <> 0)) КАК ТаблицаВыручки
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.НастройкаРаспределенияПоНаправлениямДеятельности.СрезПоследних(&КонецПериода, ) КАК НастройкаРаспределения
| ПО (НастройкаРаспределения.Используется)
| И (ТаблицаВыручки.Организация = НастройкаРаспределения.Организация
| ИЛИ НастройкаРаспределения.Организация = ЗНАЧЕНИЕ(Справочник.Организации.ПустаяСсылка))
| И (ТаблицаВыручки.Партнер = НастройкаРаспределения.Партнер
| ИЛИ НастройкаРаспределения.Партнер = ЗНАЧЕНИЕ(Справочник.Партнеры.ПустаяСсылка))
| И (ТаблицаВыручки.Подразделение = НастройкаРаспределения.Подразделение
| ИЛИ НастройкаРаспределения.Подразделение = ЗНАЧЕНИЕ(Справочник.СтруктураПредприятия.ПустаяСсылка))
| И (ТаблицаВыручки.Номенклатура = НастройкаРаспределения.Номенклатура
| ИЛИ НастройкаРаспределения.Номенклатура = ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка))
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| НоменклатураСегмента.Сегмент КАК Сегмент,
| НоменклатураСегмента.Номенклатура КАК Номенклатура
|ПОМЕСТИТЬ Сегменты
|ИЗ
| РегистрСведений.НоменклатураСегмента КАК НоменклатураСегмента
|ГДЕ
| НоменклатураСегмента.Сегмент В
| (ВЫБРАТЬ РАЗЛИЧНЫЕ
| ВтРасширенная.СегментНоменклатуры
| ИЗ
| ВтРасширенная КАК ВтРасширенная)
| И НоменклатураСегмента.Номенклатура В
| (ВЫБРАТЬ РАЗЛИЧНЫЕ
| ВтРасширенная.Номенклатура
| ИЗ
| ВтРасширенная КАК ВтРасширенная)
|
|ИНДЕКСИРОВАТЬ ПО
| Сегмент,
| Номенклатура
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВтРасширенная.ИспользуетсяРасширеннаяАналитика,
| ВтРасширенная.Подразделение,
| ВтРасширенная.Организация,
| ВтРасширенная.Номенклатура,
| ВтРасширенная.Партнер,
| ВтРасширенная.СуммаВыручки,
| ВтРасширенная.Себестоимость,
| МАКСИМУМ(ВтРасширенная.СпособРаспределения) КАК СпособРаспределения,
| ВЫБОР
| КОГДА ВтРасширенная.ИспользуетсяРасширеннаяАналитика
| ТОГДА ВЫБОР
| КОГДА ВтРасширенная.ВидНоменклатуры = ВтРасширенная.Номенклатура.ВидНоменклатуры
| ТОГДА 10
| ИНАЧЕ 0
| КОНЕЦ + ВЫБОР
| КОГДА Сегменты.Сегмент ЕСТЬ НЕ NULL
| ТОГДА 100
| ИНАЧЕ 0
| КОНЕЦ + ВЫБОР
| КОГДА ВтРасширенная.Номенклатура.Родитель = ВтРасширенная.ГруппаНоменклатуры
| И ВтРасширенная.Номенклатура.Родитель <> ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)
| ИЛИ ВтРасширенная.Номенклатура.Родитель.Родитель = ВтРасширенная.ГруппаНоменклатуры
| И ВтРасширенная.Номенклатура.Родитель.Родитель <> ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)
| ИЛИ ВтРасширенная.Номенклатура.Родитель.Родитель.Родитель = ВтРасширенная.ГруппаНоменклатуры
| И ВтРасширенная.Номенклатура.Родитель.Родитель.Родитель <> ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)
| ТОГДА 1000
| ИНАЧЕ 0
| КОНЕЦ + ВтРасширенная.Приоритет
| ИНАЧЕ ВтРасширенная.Приоритет
| КОНЕЦ КАК Приоритет,
| МАКСИМУМ(ВтРасширенная.ГруппаНоменклатуры) КАК ГруппаНоменклатуры,
| МАКСИМУМ(ВтРасширенная.СегментНоменклатуры) КАК СегментНоменклатуры,
| ВтРасширенная.ВидНоменклатуры
|ПОМЕСТИТЬ ВтТаблицаРаспределения
|ИЗ
| ВтРасширенная КАК ВтРасширенная
| ЛЕВОЕ СОЕДИНЕНИЕ Сегменты КАК Сегменты
| ПО ВтРасширенная.СегментНоменклатуры = Сегменты.Сегмент
| И ВтРасширенная.Номенклатура = Сегменты.Номенклатура
|
|СГРУППИРОВАТЬ ПО
| ВтРасширенная.ИспользуетсяРасширеннаяАналитика,
| ВтРасширенная.Подразделение,
| ВтРасширенная.Организация,
| ВтРасширенная.Номенклатура,
| ВтРасширенная.Партнер,
| ВтРасширенная.ВидНоменклатуры,
| ВтРасширенная.СуммаВыручки,
| ВтРасширенная.Себестоимость,
| ВЫБОР
| КОГДА ВтРасширенная.ИспользуетсяРасширеннаяАналитика
| ТОГДА ВЫБОР
| КОГДА ВтРасширенная.ВидНоменклатуры = ВтРасширенная.Номенклатура.ВидНоменклатуры
| ТОГДА 10
| ИНАЧЕ 0
| КОНЕЦ + ВЫБОР
| КОГДА Сегменты.Сегмент ЕСТЬ НЕ NULL
| ТОГДА 100
| ИНАЧЕ 0
| КОНЕЦ + ВЫБОР
| КОГДА ВтРасширенная.Номенклатура.Родитель = ВтРасширенная.ГруппаНоменклатуры
| И ВтРасширенная.Номенклатура.Родитель <> ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)
| ИЛИ ВтРасширенная.Номенклатура.Родитель.Родитель = ВтРасширенная.ГруппаНоменклатуры
| И ВтРасширенная.Номенклатура.Родитель.Родитель <> ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)
| ИЛИ ВтРасширенная.Номенклатура.Родитель.Родитель.Родитель = ВтРасширенная.ГруппаНоменклатуры
| И ВтРасширенная.Номенклатура.Родитель.Родитель.Родитель <> ЗНАЧЕНИЕ(Справочник.Номенклатура.ПустаяСсылка)
| ТОГДА 1000
| ИНАЧЕ 0
| КОНЕЦ + ВтРасширенная.Приоритет
| ИНАЧЕ ВтРасширенная.Приоритет
| КОНЕЦ
|
|ИНДЕКСИРОВАТЬ ПО
| ВтРасширенная.Номенклатура,
| ВтРасширенная.Партнер,
| ВтРасширенная.Подразделение,
| ВтРасширенная.Организация
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| &ПериодДвижений КАК Период,
| ТаблицаФинансовыхРезультатов.Организация КАК Организация,
| ТаблицаФинансовыхРезультатов.Подразделение КАК Подразделение,
| ТаблицаФинансовыхРезультатов.СпособРаспределения КАК СпособРаспределения,
| ТаблицаФинансовыхРезультатов.СуммаВыручки КАК СуммаВыручки,
| ТаблицаФинансовыхРезультатов.Себестоимость КАК Себестоимость,
| ЗНАЧЕНИЕ(ПланВидовХарактеристик.СтатьиДоходов.ВыручкаОтПродаж) КАК СтатьяДоходов,
| ЗНАЧЕНИЕ(ПланВидовХарактеристик.СтатьиРасходов.СебестоимостьПродаж) КАК СтатьяРасходов,
| ВЫБОР
| КОГДА ТаблицаФинансовыхРезультатов.СпособРаспределения ССЫЛКА Справочник.НаправленияДеятельности
| ТОГДА ТаблицаФинансовыхРезультатов.СпособРаспределения
| ИНАЧЕ СпособыРаспределения.НаправлениеДеятельности
| КОНЕЦ КАК НаправлениеДеятельности,
| ВЫБОР
| КОГДА ТаблицаФинансовыхРезультатов.СпособРаспределения ССЫЛКА Справочник.НаправленияДеятельности
| ТОГДА 1
| ИНАЧЕ ЕСТЬNULL(СпособыРаспределения.Коэффициент, 1)
| КОНЕЦ КАК КоэффициентРаспределения
|ИЗ
| (ВЫБРАТЬ
| ТаблицаРаспределения.Организация КАК Организация,
| ТаблицаРаспределения.Подразделение КАК Подразделение,
| СУММА(ТаблицаРаспределения.СуммаВыручки) КАК СуммаВыручки,
| СУММА(ТаблицаРаспределения.Себестоимость) КАК Себестоимость,
| ЕСТЬNULL(ТаблицаРаспределения.СпособРаспределения, НЕОПРЕДЕЛЕНО) КАК СпособРаспределения
| ИЗ
| ВтТаблицаРаспределения КАК ТаблицаРаспределения
| ГДЕ
| ТаблицаРаспределения.Приоритет В
| (ВЫБРАТЬ
| МАКСИМУМ(Таб.Приоритет) КАК Приоритет
| ИЗ
| ВтТаблицаРаспределения КАК Таб
| ГДЕ
| Таб.Номенклатура = ТаблицаРаспределения.Номенклатура
| И Таб.Подразделение = ТаблицаРаспределения.Подразделение
| И Таб.Организация = ТаблицаРаспределения.Организация
| И Таб.Партнер = ТаблицаРаспределения.Партнер)
|
| СГРУППИРОВАТЬ ПО
| ТаблицаРаспределения.Организация,
| ТаблицаРаспределения.Подразделение,
| ЕСТЬNULL(ТаблицаРаспределения.СпособРаспределения, НЕОПРЕДЕЛЕНО)) КАК ТаблицаФинансовыхРезультатов
| ЛЕВОЕ СОЕДИНЕНИЕ Справочник.СпособыРаспределенияПоНаправлениямДеятельности.НаправленияДеятельности КАК СпособыРаспределения
| ПО ТаблицаФинансовыхРезультатов.СпособРаспределения = СпособыРаспределения.Ссылка
|ИТОГИ
| МАКСИМУМ(СуммаВыручки),
| МАКСИМУМ(Себестоимость),
| СУММА(КоэффициентРаспределения)
|ПО
| Организация,
| Подразделение,
| СпособРаспределения".
Суть запроса в высталении приоритетов. Поскольку мы добавили в регистр дополнительно 3 измерения, настолько же нам надо и увеличить разрядность приоритета. Согласно этому приоритеты выстроятся:
- Партнер +1000000
- Подразделение +100000
- Номенклатура +10000
Далее новые в порядке убывания: Группа, Сегмент, Вид. И самый низкий приоритет - Организация.
Основные проблемы кода:
- учитывается органиченная иерархичность групп номенклатуры;
- и главная: позиция справочника номенклатура может принадлежать НЕСКОЛЬКИМ сегментам и ГРУППАМ одновременно. Поэтому если в регистре будет несколько записей с разными группами (вложенными, например) но с одинаковыми приоритетами... то данный алгоритм выберет какую либо одну запись. Здесь нужно быть внимательным и настраивать группы с учетом этой особенности.
Желаю успехов на внедрениях!
P.S. Огромное спасибо Евгению Гилеву и проекту http:// за вдохновление!!!