Пример программного кода, позволяющего «вывести» настройку функционала конфигурации информационной базы 1С:Предприятие, версии 7.7 из под ответственности программиста и передать его аналитику бизнес процессов.
В данной статье, позвольте «покуситься на святое» и вывести огромный блок задач из под ответственности программиста в ответственность пользователя, ну, или его консультанта по информационной системе. Я говорю о конфигурировании движений документов в системе управленческого учета. И если раньше, мы это делали в конфигураторе, редактированием, непосредственно, модуля каждого документа, то сейчас, с учетом [ссылка], мы можем определить внешний для системы 1С:Предприятие файл, где хранить параметры проведения в удобном для анализа и настройки виде.
Перед чтением данной статьи, также рекомендую посмотреть статью [ссылка] где продемонстрирована возможность создания универсальной выгрузки данных информационной базы в xml-файл и статью [ссылка], где, в рамках задачи обмена между базами разных конфигураций, приводится пример трансформации xml-файла.
В конфигурации из статьи [ссылка] зададим справочник «Товары», в документе «Продажа» определим табличную часть с реквизитами «Товар» — тип «Справочник.Товары», «Количество» — тип «Число». Добавим регистр «ОстаткиТоваров», в котором определим ресурс «Товар» — тип «Справочник.Товары» и измерение «Количество».
Переопределим обработку проведения в модуле документа «Продажа» таким образом, чтобы при проведении, обращаться к универсальной обработке формирования движений:
//*******************************************
// вызов процедуры проведения документа
Процедура ОбработкаПроведения(Параметр)
// передача управления в глобальный модуль
глОбработкаПроведения(Контекст, ?(ПустоеЗначение(Параметр) = 0, Параметр,
СформироватьДвиженияДокумента(Контекст)));
КонецПроцедуры
//*******************************************
// универсальная обработка проведения
Функция СформироватьДвиженияДокумента(Конт) Экспорт
хмлИсходныйФайл = ХМЛПредставлениеДокумента(Конт);
Преобразование = "<?xml version=""1.0"" encoding=""WINDOWS-1251""?>
|<xsl:stylesheet version=""1.0"" xmlns:xsl=""http://www.w3.org/1999/XSL/Transform"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xs=""http://www.w3.org/2001/XMLSchema"" xmlns:myType=""http://my.org/buh"">
|<xsl:template match=""/"">
|<ДвиженияДокумента>
|<xsl:for-each select=""Документ_Продажа"">
|<Продажи>
|<п>
|<Направление>0</Направление>
|<Клиент><xsl:value-of select=""Клиент""/></Клиент>
|<Сумма><xsl:value-of select=""СуммаДокумента""/></Сумма>
|</п>
|</Продажи>
|</xsl:for-each>
|<xsl:for-each select=""Документ_Продажа/ТабЧасть"">
|<ОстаткиТоваров>
|<п>
|<Направление>-1</Направление>
|<Товар><xsl:value-of select=""Товар""/></Товар>
|<Количество><xsl:value-of select=""Количество""/></Количество>
|</п>
|</ОстаткиТоваров>
|</xsl:for-each>
|</ДвиженияДокумента>
|</xsl:template>
|</xsl:stylesheet>
|";
хмлПреобразование = СоздатьОбъект("Msxml2.DOMDocument.6.0");
хмлПреобразование.async = 0;
хмлПреобразование.loadXML(Преобразование);
хмлРезультат = СоздатьОбъект("Msxml2.DOMDocument.6.0");
хмлРезультат.async = 0;
хмлИсходныйФайл.transformNodeToObject(хмлПреобразование, хмлРезультат);
Возврат хмлРезультат;
КонецФункции
Как видим, результат формирования — набор движений, представленный в xml-формате [ссылка], получен xslt-преобразованием данных документа, сформированных процедурой «ХМЛПредставлениеДокумента»-аналогом соответствующей процедуры для справочника в статье [ссылка] и представленной ниже:
//*******************************************
// универсальная обработка проведения
Функция ХМЛПредставлениеДокумента(Конт) Экспорт
хмлПарсер = СоздатьОбъект("Msxml2.DOMDocument.6.0");
хмлУзел = хмлПарсер.appendChild(хмлПарсер
.createElement("Документ_" + Конт.Вид()));
Для й = 1 По Метаданные.Документ(Конт.Вид()).РеквизитШапки() Цикл
ИмяРек = Метаданные.Документ(Конт.Вид())
.РеквизитШапки(й).Идентификатор;
хмлРек = хмлУзел.appendChild(хмлПарсер.createElement(ИмяРек));
Значение = Конт.ПолучитьАтрибут(ИмяРек);
Если ТипЗначения(Значение) < 10 Тогда
хмлРек.text = СокрЛП(Значение);
Иначе
хмлРек.text = ЗначениеВСтрокуВнутр(Значение);
КонецЕсли;
КонецЦикла;
Конт.ВыбратьСтроки();
Пока Конт.ПолучитьСтроку() = 1 Цикл
хмлТЧ = хмлУзел.appendChild(хмлПарсер
.createElement("ТабЧасть"));
Для й = 1 По Метаданные.Документ(Конт.Вид()).РеквизитТабличнойЧасти() Цикл
ИмяРек = Метаданные.Документ(Конт.Вид())
.РеквизитТабличнойЧасти(й).Идентификатор;
хмлРек = хмлТЧ.appendChild(хмлПарсер.createElement(ИмяРек));
Значение = Конт.ПолучитьАтрибут(ИмяРек);
Если ТипЗначения(Значение) < 10 Тогда
хмлРек.text = СокрЛП(Значение);
Иначе
хмлРек.text = ЗначениеВСтрокуВнутр(Значение);
КонецЕсли;
КонецЦикла;
КонецЦикла;
Возврат хмлПарсер;
КонецФункции
После проведения документа, будут записаны движения как для регистра «Продажи», так и для регистра «ОстаткиТоваров» с соответствующим знаком. Как видим, всю подсистему оперативного учета, все процедуры формирования движений документов этой [и других] подсистемы можно уместить в одном xslt-шаблоне в наглядном виде.
Примечание
Конечно, в данной процедуре нет места процедурам контроля остатка на складе и размера товарного кредита клиента после выполнения операции. Также нет места вычислениям себестоимости списанной продукции, определение партии и других «полезных» вещей. Эта методика хорошо работает там, где всего этого нет. Скажем так, если мы собираемся строить эффективную [«быструю»] конфигурацию, тогда все эти вычисления должны быть вынесены в фоновый режим. Там их проще оптимизировать.