Идея по созданию обработки возникла после того, как клиент попросил разобраться с нулевой себестоимостью в отчете Оценка валовой прибыли.
Себестоимость номенклатуры в конфигурации Розница 2.0 (2.1) хранится в регистре сведений Себестоимость номенклатуры, регистраторами данного регистра являются следующие виды документов:
1) ВводНачальныхОстатковУзла
2) КорректировкаРегистров
3) ПоступлениеТоваров
4) УстановкаСебестоимости
Суть проблемы: Товар А поступает в Магазин А, через некоторое время по причине плохих продаж или ряда других причин Товар А перемещают в Магазин Б, при этом количество по регистрам остатков двигается верно, но себестоимость не передается из Магазина А в Магазин Б. В случае, если Товар А никогда ранее не поступал в Магазин Б (документом Поступление товаров, либо себестоимость не регистрировалась одниим из видов регистраторов указаных выше) себестоимость для данного товара будет равна нулю при формирования отчета Оценка валовой прибыли. Та же проблема возникает в случае инвентаризации, когда оприходуют товар.
Принцип работы обработки: Анализируются продажи на наличие нулевой себестоимости по алгоритму взятому из отчета Оценка валовой прибыли. Если найдена продажа по нулевой себестоимости, то ищется ближайший к ней документ поступления на другой магазин и в случае нахождения такового создаются документы Установка себестоимости и помещаются в начало дня документа продажи.
Обработка содержит 3 команды:
1) Установить себестоимость. Позволяет задать расписание выполнения команды. При выполнении данной команды анализ продаж формируется за текущий день. Важно! Если у вас типовая конфигурация и вы не желаете снимать ее с поддержки, то работать по расписанию внешнюю обработку заставить не удастся, до момента выхода обновления конфигурации. Возможно, в Розница 2.1 это исправлено. Если только программно создать регламентное задание...
2) Установить себестоимость (без открытия формы обработки). Команда может быть открыта пользователям для ручного запуска формирования себестоимости. При выполнении данной команды анализ продаж формируется за текущий день
3) Установить себестоимость (открыть форму обработки). Команда открывает форму обработки, где можно указать произвольный период анализа продаж.
Сделал я обработку, в интерактивном режиме все работает, но радоваться было рано. Пытаюсь настроить расписание работы. Сохраняю обработку, открываю ее, а расписание не сохраняется и соответственно регламентное задание не создается. Пришлось взять конфигурацию БСП версии 2.1.8.3 и вставлять из нее куски кода в бывшую когда-то типовой Розницу 2.0.8.12.
Повезло, что править пришлось только один общий модуль ДополнительныеОтчетыИОбработкиРегламентныеЗадания.
Процедуры, которые надо подправить:
1) НайтиЗадание
2) ПолучитьИдентификаторЗадания
3) ПолучитьПараметрыЗадания
4) СоздатьНовоеЗадание
5) УдалитьЗадание
6) УстановитьПараметрыЗадания
Так же подправил модуль формы элемента справочника ДополнительныеОтчетыИОбработки, что бы после сохранения обработки в колонке Расписания не пропадали данные (в конфигурации БСП 2.1.8.3 они пропадают), но если форму переоткрыть, все становится на свои места. Меня это напрягало и я в конец процедуры ПослеЗаписиНаСервередобавил вызов процедуры ЗаполнитьКоманды();
По сути, изменения сводятся к тому, что надо в вышеперечисленных процедурах к условию ОбщегоНазначенияКлиентСервер.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ДополнительныеОтчетыИОбработкиВМоделиСервиса")
добавить условие ОбщегоНазначенияПовтИсп.РазделениеВключено() и объеденить их оператором И.
Если ОбщегоНазначенияПовтИсп.РазделениеВключено()
И ОбщегоНазначенияКлиентСервер.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ДополнительныеОтчетыИОбработкиВМоделиСервиса")
Код измененных процедур модуля ДополнительныеОтчетыИОбработкиРегламентныеЗадания. Извиняюсь за возможную корявость в оформлении кода. Замучился с встроенным редактором...
// Выполняет поиск задания по идентификатору (предположительно, сохраненному в данных
// информационной базы).
//
// Параметры: Идентификатор - УникальныйИдентификатор.
//
// Возвращаемое значение: РегламентноеЗадание.
//
Функция НайтиЗадание(Знач Идентификатор) Экспорт
Если ОбщегоНазначенияПовтИсп.РазделениеВключено()
И ОбщегоНазначенияКлиентСервер.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ДополнительныеОтчетыИОбработкиВМоделиСервиса") Тогда
Модуль = ОбщегоНазначенияКлиентСервер.ОбщийМодуль("ДополнительныеОтчетыИОбработкиРегламентныеЗаданияВМоделиСервиса");
Возврат Модуль.НайтиЗадание(Идентификатор);
КонецЕсли;
Если НЕ ЗначениеЗаполнено(Идентификатор) Тогда
Возврат Неопределено;
КонецЕсли;
УстановитьПривилегированныйРежим(Истина);
Задание = РегламентныеЗадания.НайтиПоУникальномуИдентификатору(Идентификатор);
Возврат Задание;
КонецФункции
// Возвращает идентификатор регламентного задания (для сохранения в данных информационной базы).
//
// Задание - РегламентноеЗадание.
//
// Возвращаемое значение: УникальныйИдентификатор.
//
Функция ПолучитьИдентификаторЗадания(Знач Задание) Экспорт
Если ОбщегоНазначенияПовтИсп.РазделениеВключено() И
ОбщегоНазначенияКлиентСервер.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ДополнительныеОтчетыИОбработкиВМоделиСервиса") Тогда
Модуль = ОбщегоНазначенияКлиентСервер.ОбщийМодуль("ДополнительныеОтчетыИОбработкиРегламентныеЗаданияВМоделиСервиса");
Возврат Модуль.ПолучитьИдентификаторЗадания(Задание);
КонецЕсли;
Возврат Задание.УникальныйИдентификатор;
КонецФункции
// Возвращает параметры регламентного задания.
//
// Параметры:
// Задание - РегламентноеЗадание.
//
// Возвращаемое значение: Структура, ключи:
// Использование - булево, флаг использования регламентного задания,
// Наименование - строка, наименование регламентного задания,
// Параметры - Массив(Произвольный), параметры регламентного задания,
// Расписание - РасписаниеРегламентногоЗадания.
//
Функция ПолучитьПараметрыЗадания(Знач Задание) Экспорт
Если ОбщегоНазначенияПовтИсп.РазделениеВключено() И
ОбщегоНазначенияКлиентСервер.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ДополнительныеОтчетыИОбработкиВМоделиСервиса") Тогда
Модуль = ОбщегоНазначенияКлиентСервер.ОбщийМодуль("ДополнительныеОтчетыИОбработкиРегламентныеЗаданияВМоделиСервиса");
Возврат Модуль.ПолучитьПараметрыЗадания(Задание);
КонецЕсли;
Результат = Новый Структура();
Результат.Вставить("Использование", Задание.Использование);
Результат.Вставить("Наименование", Задание.Наименование);
Результат.Вставить("Параметры", Задание.Параметры);
Результат.Вставить("Расписание", Задание.Расписание);
Возврат Результат;
КонецФункции
////////////////////////////////////////////////////////////////////////////////
// Подсистема "Дополнительные отчеты и обработки", процедуры и функции по управлению
// регламентными заданиями.
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// ПРОГРАММНЫЙ ИНТЕРФЕЙС
// Создает новое регламентное задание в информационной базе.
//
// Параметры:
// Наименование - строка, наименование регламентного задания.
//
// Возвращаемое значение: РегламентноеЗадание.
//
Функция СоздатьНовоеЗадание(Знач Наименование) Экспорт
Если ОбщегоНазначенияПовтИсп.РазделениеВключено() И
ОбщегоНазначенияКлиентСервер.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ДополнительныеОтчетыИОбработкиВМоделиСервиса") Тогда
Модуль = ОбщегоНазначенияКлиентСервер.ОбщийМодуль("ДополнительныеОтчетыИОбработкиРегламентныеЗаданияВМоделиСервиса");
Возврат Модуль.СоздатьНовоеЗадание();
КонецЕсли;
Задание = РегламентныеЗадания.СоздатьРегламентноеЗадание("ЗапускДополнительныхОбработок");
Задание.Использование = Ложь;
Задание.Наименование = Наименование;
Задание.Записать();
Возврат Задание;
КонецФункции
// Удаляет регламентное задание из информационной базы.
//
// Параметры:
// Задание - РегламентноеЗадание.
//
Процедура УдалитьЗадание(Знач Задание) Экспорт
Если ОбщегоНазначенияПовтИсп.РазделениеВключено()
И ОбщегоНазначенияКлиентСервер.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ДополнительныеОтчетыИОбработкиВМоделиСервиса") Тогда
Модуль = ОбщегоНазначенияКлиентСервер.ОбщийМодуль("ДополнительныеОтчетыИОбработкиРегламентныеЗаданияВМоделиСервиса");
Модуль.УдалитьЗадание(Задание);
Возврат;
КонецЕсли;
Если ТипЗнч(Задание) = Тип("РегламентноеЗадание") Тогда
Задание.Удалить();
КонецЕсли;
КонецПроцедуры
// Устанавливает параметры регламентного задания.
//
// Параметры:
// Задание - РегламентноеЗадание,
// Использование - булево, флаг использования регламентного задания,
// Наименование - строка, наименование регламентного задания,
// Параметры - Массив(Произвольный), параметры регламентного задания,
// Расписание - РасписаниеРегламентногоЗадания.
//
Процедура УстановитьПараметрыЗадания(Задание, Использование, Наименование, Параметры, Расписание) Экспорт
Если ОбщегоНазначенияПовтИсп.РазделениеВключено() И
ОбщегоНазначенияКлиентСервер.ПодсистемаСуществует("СтандартныеПодсистемы.РаботаВМоделиСервиса.ДополнительныеОтчетыИОбработкиВМоделиСервиса") Тогда
Модуль = ОбщегоНазначенияКлиентСервер.ОбщийМодуль("ДополнительныеОтчетыИОбработкиРегламентныеЗаданияВМоделиСервиса");
Модуль.УстановитьПараметрыЗадания(Задание, Использование, Параметры, Расписание);
Возврат;
КонецЕсли;
Задание.Использование = Использование;
Задание.Наименование = Наименование;
Задание.Параметры = Параметры;
Задание.Расписание = Расписание;
Задание.Записать();
КонецПроцедуры