Закупочная цена в списке цен подбора

Клиент поставил задачу — вывести цену последнего прихода в список цен, который показывается по ПКМ в списке подбора товара в чек ККМ (или расходную накладную):

Отладчиком нашел, куда переходит программа по нажатию кнопки «Цены»:

Спустился чуть ниже по стеку вызовов:

Нашел, какая форма вызывается и показывает цены: Обработка.ПодборТоваровВДокументПродажи.Форма.ЦеныНоменклатуры.

Добавил эту форму в расширение.

В самой форме добавил числовой реквизит ПоследняяЦенаПрихода, разместил его на форме:

Нашел в конфигурации код по расчету средней цены закупа, преобразовал его в код по получению последней закупочной цены. Оформил в виде функции на тот случай, если понадобится еще где получать эту цену. После сдачи клиенту обнаружил ошибку — получал не последнюю, а первую цену. Добавил в запрос Убыв.

Некоторое время протупил, т.к. конструктор ругался на поле Сумма, как будто оно не числовое:

Потом до меня дошло, что этот запрос расположен в расширении. Проверил запрос в консоли — компилируется нормально.

Итоговая форма получилась такая:

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

Вот код решения:

&НаСервере
Процедура дор_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
   
//Осипов 2021-04-06
   
ПоследняяЦенаПрихода = ПолучитьПоследнююЗакупочнуюЦену(Параметры.Номенклатура);

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

Функция
ПолучитьПоследнююЗакупочнуюЦену(Номенклатура)

   
Запрос = Новый Запрос;
   
Запрос.Текст =
   
«ВЫБРАТЬ ПЕРВЫЕ 1
    |   ВЫБОР
    |       КОГДА Т.Количество = 0
    |           ТОГДА 0
    |       ИНАЧЕ Т.Сумма / Т.Количество
    |   КОНЕЦ КАК Цена
    |ИЗ
    |   РегистрНакопления.Закупки КАК Т
    |ГДЕ
    |   Т.АналитикаУчетаНоменклатуры.Номенклатура = &НоменклатураЗапроса
    |
    |УПОРЯДОЧИТЬ ПО
    |   Т.Период Убыв»
;

   
Запрос.УстановитьПараметр(«НоменклатураЗапроса», Номенклатура);


   
Выборка = Запрос.Выполнить().Выбрать();
    Если
Выборка.Следующий() Тогда
        Возврат
Выборка.Цена;
    КонецЕсли;
    Возврат
0;
КонецФункции

Время факт: 0.5 час.

fixin

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

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

комментариев 14

  1. fajij28770:

    чего-то не понял, а что такого сложного добавить новую строку в табличный виджет, который уже существует в форме? ну в любой UI системе, с которыми я встречался, сделать это гораздо проще, чем создавать новый виджет (про эстетичность такого решения в рамках задачи промолчу).

    • naf2000:

      Потому что надо было подправить источник данных. То есть запрос динамического списка.

      • fajij28770:

        и в чем проблема? через union дописал бы свой запрос на вычисление последней закупочный цены в запрос динамического списка и все, профит. и не надо городить новые сущности (у клиента, кстати, есть понимание этого)

        • Программист 1С должен всегда думать о последующем сопровождении задачи. Возможно, конечно, что 1С не будет менять текст динамического списка в этой форме, но как-то рисковано…

    • ну раз не видите ничего сложного, расскажите как. Приведите пример, так сказать.
      Кстати, налицо сложность разработки форм в системах Не-1С.
      В 1С новый элемент разместить и привязать к данным как два байта переслать.

      • fajij28770:

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

        • Менять текст динамического списка более опасно с точки зрения обновления конфигураций, чем добавление нового изолированного поля.
          Хотя конкретно в данном случае вряд ли что-то поменяется, но все же это уже практика — не трогать больше, чем нужно.

          • fajij28770:

            Что-то не пойму, в чем опасность дописывания запроса, если у тебя есть доступ к исходному коду?

            Опять-таки, это лишь одно из возможных решений. В нормальных системах задачу можно решить множеством способов без добавления костыля с новым полем:
            1. Если есть доступ к исходному коду — то просто дописать юнион в запрос. Быстро и просто.
            2. Унаследовать модель и добавить данные туда, потом в своей форме заиспользовать эту модель. Глобальное и надежное решение, не нужен доступ к коду, не зависим от запроса в базовой модели. Но есть одно но — исходная задача должна быть решена в терминах Model-View и сама система должна поддерживать такой подход
            3. Если нет разделения по Model-View и нет доступа к коду, то можно унаследоваться от самой формы, переопределить какой-нибудь хук (show, например), и там уже лениво сделать запрос к БД и дописать в табличный виджет на форме.

            Непонятно, почему у вас там в 1с так сложно решить такую простую задачу

          • Стоимость решения с полем на форме дешевле стоимости решения с юнионом, на мой взгляд.
            И опасности того, что 1С поменяет динамический список, тоже меньше.
            Поэтому принято такое решение.

            Доступ есть, но надо думать о тех, кто придет после меня. Если 1С поменяет код списка, решение с UNION перестанет работать, а с полем ввода — останется. Это экономия денег клиента на сопровождение.

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

          • Павел:

            Пункты 2 и 3 в 1с не реализуемы. Банально в 1с специфичное наследование. Есть абстрактный класс Документ, все документы наследуемые от него изолированные. Ттже самое с другими объектами

          • fajij28770:

            здесь очевидный «immolate improved» и вероятность такого события крайне мала

          • Но ненулевая

      • Павел:

        Тут «не-1с» вообще нет — откуда взялась мысль про сложность? Сложность как раз в 1с

Добавить комментарий

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