Заполнение цен в УТ на основании поступления

В программировании важно соблюдения однообразия и разумной логики.

Когда я столкнулся с заполнением цен в документе «Установка цен», введенном на основании документа «Поступление товаров», я понял, что этот принцип не очевиден разработчикам 1С.

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

Поэтому я сперва, не глядя, написал такой код:


&После("ЗаполнитьПоПоступлениюТоваровУслуг")
Процедура дор_ЗаполнитьПоПоступлениюТоваровУслуг(Знач ДокументОснование, ДанныеЗаполнения)
	//Осипов 2021-07-01 - рассчитываем по наценке опт и розница и  округлению
	Возврат;
	СвойствоПроцентНаценкиРозницы = _Сервер.ДатьДопСвойство("ПроцентНаценкиРозницы");
	СвойствоПроцентНаценкиОпт = _Сервер.ДатьДопСвойство("ПроцентНаценкиОпт");
	СвойствоОкруглениеЦены = _Сервер.ДатьДопСвойство("ОкруглениеЦены");
	ВидЦеныЗакупочная = Справочники.ВидыЦен.НайтиПоРеквизиту("Идентификатор", "Закупочная");
	ВидЦеныРозничная = Справочники.ВидыЦен.НайтиПоРеквизиту("Идентификатор", "РозничнаяЦена");
	ВидЦеныОптовая = Справочники.ВидыЦен.НайтиПоРеквизиту("Идентификатор", "ОптоваяЦена");
	

	ТоварыОснования = ДокументОснование.Товары;
	
	Всего = ЭтотОбъект.Товары.Количество();
	Для Инд = 1 ПО Всего Цикл                       

		Строка = ЭтотОбъект.Товары[Инд- 1];
		ТекИдентификаторЦены = Строка.ВидЦены.Идентификатор;
		
		Если ТекИдентификаторЦены <> "Закупочная" Тогда
			Продолжить;
		КонецЕсли;     
		
		ДобавитьЦену(ЭтотОбъект.Товары, ТоварыОснования, Строка, ВидЦеныОптовая, СвойствоПроцентНаценкиОпт, СвойствоОкруглениеЦены);
		ДобавитьЦену(ЭтотОбъект.Товары, ТоварыОснования, Строка, ВидЦеныРозничная, СвойствоПроцентНаценкиРозницы, СвойствоОкруглениеЦены);
		
	КонецЦикла;
КонецПроцедуры

Процедура ДобавитьЦену(Товары, ТоварыОснования, Строка, ВидЦены, СвойствоПроцентНаценки, СвойствоОкруглениеЦены) Экспорт
	ТекНоменклатура = Строка.Номенклатура;
	ПроцентНаценки = _Сервер.ДатьДопСвойствоПоСсылке(ТекНоменклатура, СвойствоПроцентНаценки);
	Если НЕ ЗначениеЗаполнено(ПроцентНаценки) Тогда
		Возврат;
	КонецЕсли;          
	
	ОкруглениеЦеныСпр = _Сервер.ДатьДопСвойствоПоСсылке(ТекНоменклатура, СвойствоОкруглениеЦены);
	ОкруглениеЦены = 0.01;
	Если ЗначениеЗаполнено(ОкруглениеЦеныСпр) Тогда
		Попытка
			ОкруглениеЦены = Число(ОкруглениеЦеныСпр.Наименование);
		Исключение
		КонецПопытки;
	КонецЕсли;                                                  
	
	ИскСтроки = ТоварыОснования.НайтиСтроки(Новый Структура("Номенклатура", ТекНоменклатура));
	Если ИскСтроки.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;
	ЗакупочнаяЦена = ИскСтроки[0].Цена;

	
	НСтр = Товары.Добавить();
	НСтр.ВидЦены = ВидЦены;
	НСтр.Номенклатура = Строка.Номенклатура;
	НСтр.Цена = ЗакупочнаяЦена * (100 + ПроцентНаценки) / 100;
	НСтр.Цена = ОкрулитьДО(НСтр.Цена, ОкруглениеЦены);
	
КонецПроцедуры


Функция ОкрулитьДО(Число, Точность)         
	//https://forum.mista.ru/topic.php?id=699760
	Если Точность = 0 Тогда
		Возврат Окр(Число, 0);
	КонецЕсли;
    Возврат Окр(Число / Точность) * Точность;
КонецФункции

Увы, он не сработал. Потому что в обработка заполнения просто копировала список товаров в табличную часть, причем с нулевой ценой:

1С пошла другой, кривой дорожкой. Она заполняет цены при старте в процедуре «ПриСозданииНаСервере»:

Пришлось вставить свою обертку, которая помещает виды цен и цены в табличную часть:

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

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

		//Загружаем опять в форму то, что хранится в табличной части товары		
		УстановкаЦенСервер.ЗагрузитьТабличнуюЧастьТовары(ЭтаФорма, КэшДанных);


	КонецЕсли;

	Возврат Результат;
КонецФункции

Получилось корректно:

Потому что в самом дереве цены корректировать я не хотел, там колонки называются идентификаторами с Guid и писать код очень сложно:

Но я добавил еще тестовый код заполнения цен по счетчику, чтобы убедиться, что цены можно скорректировать таким образом. Проверил в табличной части — сработало:

Проверил в форме — тоже сработало:

Теперь осталось только перенести свои наработки в новое место:


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

		//Код скопирован из ПередЗаписьюНаСервере
		УстановкаЦенСервер.ПоместитьВидыЦенВТабличнуюЧасть(ЭтаФорма, Объект.ВидыЦен, ложь);
		
		Данные = Новый Структура;
		Данные.Вставить("Форма", ЭтаФорма);
		Данные.Вставить("Документы", Новый Массив);
		Данные.Вставить("СохранятьБазовые", Ложь);
		Данные.Документы.Добавить(Объект);
		УстановкаЦенСервер.ПоместитьЦеныВТабличнуюЧасть(Данные); 
		
		//Добавляем заполнялку 
		дор_ЗаполнитьПоПоступлениюТоваровУслуг(Объект.ДокументОснование);

		//Загружаем опять в форму то, что хранится в табличной части товары		
		УстановкаЦенСервер.ЗагрузитьТабличнуюЧастьТовары(ЭтаФорма, КэшДанных);


	КонецЕсли;

	Возврат Результат;
КонецФункции


Процедура дор_ЗаполнитьПоПоступлениюТоваровУслуг(Знач ДокументОснование)
	//Осипов 2021-07-01 - рассчитываем по наценке опт и розница и  округлению
	
	СвойствоПроцентНаценкиРозницы = _Сервер.ДатьДопСвойство("ПроцентНаценкиРозницы");
	СвойствоПроцентНаценкиОпт = _Сервер.ДатьДопСвойство("ПроцентНаценкиОпт");
	СвойствоОкруглениеЦены = _Сервер.ДатьДопСвойство("ОкруглениеЦены");
	ВидЦеныЗакупочная = Справочники.ВидыЦен.НайтиПоРеквизиту("Идентификатор", "Закупочная");
	ВидЦеныРозничная = Справочники.ВидыЦен.НайтиПоРеквизиту("Идентификатор", "РозничнаяЦена");
	ВидЦеныОптовая = Справочники.ВидыЦен.НайтиПоРеквизиту("Идентификатор", "ОптоваяЦена");
	

	ТоварыОснования = ДокументОснование.Товары;
	
	Для Каждого Строка ИЗ Объект.Товары Цикл                    
		
		ТекНоменклатура = Строка.Номенклатура;
		
		ТекИдентификаторЦены = Строка.ВидЦены.Идентификатор;
		
		ИскСтроки = Объект.Товары.НайтиСтроки(Новый Структура("Номенклатура, ВидЦены", ТекНоменклатура, ВидЦеныЗакупочная));
		Если ИскСтроки.Количество() =0 Тогда
			Продолжить;
		КонецЕсли;
		ЗакупочнаяЦена = ИскСтроки[0].Цена;
		Если ТекИдентификаторЦены = "РозничнаяЦена" Тогда
			ПроцентНаценки = _Сервер.ДатьДопСвойствоПоСсылке(ТекНоменклатура, СвойствоПроцентНаценкиРозницы);
		ИначеЕсли ТекИдентификаторЦены = "ОптоваяЦена" Тогда
			ПроцентНаценки = _Сервер.ДатьДопСвойствоПоСсылке(ТекНоменклатура, СвойствоПроцентНаценкиОпт);
		Иначе
			Продолжить;
		КонецЕсли;        
		Если ПроцентНаценки = Неопределено Тогда
			Продолжить;
		КонецЕсли;
		
		ОкруглениеЦеныСпр = _Сервер.ДатьДопСвойствоПоСсылке(ТекНоменклатура, СвойствоОкруглениеЦены);
		ОкруглениеЦены = 0.01;
		Если ЗначениеЗаполнено(ОкруглениеЦеныСпр) Тогда
			Попытка
				ОкруглениеЦены = Число(ОкруглениеЦеныСпр.Наименование);
			Исключение
			КонецПопытки;
		КонецЕсли;
			
		ТекЦена = ЗакупочнаяЦена * (100 + ПроцентНаценки) / 100;
		ТекЦена = ОкрулитьДО(ТекЦена, ОкруглениеЦены);
		Строка.Цена = ТекЦена;
		
	КонецЦикла;
КонецПроцедуры

Функция ОкрулитьДО(Число, Точность)         
	//https://forum.mista.ru/topic.php?id=699760
	Если Точность = 0 Тогда
		Возврат Окр(Число, 0);
	КонецЕсли;
    Возврат Окр(Число / Точность) * Точность;
КонецФункции

Объем факт: 3 час. Среда: УТ 11.4.13.46.

fixin

Программирую на 1С с 1999 года. В 1С просто Гений. В 2020 году ушел из офиса на вольные хлеба фриланса. Принимаю заказы.

Читайте также:

комментария 4

  1. Zuko:

    Конструктивная критика приветствуется?

  2. Павел:

    Чем больше я смотрю в современные типовые тем чаще думаю о смене видя деятельности. Надоело уже это адское мучине — сидеть и исследовать стек вызовов по 30 процедур. Чтобы сделать документ с поведением счета и субконто как в типовых — надо скопировать пол-бухгалтерии общих модулей. А поведение контролируется сразу тремя способами — свойствами полей документа, кодом и условным оформлением.

    • 1С сделала «поворот не туда». И потом повторила 100500 раз. Да. Методологи у нее слабоватенькие. Архитектура никуда не годится.

Добавить комментарий для fixin Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *