diamond АШ Tlg

1C ERP: Как разработать и добавить собственные этапы закрытия месяца

Описание точек входа и сквозной пример разработки этапа для типовой обработки Регламентные операции закрытия месяца

Содержание

Введение, постановка задачи

Типовую обработку 1С ERP "Регламентные операции по закрытию месяца" можно использовать не только для выполнения операций регламентированного учёта, но и вообще для любой задачи, которая требует проверок с отметкой о выполнении или невыполнении произвольных условий. Опциональная возможность - наложение запрета на выполнение зависимых задач при непрохождении проверок этапа. Для добавления нового кастомного этапа закрытия месяца нужно произвести несложные доработки по примеру в этой статье - я покажу точки входа для разработчика и как это работает.

Типовая обработка вам уже знакома, на картинке указал как называются сущности на форме:

Типовое закрытие месяца

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

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

Подготовка учёта

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

Настройка регистра сведений
Настройка регистра сведений
Настройка регистра сведений

Добавление описания группы этапов

В общем модуле ЗакрытиеМесяцаСервер находим процедуру ЗаполнитьОписаниеГруппЭтаповЗакрытияМесяца. Типовые группы добавляются здесь. У него в конце есть вызов из модуля локализации ЗакрытиеМесяцаЛокализация .ДополнитьОписаниеГруппЭтаповЗакрытияМесяца - по-хорошему именно там и нужно добавлять:

Процедура ДополнитьОписаниеГруппЭтаповЗакрытияМесяца(ТаблицаГруппЭтапов) Экспорт
    //++ Локализация
    ...        
    // { АШ
    АШ_Стимулирование.ДополнитьОписаниеГруппЭтаповЗакрытияМесяца(ТаблицаГруппЭтапов);
    // }
        
    //-- Локализация
КонецПроцедуры

Создаем новый общий модуль АШ_Стимулирование и пишем в нём вышеуказанную процедуру:

#Область ОписаниеЭтапов

Процедура ДополнитьОписаниеГруппЭтаповЗакрытияМесяца(ТаблицаГруппЭтапов) Экспорт
    
    // Вставляем после группы "Ручные операции":
    ИндексГруппы = ТаблицаГруппЭтапов.Индекс(
        ТаблицаГруппЭтапов.Найти(ЗакрытиеМесяцаСервер.ИдентификаторГруппыРучныеОперации())) + 1;
        
    НоваяСтрока = ТаблицаГруппЭтапов.Вставить(ИндексГруппы);
    НоваяСтрока.Код = ИдентификаторГруппыСтимулирование();
    НоваяСтрока.Наименование = НСтр("ru = 'Стимулирование';
                                    |en = 'Stimulation'");

КонецПроцедуры
    
Функция ИдентификаторГруппыСтимулирование()
    Возврат "Стимулирование";
КонецФункции
    
#КонецОбласти

Добавление описания этапа закрытия месяца

В типовое перечисление ОперацииЗакрытияМесяца добавить новое значение: ПростимулироватьПрограммиста

В типовом общем модуле ЗакрытиеМесяцаЛокализация доработать процедуру ДополнитьОписаниеЭтаповЗакрытияМесяца

Процедура ДополнитьОписаниеЭтаповЗакрытияМесяца(ТаблицаЭтапов) Экспорт
    //++ Локализация
    ...
    // { АШ
    АШ_Стимулирование.ДополнитьОписаниеЭтаповЗакрытияМесяца(ТаблицаЭтапов);
    // }

    //-- Локализация
КонецПроцедуры

Добавить в общий модуль:

Процедура ДополнитьОписаниеЭтаповЗакрытияМесяца(ТаблицаЭтапов) Экспорт

    ТекущийРодитель = ИдентификаторГруппыСтимулирование();
    ДобавитьЭтап_ПростимулироватьПрограммиста(ТаблицаЭтапов, ТекущийРодитель);

КонецПроцедуры

Процедура ДобавитьЭтап_ПростимулироватьПрограммиста(ТаблицаЭтапов, ТекущийРодитель)
	
    НоваяСтрока = ЗакрытиеМесяцаСервер.ДобавитьЭтапВТаблицу(ТаблицаЭтапов, ТекущийРодитель,
        // новое значение перечисления:
        Перечисления.ОперацииЗакрытияМесяца.ПростимулироватьПрограммиста,
        // пусть это будет регл учёт:
        Ложь, Истина, Ложь);
		
    // Предшествующие этапы, если есть:
    //НоваяСтрока.ПредшествующиеЭтапы.Добавить(Перечисления.ОперацииЗакрытияМесяца.ПереходНаЕдиныйНалоговыйСчет);
	
    // Текст кнопки Выполнить:
    НоваяСтрока.ТекстВыполнить = НСтр("ru = 'Простимулировать';
                                        |en = 'Stimulate'");
	
    // Действие при нажатии Использование
    НоваяСтрока.ДействиеИспользование = ЗакрытиеМесяцаСервер.ОписаниеДействия_СервернаяПроцедура(
        "АШ_Стимулирование.Использование_ПростимулироватьПрограммиста");
	
    // Действие при нажатии Выполнить
    НоваяСтрока.ДействиеВыполнить  = ЗакрытиеМесяцаСервер.ОписаниеДействия_ВыполнитьРасчет(
        "АШ_Стимулирование.Выполнить_ПростимулироватьПрограммиста");
	
    // Действие при нажатии Подробнее - открываем форму списка РС АШ_Стимулирование
    НоваяСтрока.ДействиеПодробнее = ЗакрытиеМесяцаСервер.ОписаниеДействия_ОткрытьФорму(
        Метаданные.РегистрыСведений.АШ_Стимулирование.Формы.ФормаСписка.ПолноеИмя()); 
		
КонецПроцедуры

Пишем код выполнение этапа

Продолжаем в общем модуле АШ_Стимулирование, код для выполнения проверок этапа:

Процедура Использование_ПростимулироватьПрограммиста(ПараметрыОбработчика) Экспорт 
	
	// Здесь нужно выполнить различные проверки учёта и в зависимости от
	// результата установить одно из состояний операции закрытия месяца:
	// ПараметрыОбработчика.ДанныеЭтапа.Состояние = Перечисления.СостоянияОперацийЗакрытияМесяца.[Значение]	
	// !!! Проверка выполняется 2 раза до и после выполнения этапа !!!

	СуммаСтимулирования = 0;	

	Запрос = Новый Запрос("ВЫБРАТЬ
	|	АШ_СтимулированиеСрезПоследних.Сумма КАК Сумма
	|ИЗ
	|	РегистрСведений.АШ_Стимулирование.СрезПоследних(&Период, ) КАК АШ_СтимулированиеСрезПоследних");
	Запрос.УстановитьПараметр("Период", ПараметрыОбработчика.ПараметрыРасчета.Период);
	Выборка = Запрос.Выполнить().Выбрать();
			
	Если Выборка.Следующий() Тогда 
		СуммаСтимулирования = Выборка.Сумма;
	КонецЕсли;	
		
	Если СуммаСтимулирования = 0 Тогда
		ПараметрыОбработчика.ДанныеЭтапа.Состояние = Перечисления.СостоянияОперацийЗакрытияМесяца.НеВыполнено;
		ЗакрытиеМесяцаСервер.ДобавитьПоясняющуюИнформациюКЭтапу(ПараметрыОбработчика,
			"Дай миллион!", "Тебе жалко что-ли?",, Перечисления.ВажностьПроблемыУчета.Ошибка);	
	ИначеЕсли СуммаСтимулирования < 1000000 Тогда
		ПараметрыОбработчика.ДанныеЭтапа.Состояние = Перечисления.СостоянияОперацийЗакрытияМесяца.ВыполненоСОшибками;
		ЗакрытиеМесяцаСервер.ДобавитьПоясняющуюИнформациюКЭтапу(ПараметрыОбработчика,
			"Маловато будет!", "Ещё давай!",, Перечисления.ВажностьПроблемыУчета.Ошибка);	
	Иначе
		ПараметрыОбработчика.ДанныеЭтапа.Состояние = Перечисления.СостоянияОперацийЗакрытияМесяца.ВыполненоУспешно;
		ЗакрытиеМесяцаСервер.ДобавитьПоясняющуюИнформациюКЭтапу(ПараметрыОбработчика,
			"Программист дуреет с этой прикормки",,, Перечисления.ВажностьПроблемыУчета.ПолезныйСовет);	
	КонецЕсли;
	                            
КонецПроцедуры

Код для для кнопки этапа "Выполнить", в нашем случае просто получаем остаток самодельного регистра и накидываем сверху сумму стимулирования:

Процедура Выполнить_ПростимулироватьПрограммиста(ПараметрыОбработчика) Экспорт 
	
    // Здесь пишем бизнес-логику этапа закрытия месяца
	
    // 1. Получим сумму стимулирования в текущем периоде
    СуммаСтимулирования = 0;	

    Запрос = Новый Запрос("ВЫБРАТЬ
        |	АШ_СтимулированиеСрезПоследних.Сумма КАК Сумма
        |ИЗ
        |	РегистрСведений.АШ_Стимулирование.СрезПоследних(&Период, ) КАК АШ_СтимулированиеСрезПоследних");
    Запрос.УстановитьПараметр("Период", ПараметрыОбработчика.ПараметрыРасчета.Период);
    Выборка = Запрос.Выполнить().Выбрать();
			
    Если Выборка.Следующий() Тогда 
        СуммаСтимулирования = Выборка.Сумма;
    КонецЕсли;
	
    // 2. Прибавим к сумме ещё 400000 рублей
    НаборЗаписей = РегистрыСведений.АШ_Стимулирование.СоздатьНаборЗаписей();
    НоваяЗапись = НаборЗаписей.Добавить(); 
    НоваяЗапись.Период = ПараметрыОбработчика.ПараметрыРасчета.Период; 
    НоваяЗапись.Сумма = СуммаСтимулирования + 400000; 
    НаборЗаписей.Записать();
	
КонецПроцедуры

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

Смотрим как работает

Закрытие месяца проверка

Жмём кнопку "Простимулировать" и смотрим что произошло:

Закрытие месяца проверка

Жмём кнопку "Простимулировать" ещё пару раз:

Закрытие месяца проверка

Отлично! Мы справились с задачей, но не полностью. Самостоятельная работа: проанализировать типовой код 1С ERP и сделать этап "Отражение зарплаты в регучёте" зависимым от этапа "Простимулировать программиста".

Дополнение: как сделать этап предварительным

Процедура ДобавитьЭтап_ПростимулироватьПрограммиста(ТаблицаЭтапов, ТекущийРодитель)
	
    НоваяСтрока = ...

    // Добавить в конце:
    НоваяСтрока.ВыполняетсяПриПредварительномЗакрытииМесяца = Истина;

КонецПроцедуры