Заполнение цен в УТ на основании поступления
В программировании важно соблюдения однообразия и разумной логики.
Когда я столкнулся с заполнением цен в документе «Установка цен», введенном на основании документа «Поступление товаров», я понял, что этот принцип не очевиден разработчикам 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.
Конструктивная критика приветствуется?
Разумеется!
Чем больше я смотрю в современные типовые тем чаще думаю о смене видя деятельности. Надоело уже это адское мучине — сидеть и исследовать стек вызовов по 30 процедур. Чтобы сделать документ с поведением счета и субконто как в типовых — надо скопировать пол-бухгалтерии общих модулей. А поведение контролируется сразу тремя способами — свойствами полей документа, кодом и условным оформлением.
1С сделала «поворот не туда». И потом повторила 100500 раз. Да. Методологи у нее слабоватенькие. Архитектура никуда не годится.