«Я сама». Настраиваем план счетов: ожидания и реальность

18.02.25

База данных - HighLoad оптимизация

Пример популярной пользовательской настройки плана счетов. К чему это может привести, почему «всё тормозит» и как это поправить.

Меня зовут Павел Белоусов, я Разработчик 1С в компании OCS Distribution.

В статье я расскажу о достаточно популярной пользовательской настройке плана счетов, которую я встречал как у нас, в конфигурации «Бухгалтерия 3.0», так и во многих других организациях.

Речь пойдёт про добавление субконто с видом «Документы расчетов с контрагентом» к отдельным счетам, в которых есть субконто «Контрагенты» и «Договоры». В частности, рассмотрим счета 60.* и 62.*

 

 

и

 

 

Для чего это делается?

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

2. «Чтобы быстрее проводились документы», так как количество данных при расчете текущего остатка по данной аналитике заметно меньше.

3. «Параллельность проведения документов» по разным документам расчётов.

 

Что же происходит на самом деле...

— замедление проведения документов,

— ожидания на блокировках по разным документам расчёта.

То есть получаем обратный эффект! Причём в процессе работы причинно-следственную связь между такой настройкой плана счетов и замедлением работы никто не замечает.

 

Пришло время наконец-то позвать разработчика

... и начать анализировать код проведения.

Делаем замер производительности при проведении трёх видов документов, которые попали в топ рейтинга по длительности проведения. Это КорректировкаДолга, РеализацияОтгруженныхТоваров и ВозвратТоваровПоставщику. В документах корректировок долга у нас преимущественно всего одна строка данных, то есть фигурирует один-единственный документ расчётов контрагента. Аналогично для реализаций отгруженных товаров и возвратов поставщику: один документ расчётов.

Что мы видим: в модуле УчетВзаиморасчетов находим пару-тройку функций с примерно одинаковой структурой кода. Это:

Функция ПодготовитьТаблицуВзаиморасчетовЗачетАвансов(...
Функция ПодготовитьТаблицуВзаиморасчетовПогашениеЗадолженности(...
Функция ПодготовитьТаблицуВзаиморасчетовЗачетАвансовВозвратПоставщику(...

Каждая из них возвращает

    Возврат ТаблицаВзаиморасчетов;

с одной-единственной строкой данных, соответствующих нашему документу расчётов. Но ей предшествуют вызов функций

   ОстаткиАвансов = ПолучитьОстаткиАвансов(...
   ОстаткиЗадолженности = ПолучитьОстаткиЗадолженности(...

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

 

 

Что мы видим на картинке: выбраны остатки по 21 документу расчётов, 20 из которых нам не нужны.
в других случаях ещё больше. Исключаем явно ошибочную ситуацию, когда пользователи не позаботились о корректном закрытии остатков в разрезе каждого документа расчётов, — тогда количество в выборке может быть и несколько тысяч. На практике видим, что функции возвращают до пары сотен строк данных! Это вполне типичная ситуация: отгрузки в работе, ещё не закрытые оплатой, при том, что нам нужна только одна, и, кстати, следующая в коде процедура их как-раз отфильтровывает, оставляя нам всего одну строку с нужной отгрузкой.

 

Что нам дал анализ кода этих двух функций?

Часть текста запроса:

ИЗ
    РегистрБухгалтерии.Хозрасчетный.Остатки(
            &МоментВремениОстатков,
            Счет В (&СчетаРасчетовПоДокументам),
            &ВидыСубконтоРасчетов,
            Организация = &Организация
                И Субконто1 В (&Контрагенты)
                И Субконто2 В (&Договоры)) КАК Остатки

 

Здесь нет никакого намёка на установку отбора по документам расчётов!
Также в коде устанавливается управляемая блокировка с отбором на Контрагенты И Договоры, но не на ДокументыРасчетовСКонтрагентами!


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

 

Как поправить? Наш подход.

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

Второе: на основе этого признака исправляем текст выборки остатков и корректируем установку управляемой блокировки.

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

 

Пример решения показан ниже: здесь вставки в типовой код модуля «УчетВзаиморасчетов».

Функция ПолучитьОстаткиАвансов(ТаблицаДокумента, Реквизиты, Отказ)
...
    // DEV++ проверяем возможность включения режима оптимизации
    // Исходный код++
    // ТаблицаДоговоров = ТаблицаДокумента.СкопироватьКолонки("СчетАвансов,Контрагент,ДоговорКонтрагента");
    // Исходный код--

    ДоступенРежимПоДокументамРасчета = dev_ПроцедурыСервер.ПроверитьУсловияАвансыПоДокументамРасчета(ТаблицаДокумента, Реквизиты);
    Если ДоступенРежимПоДокументамРасчета = Истина Тогда
        ТаблицаДоговоров = ТаблицаДокумента.СкопироватьКолонки("СчетАвансов,Контрагент,ДоговорКонтрагента,ДокументРасчетов");
    Иначе
        ТаблицаДоговоров = ТаблицаДокумента.СкопироватьКолонки("СчетАвансов,Контрагент,ДоговорКонтрагента");
    КонецЕсли;
    // DEV--
...
    // DEV++ Сохраняем колонку "ДокументРасчетов"
    // Исходный код++
    // ТаблицаДоговоров.Свернуть("СчетАвансов,Контрагент,ДоговорКонтрагента");
    // Исходный код--
    Если ДоступенРежимПоДокументамРасчета = Истина Тогда
        ТаблицаДоговоров.Свернуть("СчетАвансов,Контрагент,ДоговорКонтрагента,ДокументРасчетов");
    Иначе
        ТаблицаДоговоров.Свернуть("СчетАвансов,Контрагент,ДоговорКонтрагента");
    КонецЕсли;
    // DEV--
...
    Для Каждого СтрокаСчета Из ТаблицаСчетов Цикл
...
        // DEV++ Сохраняем колонку "ДокументРасчетов"
        // Исходный код++
        // ТаблицаДоговоровПоСчету = ТаблицаДоговоров.Скопировать(ОтборПоСчету, "Контрагент,ДоговорКонтрагента");
        // Исходный код--
        Если ДоступенРежимПоДокументамРасчета = Истина Тогда
            ТаблицаДоговоровПоСчету = ТаблицаДоговоров.Скопировать(ОтборПоСчету, "Контрагент,ДоговорКонтрагента,ДокументРасчетов");
        Иначе
            ТаблицаДоговоровПоСчету = ТаблицаДоговоров.Скопировать(ОтборПоСчету, "Контрагент,ДоговорКонтрагента");
        КонецЕсли;
        // DEV--
        
        ЭлементБлокировки.ИсточникДанных = ТаблицаДоговоровПоСчету;
        Для НомерСубконто = 1 По ДанныеСчета.КоличествоСубконто Цикл
...
            // DEV++ корректируем установку блокировки
            ИначеЕсли ДанныеСчета["ВидСубконто" + НомерСубконто] = ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.ДокументыРасчетовСКонтрагентами Тогда
                Если ДоступенРежимПоДокументамРасчета = Истина Тогда
                    ЭлементБлокировки.ИспользоватьИзИсточникаДанных(
                        ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.ДокументыРасчетовСКонтрагентами, "ДокументРасчетов");
                КонецЕсли;
            // DEV--
...
        КонецЦикла;
    КонецЦикла;
...
    Запрос.Текст = ТекстЗапросаОстаткиАвансов(УчитыватьАвансыСОсобымПорядкомНалогообложения);    
    // DEV++ Корректируем текст запроса
    Если ДоступенРежимПоДокументамРасчета = Истина Тогда
        Запрос.Текст = dev_ПроцедурыСервер.ПреобразоватьТекстЗапроса_ОстаткиАвансов_ПоДокументамРасчета(Запрос.Текст);

        Запрос.УстановитьПараметр("ДокументРасчетов",
            ОбщегоНазначения.ВыгрузитьКолонку(ТаблицаДокумента, "ДокументРасчетов", Истина));

    КонецЕсли;
    // DEV--
    РезультатЗапроса = Запрос.Выполнить();
    ОстаткиАвансов = РезультатЗапроса.Выгрузить();

и 

Функция ПолучитьОстаткиЗадолженности(РасшифровкаПлатежа, Реквизиты, Отказ)
...
    // DEV++ проверяем возможность включения оптимизации
    // Исходный код++
    // ТаблицаДоговоров = РасшифровкаПлатежа.СкопироватьКолонки("СчетРасчетов,Контрагент,ДоговорКонтрагента");
    // Исходный код--

    ДоступенРежимПоДокументамРасчета = dev_ПроцедурыСервер.ПроверитьВсеСтрокиПоДокументамРасчета(РасшифровкаПлатежа, Реквизиты);
    Если ДоступенРежимПоДокументамРасчета = Истина Тогда
        ТаблицаДоговоров = РасшифровкаПлатежа.СкопироватьКолонки("СчетРасчетов,Контрагент,ДоговорКонтрагента,ДокументРасчетов");
    Иначе
        ТаблицаДоговоров = РасшифровкаПлатежа.СкопироватьКолонки("СчетРасчетов,Контрагент,ДоговорКонтрагента");
    КонецЕсли;
    // DEV--
...
    // DEV++ сохраняем колонку "ДокументРасчетов"
    // Исходный код++
    // ТаблицаДоговоров.Свернуть("СчетРасчетов,Контрагент,ДоговорКонтрагента");
    // Исходный код--
    Если ДоступенРежимПоДокументамРасчета = Истина Тогда
        ТаблицаДоговоров.Свернуть("СчетРасчетов,Контрагент,ДоговорКонтрагента,ДокументРасчетов");
    Иначе
        ТаблицаДоговоров.Свернуть("СчетРасчетов,Контрагент,ДоговорКонтрагента");
    КонецЕсли;
    // DEV--
...
    Блокировка = Новый БлокировкаДанных;
    Для Каждого СтрокаСчета Из ТаблицаСчетов Цикл
...
        // DEV++ сохраняем колонку "ДокументРасчетов"
        // Исходный код++
        // ТаблицаДоговоровПоСчету = ТаблицаДоговоров.Скопировать(ОтборПоСчету, "Контрагент,ДоговорКонтрагента");
        // Исходный код--
        
        Если ДоступенРежимПоДокументамРасчета = Истина Тогда
            ТаблицаДоговоровПоСчету = ТаблицаДоговоров.Скопировать(ОтборПоСчету, "Контрагент,ДоговорКонтрагента,ДокументРасчетов");
        Иначе
            ТаблицаДоговоровПоСчету = ТаблицаДоговоров.Скопировать(ОтборПоСчету, "Контрагент,ДоговорКонтрагента");
        КонецЕсли;
        // DEV--
        
        ЭлементБлокировки.ИсточникДанных = ТаблицаДоговоровПоСчету;
        Для НомерСубконто = 1 По ДанныеСчета.КоличествоСубконто Цикл
...
            // DEV++ уточняем установку блокировки
            ИначеЕсли ДанныеСчета["ВидСубконто" + НомерСубконто] = ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.ДокументыРасчетовСКонтрагентами Тогда
                Если ДоступенРежимПоДокументамРасчета = Истина Тогда
                    ЭлементБлокировки.ИспользоватьИзИсточникаДанных(
                        ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.ДокументыРасчетовСКонтрагентами, "ДокументРасчетов");
                КонецЕсли;
            // DEV--
...
        КонецЦикла;
    КонецЦикла;
...
    Блокировка.Заблокировать();
    // Получаем остатки
    Запрос = Новый Запрос;
...
    // DEV++
    Если ДоступенРежимПоДокументамРасчета = Истина Тогда
        Запрос.УстановитьПараметр("ДокументыРасчетов", РазличныеЗначенияКолонкиТаблицы(ТаблицаДоговоров, "ДокументРасчетов"));
    КонецЕсли;
    // DEV--
...
    Запрос.Текст = ТекстЗапросаОстаткиЗадолженности(Реквизиты.УчитыватьЗадолженностьУСН ИЛИ Реквизиты.УчитыватьЗадолженностьУСНПатент);
    
    // DEV++ корректируем текст запроса
    Если ДоступенРежимПоДокументамРасчета = Истина Тогда
        Запрос.Текст = dev_ПроцедурыСервер.ПреобразоватьТекстЗапроса_ОстаткиЗадолженности_ПоДокументамРасчета(Запрос.Текст);
    КонецЕсли;
    // DEV--

    ОстаткиЗадолженности = Запрос.Выполнить().Выгрузить();
...
    Возврат ОстаткиЗадолженности;
КонецФункции

 

Плюс функции из нашего модуля «dev_ПроцедурыСервер»: корректировки текста запросов и установки блокировок.

// проверим, что документ имеет именно тот вид, на который рассчитан наш код корректировки,
// если встретится немножко не такой документ, оптимизация на нём включена не будет,
// т. к. не доказано, что это возможно, что это будет корректно...
Функция ПроверитьУсловияАвансыПоДокументамРасчета(ТаблицаДокумента, Реквизиты) Экспорт
	
	Если Не ТипЗнч(Реквизиты.Регистратор) = Тип("ДокументСсылка.РеализацияОтгруженныхТоваров") Тогда
		Возврат(Ложь);
	КонецЕсли;
	
	Если Реквизиты.УчитыватьЗадолженностьУСН Или Реквизиты.УчитыватьЗадолженностьУСНПатент Тогда
		Возврат(Ложь);
	КонецЕсли;
	
	РеквизитыРегистратор = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Реквизиты.Регистратор,
		"ДокументОтгрузки,СпособЗачетаАвансов,РучнаяКорректировка,ЧастичнаяПродажа");
	
	УсловиеНаРеквизиты =
		ЗначениеЗаполнено(РеквизитыРегистратор.ДокументОтгрузки)
		И ТипЗнч(РеквизитыРегистратор.ДокументОтгрузки) = Тип("ДокументСсылка.РеализацияТоваровУслуг")
		И (РеквизитыРегистратор.СпособЗачетаАвансов = Перечисления.СпособыЗачетаАвансов.Автоматически
			Или РеквизитыРегистратор.СпособЗачетаАвансов = Перечисления.СпособыЗачетаАвансов.ПоДокументу)
		И РеквизитыРегистратор.РучнаяКорректировка = Ложь
		И РеквизитыРегистратор.ЧастичнаяПродажа = Ложь;
		
	Если Не(УсловиеНаРеквизиты = Истина) Тогда
		РежимПоДокументамРасчета = Ложь;
	Иначе
		ОстаткиАвансовПоДокументамРасчетов = ПараметрОптимизацииИзСтрокиТаблицы(Реквизиты, "ОстаткиАвансовПоДокументамРасчетов");
		Если ОстаткиАвансовПоДокументамРасчетов = Истина Тогда
			РежимПоДокументамРасчета = Истина;
		Иначе
			РежимПоДокументамРасчета = Ложь;
		КонецЕсли;
	КонецЕсли;
	
	Возврат(РежимПоДокументамРасчета);
	
КонецФункции

Функция ПреобразоватьТекстЗапроса_ОстаткиАвансов_ПоДокументамРасчета(ИсходныйТекст) Экспорт
	
	СтрокаПоиска = "И Субконто2 В (&МассивДоговоры)";
	СтрокаЗамены = "И Субконто2 В (&МассивДоговоры) И Субконто3 В (&ДокументРасчетов)";
	
	Текст = СтрЗаменить(ИсходныйТекст, СтрокаПоиска, СтрокаЗамены);
	
	Возврат(Текст);
	
КонецФункции

// проверим, что все строки платежа — по документу расчёта
Функция ПроверитьВсеСтрокиПоДокументамРасчета(РасшифровкаПлатежа, Реквизиты) Экспорт
	
	РеквизитыРегистратор = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Реквизиты.Регистратор, "ВидОперации");
	Если Не РеквизитыРегистратор.ВидОперации = Перечисления.ВидыОперацийКорректировкаДолга.ПереносЗадолженности Тогда
		РежимПоДокументамРасчета = Ложь;
	Иначе
		ОстаткиЗадолженностиВзаиморасчетовПоДокументамРасчетов =
			ПараметрОптимизацииИзСтрокиТаблицы(Реквизиты, "ОстаткиЗадолженностиВзаиморасчетовПоДокументамРасчетов");
			
		Если ОстаткиЗадолженностиВзаиморасчетовПоДокументамРасчетов = Истина Тогда
			РежимПоДокументамРасчета = Истина;
			Для Каждого СтрокаПлатежа Из РасшифровкаПлатежа Цикл
				Если Не (СтрокаПлатежа.СпособПогашенияЗадолженности = Перечисления.СпособыПогашенияЗадолженности.ПоДокументу И
					ЗначениеЗаполнено(СтрокаПлатежа.ДокументРасчетов)) Тогда
					РежимПоДокументамРасчета = Ложь;
					Прервать;
				КонецЕсли;
			КонецЦикла;
		Иначе
			РежимПоДокументамРасчета = Ложь;
		КонецЕсли;
	КонецЕсли;
	
	Возврат(РежимПоДокументамРасчета);
	
КонецФункции

Функция ПреобразоватьТекстЗапроса_ОстаткиЗадолженности_ПоДокументамРасчета(ИсходныйТекст) Экспорт
	
	СтрокаПоиска = "И Субконто2 В (&Договоры)) КАК Остатки";
	УточнениеПоискаНачало = "РегистрБухгалтерии.Хозрасчетный.Остатки(";
	УточнениеПоискаКлюч = "Счет В (&СчетаРасчетовПоДокументам";
	СтрокаЗамены = "И Субконто2 В (&Договоры) И Субконто3 В (&ДокументыРасчетов) ) КАК Остатки";
	ДлинаСтрокиПоиска = СтрДлина(СтрокаПоиска);
	
	Текст = ИсходныйТекст;
	НомерВхождения = 0;
	Пока Истина Цикл
		НомерВхождения = НомерВхождения + 1;
		Позиция = СтрНайти(Текст, СтрокаПоиска, , , НомерВхождения);
		Если Позиция = 0 Тогда
			Прервать;
		КонецЕсли;
		
		ПодстрокаСлева = Лев(Текст, Позиция + ДлинаСтрокиПоиска - 1);
		ПозицияНачало = СтрНайти(ПодстрокаСлева, УточнениеПоискаНачало, НаправлениеПоиска.СКонца);
		Если ПозицияНачало = 0 Тогда
			Продолжить;
		КонецЕсли;
		ПодстрокаНачало = Лев(ПодстрокаСлева, ПозицияНачало - 1);
		ПодстрокаБлок = Сред(ПодстрокаСлева, ПозицияНачало);
		
		ПозицияКлюч = СтрНайти(ПодстрокаБлок, УточнениеПоискаКлюч);
		Если ПозицияКлюч = 0 Тогда
			Продолжить;
		КонецЕсли;
		ПодстрокаСправа = Сред(Текст, Позиция + ДлинаСтрокиПоиска);

		// нашли. делаем замену
		БлокСЗаменой = СтрЗаменить(ПодстрокаБлок, СтрокаПоиска, СтрокаЗамены);
		Текст = ПодстрокаНачало + БлокСЗаменой + ПодстрокаСправа;
		
	КонецЦикла;
	
	Возврат(Текст);
	
КонецФункции

 

 

Статья написана на основе доклада Методы ускорения группового проведения документов, прочитанного мной на конференции «Infostart tech event 2024» и подробно раскрывает одну из его тем: развязывание зависимостей в документах для подготовки их к многопоточному проведению.

 

 

Бухгалтерия 3.0 План счетов Договоры контрагентов по договорам

См. также

Механизмы типовых конфигураций Программист Платформа 1С v8.3 1C:Бухгалтерия Бесплатно (free)

Расчет себестоимости в типовых конфигурациях 1С – для многих «черный ящик», работающий по жестко зашитым в него алгоритмам. Реализация этого «черного ящика» может меняться в зависимости от конкретной конфигурации – УПП, БП 3.0, ERP. Но принцип работы везде одинаковый. Расскажем о том, как устроен расчет себестоимости, как его дорабатывать, и какие методы могут быть эффективны и без доработок.

27.12.2024    12064    Begemoth80    32    

85

HighLoad оптимизация Технологический журнал Системный администратор Программист Бесплатно (free)

Обсудим поиск и разбор причин длительных серверных вызовов CALL, SCALL.

24.06.2024    6297    ivanov660    12    

56

HighLoad оптимизация Инструменты администратора БД Системный администратор Программист Платформа 1С v8.3 1C:Бухгалтерия Абонемент ($m)

Обработка для простого и удобного анализа настроек, нагрузки и проблем с SQL сервером с упором на использование оного для 1С. Анализ текущих запросов на sql, ожиданий, конвертация запроса в 1С и рекомендации, где может тормозить.

2 стартмани

15.02.2024    14014    276    ZAOSTG    87    

118

HighLoad оптимизация Программист Платформа 1С v8.3 1C:Бухгалтерия Абонемент ($m)

Встал вопрос: как быстро удалить строки из ТЗ? Рассмотрел пять вариантов реализации этой задачи. Сравнил их друг с другом на разных объёмах данных с разным процентом удаляемых строк. Также сравнил с выгрузкой с отбором по структуре.

09.01.2024    18530    doom2good    49    

71

Инструментарий разработчика БСП (Библиотека стандартных подсистем) Механизмы типовых конфигураций Программист Стажер Платформа 1С v8.3 1С:Бухгалтерия 3.0 Бесплатно (free)

Используются для создания новых объектов в конфигурации, чтобы не забыть, что нужно сделать. Сделано на примере 1С:Бухгалтерия предприятия, в других конфигурациях могут быть другие, а могут быть и похожие объекты.

28.12.2023    7298    mrXoxot    11    

113

HighLoad оптимизация Системный администратор Программист Бесплатно (free)

При переводе типовой конфигурации 1C ERP/УТ/КА на PostgreSQL придется вложить ресурсы в доработку и оптимизацию запросов. Расскажем, на что обратить внимание при потерях производительности и какие инструменты/подходы помогут расследовать проблемы после перехода.

20.11.2023    15340    ivanov660    7    

83

HighLoad оптимизация Бесплатно (free)

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

15.11.2023    8168    a.doroshkevich    22    

75
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. quazare 3874 18.02.25 13:10 Сейчас в теме
ну вот сам пишешь, какие-то тут изъяснения, а в запросе указываешь

Счет В (&СчетаРасчетовПоДокументам)

вместо В ИЕРАРХИИ, если работаешь по субсчетам...

а вообще тема тонкая на самом деле!
4. pbelousov 44 20.02.25 15:43 Сейчас в теме
(1) это же типовой код :) вы и в своей бухгалтерии можете его найти.
а иерархия тут даже близко неприменима. просто мимо.
2. ixijixi 1986 19.02.25 08:55 Сейчас в теме
Тем временем БГУ 2.0, типовой счет 210.1х имеет субконто "Счета-фактуры" с составным (порядка 30 штук) типом.
Прикрепленные файлы:
5. pbelousov 44 20.02.25 15:48 Сейчас в теме
(2) если конфигурация нормально с ним работает, то почему бы и нет.
3. VmvLer 19.02.25 15:26 Сейчас в теме
что мешает заменить
// DEV++
на
#Вставка в расширении.

так и код читать легче и сюрпризы при обновлении минимальны
6. pbelousov 44 20.02.25 15:52 Сейчас в теме
(3) все люди делятся на 2 типа:
1. те, кто активно переносит доработки в расширения.
2. кто в состоянии постепенного обратного перехода (отказ от расширений)

по моим наблюдениям, в работе на крупного внутреннего заказчика, преобладает тип 2.
:)
7. VmvLer 20.02.25 16:02 Сейчас в теме
(6) по моим наблюдениям, вмешиваться в типовой код БП в основной конфигурации (у крупного внутреннего заказчика) строго после сотни согласований и обсуждений на тему "зачем мы себе усложняем жизнь и что мешает вынести этот код в расширение".
8. quazare 3874 20.02.25 20:08 Сейчас в теме
Оставьте свое сообщение