Базовый курс. Домашнее задание №8

2-ое задание по второму блоку базового курса.

Для выполнения рекомендуется изучить следующие главы 2-го блока.
Глава 4. Настройка форм документов.
Глава 5. Журналы документов.
Глава 6. Настройка командного интерфейса.
Глава 7. Регистры.
Глава 8. Регистры накопления.
Глава 9. Регистры сведений.
Глава 10. Настройка форм.

К сожалению, у Вас недостаточно прав для просмотра этой записи. Если Вы еще не залогинены на сайте — залогиньтесь. Если Вы оплачивали курс, у Вас активирован токен доступа, Вы залогинены, но Вы видите эту запись — напишите нам на e-mail поддержки.

комментария 92 на “Базовый курс. Домашнее задание №8”

  1. ДЗ №8 выполнил.
    Основные трудности, вернее даже не трудности, а неоднозначность  понимания – с трактовкой самого задания… Ну может это и к лучшему, т.к. сначала делаю по-своему, а потом  часто переделываю так как рекомендовано у вас в решени – т.е. решаю одну задачу дважды…
    Постараюсь за праздники догнать группу.

  2. Задание выполнил, все небыло времени отписаться…
    При первом выполнении основные сложности испытал на реализации пересчета при изменении Суммы.  После просмотра решения пришлось все переделать т.к. Куча дублируемого кода, и ошибок в движениях при проведении по регистрам, в частности не приводил единицу к базовой…

  3. Задание выполнено, но только потому, что во время выполнения смотрела эталонное решение. Долго не могла решить какими объектами реализовать “привязку менеджеров” и хранение цен, потом решила “подсматривать”  :)) Очень непривычно использовать регистр сведений вместо периодич. реквизитов. С движениями по регистрам  понятно, в уроках все подробно рассказано. Спасибо.

  4. comradeegor 23.12.2010 в 00:17

    Задание выполнил.
    Привязку менеджеров к клиентам сделал с помощью независимого регистра сведений “МенеджерыКлиентов”. Периодичность: В пределах дня.
    Измерение: Контрагент, Ресурс: Менеджер.
    При проведении документа “КонтактСКлиентом” брал срез последних из р.с. с отбором по контрагенту. Если результат запроса – пустой, то значит это первый контакт и требуется добавить запись в р.с.
    Пробовал через набор и через менеджер записи. Через менеджер в данном случае конечно гораздо удобней. Набором записи я так понимаю лучше пользоваться тогда, когда мы хотим перезаписать какой-то набор из р.с. Для добавления записей лучше использовать менеджер, мне кажется.
    Для хранения прайсов был создан независимый регистр сведений “ПрайсЛист” с периодичностью в пределах дня.
    Измерения: Номенклатура, ВидЦены (Тип – Перечисления.ВидыНоменклатуры)
    Реализация юзабилити документов поступления ТМЦ проблем не вызвала.
    Был создан регистр накопления “ОстаткиНоменклатуры” типа “Остатки”.
    Измерения: Номенклатура, Качество
    Ресурсы: Количество
    Регистраторы: ПоступлениеТоваров, АвансовыйОтчет
    Был создан регистр накопления “ОстаткиНоменклатуры” типа “Остатки”.
    Измерения: Номенклатура, Качество
    Ресурсы: Количество
    Регистраторы: ПоступлениеТоваров, АвансовыйОтчет
    Был создан регистр накопления “ЗакупкиПоставщиков” типа “Обороты”.
    Измерения: Номенклатура, Контрагент
    Ресурсы: Количество, Сумма
    Регистраторы: ПоступлениеТоваров
    Для чего нужен “ЗакупкиПоставщиков” я пока не сообразил, поэтому получилось пока как-то так. По минимуму.
    Обработку проведения создал для одного документа с помощью конструктора движений, после чего вынес в общий модуль.
    Так избежал дублирования кода.
    Проверка изменения базовой ед. изм. не вызвала затруднений. Реализовал схематично так:
    В модуле формы при изменении реквизита “БазоваяЕдиница”
    СтараяБазЕдиница = СтараяБазЕдиница(Объект.Ссылка);
    Если Объект.БазоваяЕдиница <> СтараяБазЕдиница И БылиДвижения(Объект.Ссылка) Тогда

    БылиДвижения – серверная процедура МФ (без контекста) обращается к таблицам движений регистров “ОстаткиНоменклатуры”  и “ЗакупкиПоставщиков”  с отбором по номенклатуре. Результаты запросов объединяет.
    Возвращает НЕ Результат.Пустой()
    Общее ощущение – задания становятся сложнее и объемнее. Иногда приходится обращаться к материалам видео-лекций.
    Постоянно приходится задумываться о контексте и доступных объектах.
    Задание выполнил.Привязку менеджеров к клиентам сделал с помощью независимого регистра сведений “МенеджерыКлиентов”. Периодичность: В пределах дня.Измерение: Контрагент, Ресурс: Менеджер.
    При проведении документа “КонтактСКлиентом” брал срез последних из р.с. с отбором по контрагенту. Если результат запроса – пустой, то значит это первый контакт и требуется добавить запись в р.с.Пробовал через набор и через менеджер записи. Через менеджер в данном случае конечно гораздо удобней. Набором записи я так понимаю лучше пользоваться тогда, когда мы хотим перезаписать какой-то набор из р.с. Для добавления записей лучше использовать менеджер, мне кажется.
    Для хранения прайсов был создан независимый регистр сведений “ПрайсЛист” с периодичностью в пределах дня. Измерения: Номенклатура, ВидЦены (Тип – Перечисления.ВидыНоменклатуры)
    Реализация юзабилити документов поступления ТМЦ проблем не вызвала.
    Был создан регистр накопления “ОстаткиНоменклатуры” типа “Остатки”. Измерения: Номенклатура, КачествоРесурсы: КоличествоРегистраторы: ПоступлениеТоваров, АвансовыйОтчет
    Был создан регистр накопления “ОстаткиНоменклатуры” типа “Остатки”. Измерения: Номенклатура, КачествоРесурсы: КоличествоРегистраторы: ПоступлениеТоваров, АвансовыйОтчет
    Был создан регистр накопления “ЗакупкиПоставщиков” типа “Обороты”. Измерения: Номенклатура, КонтрагентРесурсы: Количество, СуммаРегистраторы: ПоступлениеТоваров
    Для чего нужен “ЗакупкиПоставщиков” я пока не сообразил, поэтому получилось пока как-то так. По минимуму.
    Обработку проведения создал для одного документа с помощью конструктора движений, после чего вынес в общий модуль.Так избежал дублирования кода.
    Проверка изменения базовой ед. изм. не вызвала затруднений. Реализовал схематично так:
    В модуле формы при изменении реквизита “БазоваяЕдиница” СтараяБазЕдиница = СтараяБазЕдиница(Объект.Ссылка);Если Объект.БазоваяЕдиница <> СтараяБазЕдиница И БылиДвижения(Объект.Ссылка) Тогда…
    БылиДвижения – серверная процедура МФ (без контекста) обращается к таблицам движений регистров “ОстаткиНоменклатуры”  и “ЗакупкиПоставщиков”  с отбором по номенклатуре. Результаты запросов объединяет.Возвращает НЕ Результат.Пустой()
    Общее ощущение – задания становятся сложнее и объемнее. Иногда приходится обращаться к материалам видео-лекций.Постоянно приходится задумываться о контексте и доступных объектах.

  5. Задание выполнил. С сложностями разобрался, помогло решение преподавателя и  повторные просмотры уроков.

  6. Задание выполнила.  Все вполне понятно как реализовывать.

  7. Manase940N 15.12.2010 в 09:23

    Задание выполнил.  Сложности возникли при проверке движений по номенклатуре при использовании объектной модели, пришлось пересматривать уроки).

  8. Антон К. 13.12.2010 в 12:33

    Добрый день, задание выполнил.
    Возникли следующие сложности, которые я обошел, изменив реализацию (но понять, как можно было выполнить первоначальный вариант, все равно хочу):
    1) менеджеров для контрагентов я реализовал через независимый периодический регистр сведений (период = день), хотя по условию задачи можно было обойтись и непериодическим РС.
    Сложности:
    1.1.) не понял как замещать записи в пределах дня. мое решение: читаю набор записей (НЗ.Прочитать()), и если есть запись за текущий день, я ее просто изменяю и записываю набор записей.
    1.2.) хотел на форме контрагента отобразить историю менеджеров данного контрагента с возможностью добавления. начал делать через дополнительный реквизит формы ДинамическийСписок. не смог установить отбор по контрагенту.
    В итоге отказался от списка, сделал реквизит формы СправочникСсылка.Сотрудник, который заполняю в событии формы ПриСозданииНаСервере значением из виртуальной таблицы РС СрезПоследних. В момент записи контрагента проверяю, и если менеджер изменен – записываю его в РС.
    2) По ТипуЦен – сделал справочник ТипыЦен. Добавил документ УстановкаЦенНоменклатуры, который записывает цены в периодический РС ЦеныНомеклатуры (периодичность в пределах секунды). РС ЦеныНоменклатуры заполняется только документом УстановкаЦенНоменклатуры. Во все товарные документы вывел реквизит ТипЦен.
    При изменении значения  ТипаЦен я обновляю цены в уже введенных в данный документ строках с товарами.
    2.1.) Сложность возникла с тем, что на сервер в процедуру с опцией компиляции НаСервереБезКонтекста надо передать табличную часть документа и потом ее вернуть на клиента с заполненными ценами. Не смог сделать. Изменил опцию компиляции на НаСервере и в процедуре напрямую работаю с основным реквизитом формы.
    2.2.) Решил вынести обновление цен в серверный Общий серверный модуль, чтобы не дублировать код в модулях форм. В серверный Общий модуль в качестве параметра передаю основной реквизит формы документа (ДокументОбъект). В серверном модуле делаю преобразование с помощью ДанныеФормыВЗначение() – получаю ошибку “нельзя изменять реквизит формы Объект” – как ее побороть не понимаю. В итоге у меня сейчас в модулях форм всех товарных документов один и тот же код, который не удалось вынести в серверный общий модуль.
    2.3.) подстановку цен и базовых единиц измерения при выборе номенклатуры, а также пересчет суммы при изменении количества или цены (и наоборот) вынес в клиентский Общий модуль. Данная процедура базируется на том, что имена табличных частей и реквизитов у товарных документов одинаковые: таб.часть Товары, реквизиты: Номенклатура,  ЕдИзмерения, Цена, Количество, Сумма.
    ====
    Больше сложностей в реализации не возникло. Евгений, хотелось бы увидеть от Вас комментарий относительно возникших сложностей (можно в виде ссылок на ролики, где объясняется решение – может я пропустил или забыл – видео обычно смотрю после 23:00 =)

    • Антон К. 13.12.2010 в 13:50

      По поводу пункта 2.2.) Я вынес таки общий код в общий серверный модуль. Но вызываю функцию в общем серверном модуле не из Клиентской процедуры модуля формы (как было до этого, когда я писал о сложностях), а из серверной (опция &НаСервере) процедуры, в которой я делаю преобразования ДанныеФормыВЗначение и ЗначениеВДанныеФормы.
      При этом интересный момент: если я из серверного модуля формы передаю это значение в функцию в серверном общем модуле как ссылку (Документ.Ссылка), то я теряю незаписанные изменения в передаваемом документе, поэтому передаю в качестве параметра ДокументОбъект.

      • > Я вынес таки общий код в общий серверный модуль.
        Такое решение допустимо. По сути у вас делается контекстный серверный вызов, а далее идете в общий модуль. Все ок.
        > то я теряю незаписанные изменения в передаваемом документе
        Это верное поведение. Ведь данные полученные через ссылку – это информация из БД. Поэтому для работы с данными документа нужно обращаться к данным формы.

    • >хотя по условию задачи можно было обойтись и непериодическим РС.
      Разве в условии указывается непериодический РС?
      >не понял как замещать записи в пределах дня
      Можно было использовать параметр метода Записать()
      >не смог установить отбор по контрагенту.
      Можно было применить метод УстановитьЗначениеПараметра() динамического списка, который доступен даже на клиенте.
      > Изменил опцию компиляции на НаСервере и в процедуре напрямую работаю с основным реквизитом формы.
      На самом деле с табличной частью работать эффективнее именно в контекстном серверном вызове. Мы этот эффект рассматриваем в продвинутом курсе.
      >В итоге у меня сейчас в модулях форм всех товарных документов один и тот же код, который не удалось вынести в серверный общий модуль.
      Действительно, данные формы нельзя передавать в процедуры. А вернее их нельзя изменять присваиваем.
      Поэтому правильный вариант – передача текущих данных в методы общих модулей.

      В видео-решении рассматриваются эти и другие интересные особенности. Так что смотрите :)

      • Антон К. 13.12.2010 в 14:39

        >> не понял как замещать записи в пределах дня
        > Можно было использовать параметр метода Записать()
        Если не делать НаборЗаписей.Прочитать() то затирается содержимое регистра сведений.
        Если делаю НаборЗаписей.Прочитать() и добавляю новую запись, то при Записать() получаю ошибку – запись не уникальна (в пределах дня), поэтому в прочитанном наборе записей сначала ищу существующую, где период = текущий день, и создаю новую только если существующей записи нет.

        • Нужно еще отбор по периоду использовать, тогда не должен затираться.

          • Антон К. 13.12.2010 в 17:07

            Бинго! ;-) Как говорит мой коллега: “Тупняк напал”
            Спасибо

          • Антон К. 14.12.2010 в 00:34

            Стоп-стоп. посмотрите, пожалуйста, код:
            НЗ = РегистрыСведений.МенеджерыКонтрагентов.СоздатьНаборЗаписей();
              НЗ.Отбор.Контрагент.Значение = Объект.Ссылка;
              НЗ.Отбор.Период.Значение = ТекущаяДата();
              НЗ.Прочитать();
              Запись = НЗ.Добавить();
              Запись.Контрагент = Объект.Ссылка;
              Запись.Период = ТекущаяДата();
              Запись.Менеджер = Менеджер;  
              НЗ.Записать();

            В данном случае получаю ошибку неуникальности записи в пределах дня. А если не делать НЗ.Прочитать(), то теряю все содержимое РС.
            Не получается без анализа прочитанного набора записей.

            • Давайте попробуем все же установить отбор.
              То есть:
              НЗ.Отбор.Контрагент.Использование = Истина;
              НЗ.Отбор.Период.Использование = Истина;
              Или применяйте метод
              УстановитьЗначение().

              • Антон К. 14.12.2010 в 23:22

                Спасибо, теперь все работает и без НЗ.Прочитать()
                 – текущую запись замещает

  9. Задание выполнил. Для хранения менеджеров созан РС МенеджерыКонтрагентов (Периодичность – День, Измерение – Контрагент, Ресурс – Менеджер). Для хранения остатков товаров создан РН Товары (Измерения – Номенклатура, Качество, Ресурс – Количество). Для хранения закупок создан РН Закупки (Измерения – Номенклатура, Контрагент, Ресурсы – Количество, Стоимость).

  10. Задание выполнил. Для выполнения задания добавил в конфигурацию справочник Прайс (где указываю тип цен), в документ КонтактыСКонтрагентами добавил реквизит менеджер (который по умолчанию заполняется при вводе нового документа параметрами текущего пользователя), справочник Должность (где хранится контактное лицо и должность) сделал подчиненным спраочнику мКонтрагенты, в документ мРеализацияТоваров и мПоступлениеТоваров добавил реквизит Прайс (на основании которого находится значение цены для соответствующего товара). Реквизит КонтактноеЛицоДолжность документа мРеализацияТоваров связал через параметр выбора со справочником мКонтрагенты. Создал регистр накопления мОстаткиТоваров (вид остатки) с измерениями Номенклатура и Брак, и ресурсом Количество (для отслеживания остатков товара), и регистр накопления Закупки (оборотный регистр) с измерением Контрагент и ресурсом Сумма (для хранения закупок от контрагентов). Измерения Номенклатура и Контрагенты соответствующих регистров сделал обязательными для заполнения. Создал регистр сведений МенеджерыКонтрагента с измерением Контрагент и Ресурсом Менеджер. 
    Регистр сведений мЦеныНоменклатуры, с измерениями Номенклатура (тип Справочник.ССылкамНоменклатура) и Прайс(тип СправочникСсылка.Прайс) и измерением Цена. Кроме этого завел константу ПриИзмененииСуммыРасчитыватьЦену (тип булево) на основании которой выбирается что расчитывается при изменении суммы. Если значение истина тогда ТД.Цена = ТД.Сумма/ТД.Количество (т.е. расчитываю цену на 
    основании количества), в противном случае ТД.Количество = ТД.Сумма/ТД.Цена;. В принципе про изменение структуры все.
    Теперь о трудностях которые были при реализации. Все сделал в основном все с использованием объектной модели доступа, хоть и сложнее чем запросом но с запросом как я понял работать будем дальше. В принципе все понятно и затруднений не вызвало но интересует 2 момента. 
    1) При изменении базовой единицы измерения в справочнике мНоменклатуры должен запретить изменения если по
    данной номенклатуре были проведенные документы. Хотел сначала использовать РегистрСведений с измерением Номенклатура который будет записываться при проведении документа, но потом решил что проще будет просто проверять наличие оборотов. Сделал так в модуле объекта<code> 
    Процедура ПередЗаписью(Отказ)
    если БазоваяЕдиница<>Ссылка.БазоваяЕдиница тогда
    Отбор = Новый Структура(“Номенклатура”,Ссылка);
    ТабОборотов = РегистрыНакопления.мОстаткиТоваров.Обороты(,, Отбор,”Номенклатура”, “Количество”);
    если ТабОборотов.Количество()>0 тогда
    отказ = Истина;
    КонецЕсли;
    КонецЕсли;
    КонецПроцедуры
    </code> Правильно ли я делую проверку на изменение БазовойЕдиницы (если БазоваяЕдиница<>Ссылка.БазоваяЕдиница тогда)? Или это лишнее обращение к БД и это методологически неверно? Кстати потом подумал и решил а если у меня оборот будет = 0 (т.е. приход=расходу), то надежнее сделать так <code> 
    Процедура ПередЗаписью(Отказ)
    если БазоваяЕдиница<>Ссылка.БазоваяЕдиница тогда
    отказ = ЗаполнениеДокументов.ПроверкаОборотовПоТовару(Ссылка);
    КонецЕсли;
    КонецПроцедуры
    //////////////////////// Общий модуль ЗаполнениеДокументов
    Функция ПроверкаОборотовПоТовару(Товар) Экспорт
    выход = Ложь;
    Запрос = Новый Запрос;
    Запрос.Текст =
    “ВЫБРАТЬ ПЕРВЫЕ 1
    | мОстаткиТоваров.Регистратор
    |ИЗ
    | РегистрНакопления.мОстаткиТоваров КАК мОстаткиТоваров
    |ГДЕ
    | мОстаткиТоваров.Номенклатура = &Номенклатура”;
    Запрос.УстановитьПараметр(“Номенклатура”, Товар);
    Результат = Запрос.Выполнить();
    ВыборкаДетальныеЗаписи = Результат.Выбрать();
    Если ВыборкаДетальныеЗаписи.Следующий() Тогда 
    выход = Истина;
    КонецЕсли;
    возврат выход;
    КонецФункции // ПроверкаОборотовПоТовару()
    </code> Ведь тут я просто беру первыую попавшую ссылку по которой прошло движение. 
    2) Также возник вопорос по работу с РегистромСведений через НаборЗаписей. Сотрел видео и на основании его сделал такой код, который проверяет есть ли регистр с такими измерениями. <code>
    Процедура ОбработкаПроведения(Отказ, РежимПроведения)
    Набор =РегистрыСведений.МенеджерыКонтрагента.СоздатьНаборЗаписей();
    Набор.Отбор.Контрагент.Значение = Контрагент;
    Набор.Прочитать();
    если Набор.Количество()=0 тогда // если первый контакт был и менеджер есть то ничего не меняем
    Запись = Набор.Добавить();
    Запись.Контрагент = Контрагент;
    Запись.Период = Дата;
    Запись.Менеджер = Менеджер;
    Набор.Записать();
    конецЕсли;
    КонецПроцедуры
    </code> Запустил и он уменя все время возвращает полный набор записей по данному регистру сведений, по всем измерениям. Но мне то нужны только измерения которые отражаются в конкретном наборе. короче пока не подставил в этот код строчку <code> Набор.Отбор.Контрагент.Использование = Истина; </code> смысла в том что я каким то образом инициировал отбор не было никакого. Может оно (использование отбора) гдето инициируется глобально и при заполнении свойства Отбор устанавливается автоматически?
    Кстати очень понравился видеоурок где текст запроса меняется с помощью функции замены строк (вроде все просто но я никогда так не делал), т.е. примочка которая на порядок облегчит жизнь при разработке. А так же где рассматриваются заранее ошибочные варианты решения задач. Побольше бы таких!!!

    • >Все сделал в основном все с использованием объектной модели доступа, хоть и сложнее чем запросом но с запросом как я понял работать будем дальше
      Сейчас и всегда нужно стараться использовать запрос, вместе объектной техники.
      >Правильно ли я делую проверку на изменение БазовойЕдиницы (если БазоваяЕдиницаСсылка.БазоваяЕдиница тогда)?
      Правильно. От обращения в БД здесь не уйти.
      >Ведь тут я просто беру первыую попавшую ссылку по которой прошло движение.
      Вот этот вариант правильный.
      > Может оно (использование отбора) гдето инициируется глобально и при заполнении свойства Отбор устанавливается автоматически?
      Отбор устанавливается в два этапа: сначала указывается значение, потом ставится флажок использование. Оба условия необходимы для наложения отбора.
      Однако, есть метод Установить(), который может оба шага сделать одновременно. Например, так Набор.Отбор.Контрагент.Установить(ВашеЗначение);

      > Побольше бы таких!!!
      Ок :)

  11. Вячеслав Вязигин 12.12.2010 в 19:38

    Задание выполнено. Затруднений не возникло.

  12. Евгений Шилов 12.12.2010 в 18:16

    Задание выполнил.
    При создании нового документа “КонтактСКлиентом” заполняю менеджера в процедуре формы “ПриСозданииНаСервере”. Анализ на первый контакт и создание записей в регистре “МенеджерыКонтрагентов” провожу в процедуре “Обработка проведения”.
    Общее поведение форм документтов ТМЦ вынес в общий модуль.
    Для журнала “Документы Закупки” создал реквизит сумма в каждом документе закупки, который заполняется при смене цены, количестве в табличной части.
    При выполнении стандартных действий при изменении цены, количества сильно не хватает возможности передать всю строку в общий модуль, где и проводить все изменения.Скажите, как можно этого добиться? Модуль у меня серверный.
     

    • Можно передавать ТекущиеДанные в клиентский модуль, а из него делать серверный вызов.

      • Евгений Шилов 12.12.2010 в 23:31

        Прежде чем задать вопрос, стоит посмотреть решение преподавателя :)

  13. Sergey.Volkov 12.12.2010 в 16:37

    Связь Клиентов с Менеджерами с учетом времени навела на мысль о необходимости периодического регистра с измерением КОнтрагент и ресурсом Менеджер.
    В документе КонтактСКонтрагентами создал реквизиты Менеджер и КОнтрагент. Установил для КонтактногоЛица связь по владельцу с Контрагентом.
    Автоматическую подстановку текущего пользователя в реквизит Менеджер реализовал в ОбработкаЗаполнения(), функцию получения пользователя взял из прошлых заданий.
    Сделал реквизиты Менеджер и Контрагент обязательными путем установки проверки заполнения “Выдаавть ошибку”.
    Перед записью в регистр ищу в нем запись с данным КОнтрагентом с помощью запроса к регистру МенеджерыКонтрагенты, в который передаю контрагента как параметр.
    Для цен товаров создал периодический регистр сведений Цены с ресурсов Цена и измерениями Товар,ПрайсЛист (ПрайсЛист – ссылка на справочник видов цены). В обоих документах реализовал автоподстановку цены при выборе Прайслиста в обработчике ПриИзменении() реквизита документа.
    Перерасчет суммы документов вызываю в клиентских обработчиках ПриИзменении() соответствующих реквизитов.
    Пересчет единиц измерения сделал с помощью константы.
    Создал регистр ОстаткиТоваров и регистр ЗакупкиТоваров. Запись в регистры сделал в цикле.
    Проверка изменения базовой единицы измерения – в ОбработкаПроверкиЗаполнения() модуля справочника Номенклатура с помощью запроса, проверяющего есть ли в регистре записи с определенной номенклатурой.
    Создал журнал документов. Не нашел способа вывести сумму документа.

    • >Не нашел способа вывести сумму документа.
      Создать реквизит документа. Смотрите решение :)

  14. tatianalma 12.12.2010 в 16:01

    Задание сделала.
    Создала регистр сведений для хранения менеджеров контрагентов. Измерение Контрагент ведущее, чтобы удобно заполнялось по ссылке из контрагента.
    Менеджер при создании документа Контакты заполняется в ОбработкеЗаполнения:
                Если ДанныеЗаполнения = Неопределено тогда
                            Менеджер=Справочники.Пользователи.НайтиПоНаименованию(ИмяПользователя());
                КонецЕсли;
    ********
    Заполнение записи регистра сведений при первом контакте:
    Процедура ОбработкаПроведения(Отказ, РежимПроведения)
                Отбор = Новый Структура(“Контрагент”, Контрагент);
                Если РегистрыСведений.РСМенеджер.СрезПоследних(, Отбор).Количество() = 0 Тогда
                            НЗ=РегистрыСведений.РСМенеджер.СоздатьНаборЗаписей();
                            НЗ.Отбор.Контрагент.Значение = Контрагент;
                            НЗ.Отбор.Период.Значение = Дата;
                            НЗ.Прочитать();
                            Запись = НЗ.Добавить();
                            Запись.Контрагент = Контрагент;
                            Запись.Менеджер = Менеджер;
                            Запись.Период = Дата;
                            НЗ.Записать();
                КонецЕсли;  
    КонецПроцедуры
    ***********
    Обнаружила, что все работает, но если потом попытаться удалить созданную запись из регистра вручную, оно не дает, пишет ошибка блокировки объекта.  Причем пробовала ее создавать и через МенеджерЗаписи, и если через МенеджерНабораЗаписей – одинаково. Если выйти из программы и снова зайти, запись можно удалить, но это не выход. Почему так происходит и как отпустить блокировку?
     
    Для хранения цен создан регистр сведений ЦеныНоменклатуры, независимый, с периодичностью в день. Для выбора типа цен – справочник ТипыЦен.
    С расчетом итогов и цен проблем не возникло. Более менее вынесла функции в клиентский и серверный общие модули.
    Для журнала завела в документах реквизит шапки Сумма, куда перед записью сохраняется итог по сумме.
    Созданы регистры накопления ОстаткиТовара и Закупки, первый – остаточный, второй -оборотный. Для того чтобы при проведении не лазить на сервер, в табличную часть документов добавлен реквизит табличной части К, равный 1 если выбрана базовая единица, и куда автоматически записывается коэффициент пересчета в базовую, если нет. Проведение хорошо создается конструктором движений, руками только умножение на коэффициент.
    Проверка на наличие движений при смене базовой единицы делается запросом в процедуре ПередЗаписью:
    Запрос = Новый Запрос;
                Запрос.Текст =
                            “ВЫБРАТЬ
                            |           ОстаткиТовара.МоментВремени
                            |ИЗ
                            |           РегистрНакопления.ОстаткиТовара КАК ОстаткиТовара
                            |ГДЕ
                            |           ОстаткиТовара.Номенклатура.Ссылка = &Ссылка”;
     
                Запрос.УстановитьПараметр(“Ссылка”, ЭтотОбъект.Ссылка);
     
                Результат = Запрос.Выполнить();
     
                Выборка = Результат.Выбрать();
     
                Если Выборка.Следующий() тогда
                            Сообщить(“Нельзя изменять базовую единицу, т.к. по ней уже были движения!”);
                            Отказ=Истина;
                КонецЕсли;
    *********
    Еще один вопрос, если можно: Хотелось сделать проверку движений по базовой в модуле формы, при изменении реквизита, но не нашла, как в этом месте можно отказаться от смены. Теоретически можно залезть на сервер, взять сохраненное оттуда, но должно быть что-то чтобы просто отказаться менять и вернуть то, что было на форме до, аналог СтатусВозврата(0)?

    • >Почему так происходит и как отпустить блокировку?
      Достаточно интересное поведение с блокировкой.
      Вставил ваш код. Провел документ, потом без проблем удалил запись регистра.
      Может быть дело в том, что у вас интерактивна открыта форма записи регистра?
      Проверьте еще раз на своей базе.
      И если ошибка повторяется, то приведите дословный текст ошибки.
      >что было на форме до, аналог СтатусВозврата(0)
      Если я понял, речь идет о контроле изменения единицы в форме справочника Номенклатура.
      Штатных средств по отмене выбранного значения нет.
      Однако можно использовать следующий подход:
      1. Сохранять “старое” значение в клиентской переменной модуля формы. Изначально делать инициализацию в обработчике ПриОткрытии() формы.
      2. В случае если изменение недопустимо, “откатиться” назад до значения клиентской переменной.
      3. При каждом изменении единицы обновлять значение переменной.

      • tatianalma 13.12.2010 в 15:27

        Большое спасибо, Евгений! Про изменение реквизита все поняла.
         
        Про ошибку с блокировкой: Действительно, если в текущем сеансе не было обращения к форме списка регистра, а сначала провожу документ, а потом лезу в регистр, запись удаляется. А вот если сначала зайти в регистр, там что-то создать/удалить, а потом провести документ, появляются заблокированные записи. Открытых форм записей нет, а само окно списка регистра ведь нельзя закрыть, можно только переключиться в другое.(или я не права?) Я еще немного протестировала: если в регистре одна запись, блокируется она, если их несколько, то один раз оно даже заблокировало после проведения документа не созданную им запись, она удалилась, а другую, на другую фирму, а при повторном проведении того же документа заблокированными оказались обе записи… (их всего две на этот момент в регистре) А в другом случае созданная запись заблокирована, другая удаляется, может потому что в этом случае другая запись была создана не в текущем сеансе. На изменение форму заблокированной записи открывает, но при прикосновении к любому реквизиту выдает ту же ошибку. Текст ошибки:
         
        Ошибка блокировки объекта. Объект уже заблокирован.
        компьютер: TOSHIBA, пользователь: Администратор, сеанс 6, начат 13.12.2010 в 14:46:17, приложение: Тонкий клиент  
         
        Релиз: 8.2.12.80
         
        Не знаю стоит ли это траты Вашего времени, но вот такой неадекват :)

        • У меня ошибка с блокировкой все равно не воспроизводится.
          Во-первых, можно обновится на последний релиз платформы (13.202) и проверить поведение на нем.
          Если блокировка будет повторятся, то можно будет прислать мне базу и способ воспроизведения.
          Я разберусь :)

          • tatianalma 14.12.2010 в 15:03

            >Я разберусь :)
            Не сомневаюсь! :)
            У меня пока нет дистрибутива нового релиза.  Но я его добуду. Если ошибка останется после обновления, я Вам напишу.
            Спасибо!

            • tatianalma 15.12.2010 в 22:11

              Поставила 13.202 – ошибка пропала. О, чудо! :)

  15. Задание выполнено.
    Созданы следующие объекты:
    1. Независимый периодический регистр сведений “МенеджерыПоКонтрагентам”. Измерение “Контрагент”, тип “СправочникСсылка.Контрагенты”, установлено свойство “Запрет незаполненных значений”, “Проверка заполнения” установлено в “Выдавать ошибку”; ресурс “Менеджер”, тип “СправочникСсылка.Пользователи”.
    2. Справочник “ПрайсЛисты”.
    3. Независимый периодический регистр сведений “ЦеныНоменклатуры”. Измерение “Товар”, тип “СправочникСсылка.Номенклатура”, установлено свойство “Запрет незаполненных значений”, “Проверка заполнения” установлено в “Выдавать ошибку”; измерение “ПрайсЛист”, тип “СправочникСсылка.ПрайсЛисты”; ресурс “Цена”, тип “Число”.
    4. Регистр накопления (вид регистра – остатки) “ОстаткиТоваров”. Измерение “Товар”, тип “СправочникСсылка.Номенклатура” (проверяется заполнение); измерение “СтепеньБрака”, тип “СправочникСсылка.СтепениБрака”; ресурс “Количество”, тип “Число”.
    5. Регистр накопления (вид регистра – обороты) “ЗакупкиТоваров”. Измерение “Товар”, тип “СправочникСсылка.Номенклатура” (проверяется заполнение); измерение “Поставщик”, тип “СправочникСсылка.Контрагент” (проверяется заполнение); ресурс “Количество”, тип “Число”; ресурс “Сумма”, тип “Число”.
    6. Константа “ПересчетЦеныПриИзмененииСуммы”, тип “Булево”.
    7. Журнал документов “Документы закупки”. Графы “Контрагент” и “Сумма”. У соответствующих документов добавлены реквизиты шапки “СуммаДок” для вывода в журнале документов.
    В документе “КонтактСКлиентами” добавлены реквизиты “Контрагент”, тип “СправочникСсылка.Контрагенты” и “Менеждер”, тип “СправочникСсылка.Пользователи”. Создана связь параметров выбора для контактного лица (по контрагенту). В процедуре “ОбработкаЗаполнения” модуля объекта происходит заполнение реквизита “Менеджер” по умолчанию текущим пользователем. В процедуре “ОбработкаПроведения” осуществляется проверка на существование менеждера для текущего контрагента. Если такового нет – создаем запись в регистре сведений “МенеджерыПоКонтрагентам”.
    Для документов отгрузки и закупки создан реквизит “ПрайсЛист”, тип “СправочникСсылка.ПрайсЛисты”. Для подстановки цен по умолчанию, а также для пересчета реквизитов используются события “ПриИзменении” для соответствующих полей.
    Сама процедура пересчета описана в общем модуле “РаботаСНоменклатуройКлиент” с проставленным признаком “Клиент (управляемое приложение)”. Код:
    Процедура Пересчет(ТекДанные, РедактируемыйРеквизит=”Количество”) Экспорт
    Если РедактируемыйРеквизит=”Количество” Или РедактируемыйРеквизит=”Цена” Тогда
    ТекДанные.Сумма=ТекДанные.Цена*ТекДанные.Количество;
    ИначеЕсли РедактируемыйРеквизит=”Сумма” Тогда
    ПересчетЦены=РаботаСНоменклатуройСервер.ПересчетЦеныПриИзмененииСуммы();
    Если ПересчетЦены Тогда
    ТекДанные.Цена=ТекДанные.Сумма/ТекДанные.Количество;
    Иначе
    ТекДанные.Количество=ТекДанные.Сумма/ТекДанные.Цена;
    КонецЕсли;
    КонецЕсли;
    КонецПроцедуры
    В процедуре “ОбработкаПроведения” модуля объекта документа “Поступление товаров” описано добавление записей в регистры накопления “ОстаткиТоваров” и “ЗакупкиТоваров”.
    Проверка на возможность изменения базовой единицы измерения осуществляется в процедуре “ПередЗаписью” модуля объекта справочника “Номенклатура”. Код:
    Если БазоваяЕдиницаИзмерения<>Ссылка.БазоваяЕдиницаИзмерения Тогда
    Запрос = Новый Запрос;
    Запрос.Текст =
    “ВЫБРАТЬ
    |    ЗакупкиТоваров.Товар
    |ИЗ
    |    РегистрНакопления.ЗакупкиТоваров КАК ЗакупкиТоваров
    |ГДЕ
    |    ЗакупкиТоваров.Товар = &Товар
    |
    |ОБЪЕДИНИТЬ ВСЕ
    |
    |ВЫБРАТЬ
    |    ОстаткиТоваров.Товар
    |ИЗ
    |    РегистрНакопления.ОстаткиТоваров КАК ОстаткиТоваров
    |ГДЕ
    |    ОстаткиТоваров.Товар = &Товар”;

    Запрос.УстановитьПараметр(“Товар”, Ссылка);

    Результат = Запрос.Выполнить();

    ВыборкаДетальныеЗаписи = Результат.Выбрать();

    Если ВыборкаДетальныеЗаписи.Следующий() Тогда
    Сообщить(“По данному товару существуют движения. Базовую единицу измерения менять нельзя.”);
    Отказ=Истина;
    КонецЕсли;
    КонецЕсли;

  16. Здравствуйте. ДЗ выполнила.

    Для привязки менеджера завела новый реквизит в справочнике Контрагенты. Признак первого контакта – незаполненный реквизит Менеджер.

    Хранение цен в регистре сведений. Измерения ВидЦены (тип справочник ВидыЦен) и номенклатура.

    Регистр для хранения остатков – регистр остатков. Регистр для хранения данных о закупках – регистр оборотов.

    Супер сложностей не возникло, всё есть в уроках – главное внимательно смотреть-)))

  17. При выполнении задания не смог реализовать выбор из списка регистра сведений. Т.е. если делать связь между контактным лицом и контрагентом через регистр сведений, то в дальнейшем открывать список регистра с отбором в режиме выбора и по ключю выбранной записи определять КонтактноеЛицоКонтрагента. Поэтому, облегчил себе жизнь и просто добавил в спр. “КонтактныхЛицКонтрагента” реквизит “Контрагент”.  Все остальное не вызвало трудностей.

  18. Основные моменты выполнения задания:
    1) привязку менеджеров реализовала через независимый периодический(день) регистр сведений(измерение:Контрагент, ресурс:Менеджер), текущего пользователя подставляю в ОбработкаЗаполнения, при проведении проверка

    Граница = Новый Граница(Дата,ВидГраницы.Включая);
    Отбор = Новый Структура(“Контрагент”, Контрагент);
    Выборка = РегистрыСведений.МенеджерыПоКлиентам.СрезПоследних(, Отбор);
    Если Выборка.Количество() = 0 Тогда
    МенеджерЗаписи = РегистрыСведений.МенеджерыПоКлиентам.СоздатьМенеджерЗаписи();
    МенеджерЗаписи.Период = Дата;
    МенеджерЗаписи.Контрагент = Контрагент;
    МенеджерЗаписи.Менеджер = Менеджер;
    МенеджерЗаписи.Записать();
    КонецЕсли;

    2) хранение цен: типы цен храню в справочнике ТипыЦенНоменклатуры, сами цены в периодическом(день) подчиненном регистратору регистре сведений ЦеныНоменклатуры(измерения:ТипЦены,Номенклатура; ресурсы:Цена), цены вводятся при проведении документа УстановкаЦенНоменклатуры(цены сохраняю на начало дня)
    3) по удобству работы с документами
    – автоматическая установка цен происходит при изменении номеклатуры
    ТД.Цена = ОбщиеФункцииСервер.ПолучитьЦенуНаСервере(ТД.Номенклатура,Объект.ТипЦен,Объект.Дата);
    где получение цены на конец дня
    Функция ПолучитьЦенуНаСервере(Товар, ТипЦен, Дата) Экспорт
    Отбор = Новый Структура(“ТипЦены,Номенклатура”,ТипЦен,Товар);
    Возврат РегистрыСведений.ЦеныНоменклатуры.ПолучитьПоследнее(КонецДня(Дата), Отбор).Цена;
    КонецФункции
    -пересчет суммы по цене и количеству – однин обработчик события указан для 2х реквизитов(функция общего модумя возвращает произведение)
    Процедура ТоварыКоличествоЦенаПриИзменении(Элемент)
    Строка = Элементы.Товары.ТекущиеДанные;
    Строка.Сумма = ОбщиеФункцииКлиент.ВернутьСумму(Строка.Цена, Строка.Количество);
    КонецПроцедуры
    – пересчет при изменении суммы – ввела перечисление ВидыВариантовПересчетаПриИзмененииСуммы, создала константу, далее наверно выбрала не самый простой метод :)
    Процедура ТоварыСуммаПриИзменении(Элемент)
    Строка = Элементы.Товары.ТекущиеДанные;
    Если Строка.Цена<>0 И Строка.Количество<>0 Тогда
    Рез = ОбщиеФункцииСервер.ПересчитатьПоСумме(Строка.Сумма, Строка.Цена, Строка.Количество);
    Если Рез.Реквизит = “Цена” Тогда
    Строка.Цена = Рез.Значение;
    ИначеЕсли Рез.Реквизит = “Количество” Тогда
    Строка.Количество = Рез.Значение;
    КонецЕсли; 
    КонецЕсли; 
    КонецПроцедуры
    где функция в общем серверном модуле
    Функция ПересчитатьПоСумме(Сумма,Цена,Количество)Экспорт
    ВариантПересчета = Константы.ВариантПересчетаПриИзмененииСуммы.Получить();  
    Рез = Новый Структура;
    Рез.Вставить(“Реквизит”, Метаданные.Перечисления[ВариантПересчета.Метаданные().Имя].ЗначенияПеречисления[Перечисления.ВидыВариантовПересчетаПриИзмененииСуммы.Индекс(ВариантПересчета)].Имя);
    Если ВариантПересчета = Перечисления.ВидыВариантовПересчетаПриИзмененииСуммы.Цена Тогда
    Цена = Сумма/Количество;
    Рез.Вставить(“Значение”, Цена);
    Иначе
    Количество = Сумма/Цена;
    Рез.Вставить(“Значение”, Количество);
    КонецЕсли; 
    Возврат Рез; 
    КонецФункции
    4)хранение остатков в регистре накопления ОстаткиТоваров(измерения:Номенклатура,Качество, русурс:Количество). Движения в документах закупки сформировала через констуктор
    5)запрет изменения базоваой единицы для номенклатуры организовала так
    &НаКлиенте
    Процедура ПриОткрытии(Отказ)
    Элементы.БазоваяЕдиница.Доступность = ПроверкаДоступностиБазЕдНаСервере(Объект.Ссылка);
    КонецПроцедуры
    &НаСервереБезКонтекста
    Функция ПроверкаДоступностиБазЕдНаСервере(Товар)
    Запрос = Новый Запрос;
    Запрос.Текст =
    “ВЫБРАТЬ ПЕРВЫЕ 1
    | ОстаткиТоваровОбороты.Номенклатура,
    | ОстаткиТоваровОбороты.КоличествоОборот
    |ИЗ
    | РегистрНакопления.ОстаткиТоваров.Обороты КАК ОстаткиТоваровОбороты
    |ГДЕ
    | ОстаткиТоваровОбороты.Номенклатура = &Номенклатура
    |
    |ОБЪЕДИНИТЬ ВСЕ
    |
    |ВЫБРАТЬ ПЕРВЫЕ 1
    | ЗакупкиОбороты.Номенклатура,
    | ЗакупкиОбороты.КоличествоОборот
    |ИЗ
    | РегистрНакопления.Закупки.Обороты КАК ЗакупкиОбороты
    |ГДЕ
    | ЗакупкиОбороты.Номенклатура = &Номенклатура”;
    Запрос.УстановитьПараметр(“Номенклатура”, Товар);
    Возврат Запрос.Выполнить().Пустой();
    КонецФункции
    6)данные о закупках хранятся в оборотном регистре накопления Закупки(измерения:Контрагент,Номенклатура; ресурсы:Количество,Сумма)
    7)с журналом документов проблем вроде все понятно

  19. Нашел время добить задание. Посмотрев решение, понял, что не очень пользовался выносом кода в общие модули. Выходит не красиво. А на сколько критично в реализации? по сути это еще одна задача, которую можно и не делать, ведь и так работает )

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

  20. Задание выполнил.
    1. Для привязки менеджеров создал регистр сведений. Условие для заполнения текущего пользователя – Объект.Ссылка.Пустая(). Не совсем понял по поводу анализа на первый контакт – у меня все это делает платформа (т.к. я создал непериодический регистр).
    2. Создал регистр сведений. В форме элемента справочника номенклатура добавил табл. часть, куда вношу необходимые виды цен и сами цены. В модуле объекта, в процедуре ПриЗаписи заполняю регистр.
    3. С оптимизацией форм, регистрами накопления и журналом проблем почти не было.
    4. Проверку запрещающую изменять базовую единицу в полном объеме сделать пока не смог – запрос только для одного регистра.

    • >т.к. я создал непериодический регистр
      А ведь по условию требовался периодический регистр.

  21. ДЗ выполнил. Задание действительно объемное- много пришлось делать. Очень рад что наконец с регистрами в голове  все разложилось по полочкам. Какая то нелюбовь у меня с ними была еще с  7 -ки.  После просмотра ответа некоторые вещи исправил, т.к. уже наткнулся пару заданий назад, что если что-то делаешь на свое усмотрение”со своим видением” потом невозможно без кардинального изменения конфигурации выполнить текущее задание и все равно приходиться конфигурацию подтаскивать под опубликованное решение.

  22. Задание выполнено. Добавила Регистр сведений МенеджерыКонтрагентов. В документе Контакт делаю проверку. Предполагается, что если нет ни одного контакта, то и менеджера у контрагента нет.
    Поэтому проверяю именно наличие документов Контакт по данному контрагенту. Запрос по наличию документов в обработке проведения не пустой, т.к. учитывает текущий документ. Поэтому проверку вставила в ОбработкуПроверкиЗаполнения.
    <code> Процедура ОбработкаПроведения(Отказ, РежимПроведения)
    Если НадоЗаписатьМенеджера Тогда
    Запись=РегистрыСведений.МенеджерыКонтрагентов.СоздатьМенеджерЗаписи();
    Запись.Контрагенты= Контрагент;
    Запись.Менеджер  =Менеджер;
    Запись.Период=Дата;
    Запись.Записать();     
    КонецЕсли;          
    КонецПроцедуры

    Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
    НадоЗаписатьМенеджера=Ложь;

    Запрос = Новый Запрос;
    Запрос.Текст =
    “ВЫБРАТЬ
    |    Контакт.Номер,
    |    Контакт.Контрагент,
    |    Контакт.Менеджер
    |ИЗ
    |    Документ.Контакт КАК Контакт
    |ГДЕ
    |    Контакт.Контрагент = &Контрагент
    |    И Контакт.Проведен = ИСТИНА”;

    Запрос.УстановитьПараметр(“Контрагент”, Контрагент);

    Результат = Запрос.Выполнить();
    Если Результат.Пустой() Тогда
    НадоЗаписатьМенеджера=Истина;
    конецесли;       

    КонецПроцедуры</code>
    Работу с ценами организовала. Типы цен – справочник, цены номенклатуры – регистр сведений. Обращение к константе, от которой зависит реакция системы на изменение суммы и получение цены из регистра сведений вынесла в общий серверный модуль.  С приходной и расходной проблем не возникло, все как в видео уроках. Закупки от поставщиков сделала регистром оборотов, предполагаю, что нас будет интересовать объем закупок в количественном и суммовом выражении. В модуле объекта справочника Номенклатура в процедуру перед записью добавила проверку, если результат запроса по регистру по номенклатуре не пустой, базовую единицу менять нельзя.

  23. Задание сделано.

    В конфигурацию добавлен справочник Ползователи.

    Привязка менеджеров компании к её контрагентам осуществляется посредством создания периодического РС Менеджер клиента (период-День).

    При создании нового документа КонтактСКлиентом в реквизит подставляется текущий пользователь ИБ. Для определения, является ли данный контакт первым,
    используется запрос в модуле объекта документа в процедуре ОбрабокаПроведения.
    Для обеспечения хранения цен на товары и ведения различных прайс-листов созданы следующие объекты конфигурации:

    Типы цен
    – справочник
      ,
    Установка цен номенклатуры – документ ,
    Цены товаровРС  (период-День) .

    Доработаны документы закупки и отгрузки в соответствии с условиями задания.

    Запрещающая проверка на изменение базовой единицы измерения для наменклатуры реализована при помощи соответствующего запроса в модуле объекта.

    Создан РН Остатки товаров (вид-Остатки) для хранения остатков товаров.

    Создан журнал документов Документы закупки (пришлось вводить дополнительный реквизит в документы для вывода суммы).

  24. Задание выполнено.

    1. Привязка менеджеров к клиентам с помощью независимого
    регистра сведений “МенеджерыКонтрагентов”,
    Контрагент->Менеджер
    Документ “КонтактСКлиентом” делает запись в этот регистр
    при проведении, в случае отсутствия записей в регистре
    по контрагенту документа.

    2. Хранение цен.
    Создан документ “УстановкаЦенНоменклатуры”, который делает
    записи по регистру сведений “ЦеныНоменклатуры”
    (Номенклатура,ТипЦен -> Цена)

    3. Хранение остатков
    Регистр накопления “ОстаткиНоменклатуры”
    (Номенклатура,Качество -> Количество)

    4. Данные о закупках.
    Регистр накопления “Закупки”
    (Номенклатура,Контрагент -> Количество, Сумма)

  25. 1. Привязка менеджеров к клиентам – конечно же через регистр сведений, т.к. всегда может возникнуть вопрос: “А кто работал с клиентом такого-то числа?”. Кроме того, для установки менеджеров документами можно также иметь в виду, что документ может проводиться задним числом (кто-нибудь вспомнил, что он давно уже работал с этим клиентом). Тогда для анализа, что это первый контакт, надо выбирать таблицу СрезПоследних с параметром Период – ГраницаПередНачаломДня (“ПередНачалом” – чтобы при повторном проведении не попались записи, сделанные данным документом, а “Дня” – т.к. периодичность регистра выбрана “День”.
    2. Приступая к обработчику при изменении номенклатуры обнаруживаем, что там уже есть вызов сервера для получения единицы измерения. Кроме того, имеем в виду, что аналогичные действия надо выполнить во всех трех имеющихся документах по учету ТМЦ. Поэтому, во первых, в каждом документе вызываем клиентскую процедуру:
    <code>
    ОбщиеФункцииКлиент.ПересчитатьДанныеСтрокиПриИзмененииНоменклатуры(Объект.Дата, Элементы.Товары.ТекущиеДанные, Объект.ТипЦен);
    </code>
    а из неё выполняем вызов сервера:
    <code>
    СтруктураСведений = ОбщиеФункцииСервер.ПолучитьСведенияОНоменклатуре(ДатаСведений, ДанныеСтроки.Номенклатура, ВыбранныйТипЦен);
    </code>
    На сервере извлекаем данные из базы одним запросом, в виде структуры возвращаем в клиентский общий модуль. Клиентский модуль устанавливает полученные значения в Элементы.Товары.ТекущиеДанные, а также пересчитывает сумму.
    Промежуточный вызов клиентского модуля необходим, т.к. Элементы.Товары.ТекущиеДанные клиентской формы на сервере недоступны. Альтернативный вариант – промежуточный вызов контекстной серверной процедуры формы – неэффективен, т.к. пришлось бы перегонять все данные формы ради одной строки. Я правильно рассуждаю (не вполне уверенно чувствую себя в клиент-серверной версии)?
    3. Отображение итоговой суммы.
    Итоговую сумму показываем в подвале таблицы.
    Для таблицы Товары указываем свойство “Подвал” – Истина, для поля ТоварыСумма – “Отображать в подвале” – Истина и “Путь к данным подвала” – Объект.Товары.ИтогСумма.
    Далее для отражения суммы в журнале по документам закупок пришлось добавить реквизит шапки “Сумма”, который не виден пользователю в форме документа, а устанавливается перед записью документа.
    4. Запрет изменения базовой единицы измерения номенклатуры.
    Для реализации организовал функцию ПолучитьБазовуюЕдиницуИзмеренияНеПодлежащуюИзменению() в модуле справочника Номенклатура. Функция всегда вызывается перед записью (не нового) элемента справочника; при желании её можно также вызывать из формы, чтобы заранее воспрепятствовать попыткам изменения.
    Обратив внимание на формулировку “если по ней уже есть движения в РЕГИСТРАХ”, попробовал реализовать функцию так, чтобы она работала при неопределенном количестве регистров, имеющих соответствующее измерение (правда, только для регистров накопления). В таком случае надо собирать текст запроса примерно следующим образом:
    <code>
    МетаданныеРегистры = Метаданные.РегистрыНакопления;
    Для Каждого МетаданныеРегистр Из МетаданныеРегистры Цикл
      
     ИмяРегистра = МетаданныеРегистр.Имя;
     МетаданныеИзмеренияРегистра = МетаданныеРегистр.Измерения;
     Для Каждого МетаданныеИзмерениеРегистра Из МетаданныеИзмеренияРегистра Цикл
      
      ИмяИзмерения = МетаданныеИзмерениеРегистра.Имя;
      ОписаниеТиповИзмерения = МетаданныеИзмерениеРегистра.Тип;
      Если ОписаниеТиповИзмерения.СодержитТип(Тип(“СправочникСсылка.Номенклатура”)) Тогда
       …………………….
      КонецЕсли;
     КонецЦикла;
    КонецЦикла;
    </code>
    Внутри цикла объединяются запросы (через ОБЪЕДИНИТЬ):
    <code>
    “ВЫБРАТЬ ПЕРВЫЕ 1
    | 1 КАК Поле1
    |ИЗ
    | РегистрНакопления.” + ИмяРегистра + ” КАК ” + ИмяРегистра + ”
    |ГДЕ
    | ” + ИмяРегистра + “.” + ИмяИзмерения + ” = &Номенклатура”
    </code>
    Если результат выполнения запроса не пустой, то возвращаем ссылку на базовую единицу измерения.
    Используя “ВЫБРАТЬ ПЕРВЫЕ 1” я ожидаю, что как только будет обнаружена первая запись в запросе по отдельному регистру, выполнение запроса по этому регистру будет прекращено. Возникает вопрос, возможна ли дальнейшая оптимизация, чтобы прекращалось выполнение всего запроса. Может быть, надо написать: “ВЫБРАТЬ ПЕРВЫЕ 1 1 КАК Поле1 ИЗ (…) КАК ВложенныйЗапрос, где в скобках будет имеющийся запрос? – Но уверенности, что во вложенном запросе не будут обходиться все регистры, у меня нет.
     

     

    • > т.к. пришлось бы перегонять все данные формы ради одной строки. Я правильно рассуждаю
      Да, правильно.
      Можно только добавить, что в платформе заложены возможности оптимизации. Поэтому в большинстве случаев перегоняются не все данные, а только измененные.
      >Используя «ВЫБРАТЬ ПЕРВЫЕ 1″ я ожидаю, что как только будет обнаружена первая запись в запросе по отдельному регистру, выполнение запроса по этому регистру будет прекращено.

      Это действительно оптимальная конструкция, то запрос не прекратит выполнятся встретив первую подходящую запись.
      Вообще исполнение запроса на СУБД – вещь неоднозначная.
      Один и тот же запрос может в разные моменты времени исполнятся по разному (с разной скоростью и дело не в нагрузке на СУБД).
      Но об этом мы говорим в продвинутом.
      Дальнейшая оптимизация вашего запроса не требуется.

  26. Задание выполнил. 
    Для привязки менеджеров компании к клиентам был создан периодический независимый регистр сведений МенеджерыКлиентов с измерением Контрагент (тип СправочникСсылка.Контрагенты), ресурсом Менеджер (тип СправочникСсылка.Пользователи) и периодичностью «В пределах дня».
    Информация о текущем пользователе хранится в параметре сеанса ТекущийПользователь, который инициируется в модуле сеанса с помощью созданной ранее функции:

    <code> Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
    ПараметрыСеанса.ТекущийПользователь = ОбщиеФункцииСервер.СинхронизацияПользователей();
    КонецПроцедуры</code>

    Параметр сеанса удобен тем, что к нему можно обращаться в серверном контексте, в нашем случае это было необходимо при автоматическом заполнении реквизита Менеджер в документе КонтактСКлиентом:

    <code>Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)

    Менеджер = ПараметрыСеанса.ТекущийПользователь;

    КонецПроцедуры</code>

    При проведении документа КонтактСКлиентом в обработчике ОбработкаПроведения, анализ того, первый это контакт с клиентом или нет, был реализован двумя способами – с помощью объектной модели и с помощью запроса.
    Вариант 1 – объектная модель:

    <code>Отбор = Новый Структура(“Контрагент”, Контрагент);
    Выборка = РегистрыСведений.МенеджерыКлиентов.Выбрать(,, Отбор);

    Если НЕ Выборка.Следующий() Тогда
    Набор = РегистрыСведений.МенеджерыКлиентов.СоздатьНаборЗаписей();
    Набор.Отбор.Период.Значение = Дата;
    Набор.Отбор.Контрагент.Значение = Контрагент;
    Набор.Прочитать();

    НоваяЗапись = Набор.Добавить();
    НоваяЗапись.Период = Дата;
    НоваяЗапись.Контрагент = Контрагент;
    НоваяЗапись.Менеджер = Менеджер;

    Набор.Записать();

    КонецЕсли; </code>

    Вариант 2 – запрос:
    <code>Запрос = Новый Запрос;
    Запрос.Текст = 
    “ВЫБРАТЬ
    | МенеджерыКлиентов.Контрагент,
    | МенеджерыКлиентов.Менеджер,
    | МенеджерыКлиентов.Период
    |ИЗ
    | РегистрСведений.МенеджерыКлиентов КАК МенеджерыКлиентов
    |ГДЕ
    | МенеджерыКлиентов.Контрагент = &Контрагент”;

    Запрос.УстановитьПараметр(“Контрагент”, Контрагент);

    Результат = Запрос.Выполнить();

    Если Результат.Пустой() Тогда
    Набор = РегистрыСведений.МенеджерыКлиентов.СоздатьНаборЗаписей();
    Набор.Отбор.Период.Значение = Дата;
    Набор.Отбор.Контрагент.Значение = Контрагент;
    Набор.Прочитать();

    НоваяЗапись = Набор.Добавить();
    НоваяЗапись.Период = Дата;
    НоваяЗапись.Контрагент = Контрагент;
    НоваяЗапись.Менеджер = Менеджер;

    Набор.Записать();
    КонецЕсли; </code>

    Хотелось бы узнать, чем руководствоваться при выборе способа решения между объектной моделью и запросом, и какой вариант предпочтительнее в данном случае?

    Для хранения цен на товары были созданы справочник ТипыЦен и независимый периодический регистр сведений Цены с измерениями Номенклатура (тип СправочникСсылка.Номенклатура) и ТипЦены (тип СправочникСсылка.ТипыЦен), ресурсом Цена (тип Число 15.2) и периодичностью «В пределах дня». Предполагается, что в регистре Цены будут храниться цены для базовых единиц измерения номенклатуры.
    В документах по учету ТМЦ, при изменении номенклатуры, автоматически рассчитывается цена с помощью созданной в общем модуле ОбщиеФункцииСервер функции:
    <code>Функция ПолучитьЦену(Номенклатура, ТипЦены, ЕдиницаИзмерения, Дата) Экспорт 

    Отбор = Новый Структура;
    Отбор.Вставить(“Номенклатура”, Номенклатура);
    Отбор.Вставить(“ТипЦены”, ТипЦены);

    ЦенаЗаБазовуюЕдиницу = РегистрыСведений.Цены.ПолучитьПоследнее(Дата, Отбор).Цена;

    Возврат ЦенаЗаБазовуюЕдиницу * ЕдиницаИзмерения.К;

    КонецФункции</code> 

    Для пересчета в табличных частях документов реквизитов Сумма, Цена и Количество в клиентском общем модуле ОбщиеФункцииКлиент была создана процедура:

    <code>Процедура ПересчитатьСтрокуДокумента(ТекущиеДанные, ИмяРеквизита) Экспорт
    Если (ИмяРеквизита = “Сумма”) Тогда
    Если (ОбщиеФункцииСервер.ПолучитьЗначениеКонстанты(“ПересчитыватьКоличество”)) Тогда

    ТекущиеДанные.Количество = Окр(ТекущиеДанные.Сумма / ТекущиеДанные.Цена, 3);
    Иначе
    ТекущиеДанные.Цена = Окр(ТекущиеДанные.Сумма / ТекущиеДанные.Количество, 2);
    КонецЕсли;

    Иначе
    ТекущиеДанные.Сумма = ТекущиеДанные.Цена * ТекущиеДанные.Количество;
    КонецЕсли;

    КонецПроцедуры</code>

    Процедура ПересчитатьСтрокуДокумента вызывается из обработчиков ПриИзменении реквитов Номенклатура, Количество, Цена, Сумма документов по учету ТМЦ. В качестве параметров передаются текущие данные строки и имя изменяемого реквизита. Например, обработчик события ПриИзменении для реквизита Номенклатура, выглядит так:
    <code>&НаКлиенте
    Процедура ТоварыНоменклатураПриИзменении(Элемент)
    ТД = Элементы.Товары.ТекущиеДанные;
    ТД.ЕдиницаИзмерения = ПолучитьЕдиницуИзмерения(ТД.Номенклатура);
    Если (НЕ Объект.ТипЦены.Пустая()) Тогда
    ТД.Цена = ОбщиеФункцииСервер.ПолучитьЦену(ТД.Номенклатура, Объект.ТипЦены, 
    ТД.ЕдиницаИзмерения, Объект.Дата);

    КонецЕсли;

    ОбщиеФункцииКлиент.ПересчитатьСтрокуДокумента(ТД, “Номенклатура”);  
    КонецПроцедуры</code>

    Для хранения остатков товаров создан остаточный регистр накопления ОстаткиТоваров, имеющий измерения Номенклатура (тип СправочникСсылка.Номенклатура), Качество (тип СправочникСсылка.Качества) и ресурс Количество (тип число 15.3). Регистраторы – документы ПоступлениеТоваров, АвансовыйОтчет и РеализацияТоваров.

    При открытии формы элемента справочника Номенклатура, реквизит БазоваяЕдиница не доступен для редактирования, в случае если по этой номенклатуре существуют движения в регистре ОстаткиТоваров. Текст модуля формы элемента справочника:
    <code>&НаКлиенте
    Процедура ПриОткрытии(Отказ)

    Элементы.БазоваяЕдиница.Доступность = НеБылоДвижений(Объект.Ссылка);

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

    &НаСервереБезКонтекста
    Функция НеБылоДвижений(Номенклатура)

    Запрос = Новый Запрос;
    Запрос.Текст = 
    “ВЫБРАТЬ
    | ОстаткиТоваров.Регистратор
    |ИЗ
    | РегистрНакопления.ОстаткиТоваров КАК ОстаткиТоваров
    |ГДЕ
    | ОстаткиТоваров.Номенклатура = &Номенклатура”;

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

    Результат = Запрос.Выполнить();

    Возврат Результат.Пустой();

    КонецФункции</code>

    Для хранения данных о закупках создан оборотный регистр накопления Закупки, имеющий измерения Поставщик (составной тип СправочникСсылка.Контрагенты, СправочникСсылка.Сотрудники), Номенклатура (тип СправочникСсылка.Номенклатура) и ресурсы Количество (тип число 15.3), Сумма (тип число 15.2). Регистраторы – документы ПоступлениеТоваров и АвансовыйОтчет. 

    Был создан журнал документов ДокументыЗакупки. Для вывода в графу Сумма сумм документов, в документы ПоступлениеТоваров и АвансовыйОтчет добавлен реквизит СуммаДокумента, который заполняется перед записью документов:
    <code>Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    СуммаДокумента = Товары.Итог(“Сумма”); 
    КонецПроцедуры</code>

    • >Хотелось бы узнать, чем руководствоваться при выборе способа решения между объектной моделью и запросом, и какой вариант предпочтительнее в данном случае?
      Руководство очень простое – всегда использовать запрос.
      Это более правильный и оптимальный подход.

      • т.е. в платформе реализован избыточный функционал? :-)

        • Нельзя сказать, что избыточный. Скорее так сделано для единообразия, и приемственности с 7.7
          Реализовано две модели работы с данными: объектная и табличная.
          Объектная позволяет писать и читать. Но такое чтение все равно порождает запрос к БД.
          В ряде случаев использование объектной модели для чтения:
          А. Крайне неэффективно (об этом в продвинутом).
          Б. Приводит к ошибка (об этом см. бонус про 13 ошибок).

  27. Доброе время суток!
    Задание выполнил. Писать просто не о чем.  Имхо, сложность ДЗ№8 значительно ниже чем у ДЗ№7.
    Есть вопросы:
    1.В задании  что-бы сделать вывод суммы по документу в журнал делал доп. реквизит в шапке документа. По другому ни как?
    2.Финальное задание тоже будет сделано на основе дз котрые делаем или с нeт?
    3.По итогам завершения наших блоков можно будет скачать ту базу,  на которой демонстрируют решения ДЗ?

    • 1. Дополнительный реквизит – самое оптимальное и разумное решение.
      2. Нет, оно будет основано на другой базе.
      3. База с решением выкладывается после каждого ДЗ. У вас не получилось ее скачать?

      • видать не по глазам… сейчас  пробую, если не получится – ещё спрошу…

  28. Задание выполнил. Трудностей не возникало. Соглашусь с тем что задания могли бы быть  более подробными.

  29. Admin_Net_1C 04.12.2010 в 07:49

    Домашнее задание №8 выполнено.
    1) Для привязки менеджеров к клиентам в справочнике “Контрагенты” добавлен реквизит “Менеджер” (СправочникСсылка.Пользователи). Выбран реквизит справочника, а не механизм с регистром сведений в силу того, что по условиям задания “считается, что в один момент времени с клиентом может работать только один менеджер, но с течением времени менеджер у контрагента может измениться”.
    2) При создании нового документа “КонтактСКлиентом” в реквизит “Менеджер” (СправочникСсылка.Пользователи) подставляется текущий пользователь ИБ. В МО документа в процедуре “ОбрабокаПроведения” с помощью запроса к физической таблице на выборку вида “ВЫБРАТЬ ПЕРВЫЕ 1” регистра сведений “КонтактыСКонтрагентами”, определяется, является ли данный контакт первым, если да, значение реквизита “Менеджер” текущего документа записывается в реквизит “Менеджер” выбранного в документе контрагента.
    3) Для хранения цен и различных видов прайс-листов созданы следующие объекты:
    а) Справочник.ТипыЦен.
    б) Документ. УстановкаЦен. Табличная часть “Цены” с реквизитами: Номенклатура (СправочникСсылка.Номенклатура), ТипЦен (СправочникСсылка.ТипыЦен), Цена (Ч15.2). При проведении осуществляет запись в регистр сведений ” ЦеныТоваров”.
    б) РегистрСведений.ЦеныТоваров. Измерения: Номенклатура (СправочникСсылка.Номенклатура), ТипЦен (СправочникСсылка.ТипыЦен). Ресурсы: Цена (Ч15.2). Периодичность регистра “В пределах дня”, подчинен регистратору (Документ.УстановкаЦен).
    4) В документах “ПоступлениеТоваров” и “Реализация” реализовано соедующее поведение:
    а) автоматическая подстановка соответствующего значение цены выбранной номенклатуры, в соответствии с выбранным прайсом в реквизите “ТипЦен” (СправочникСсылка.ТипыЦен). Подстановка реализована с помощью функции общего модуля ПолучитьЦенуТовара(Дата, Товар, Единица, ТипЦен), в которой с помощью запроса осуществляется получение значения цены с указанным типом на указанную дату и пересчетом в соответствии с выбранной единицей измерения. В качестве источника данных запроса выступает ВТ РегистрСведений.ЦеныТоваров.СрезПоследних.
    б) пересчет реквизита табличной части “Сумма” при изменении цены/количества, выборе номенклатуры.
    в) пересчет цены или количества при изменении суммы в зависимости от значения константы ” ПересчетЦеныКоличестваОтСуммы”.
    г) отображение итоговой суммы в подвале табличной части.
    5) Для хранения остатков номенклатуры создан регистр накоплений “ОстаткиТоваров” с видом остатки. Измерения: Номенклатура (СправочникСсылка.Номенклатура), ВидБрака (СправочникСсылка.ВидБракаТоваров). Ресурсы: Количество (Ч10.3). Регистраторы: Документ.ПоступлениеТоваров, Документ.Реализация. При проведении документа “ПоступлениеТоваров” выполняется запись приходных движений по регистру в базовых единицах (при необходимости количество из табличной части документа пересчитывается в базовые единицы).
    6) Реализован механизм запрета изменения базовой единицы номенклатуры, если по данной позиции были движения в регистре “ОстаткиТоваров”. Алгоритм реализован с помощью проверки на пустоту результата запроса вида ” ВЫБРАТЬ ПЕРВЫЕ 1″ к физической таблице регистра по выбранной номенклатуре.
    7) Создан журнал “ДокументыЗакупки” отображающий информацию о документах поступления товаров (Документ.ПоступлениеТоваров).
     
    Вопрос:
    Не понятно задание в части абзаца:
    “Создайте объект, для хранения данных о закупках от поставщиков. Обеспечьте заполнение данных объекта при проведении документов.”
    Объект какого типа имеется в виду и соответственно какие данные этого объекта должны заполняться?

    • Речь идет о создании регистра.

      • Admin_Net_1C 07.12.2010 в 20:00

        Только при просмотре решения домашнего задания выяснил что в абзаце:
        «Создайте объект, для хранения данных о закупках от поставщиков. Обеспечьте заполнение данных объекта при проведении документов.»
        речь идет о создании оборотного регистра )) Большая просьба формулировать более “доходчиво” текст домашнего задания для таких тугодумов как я ))

        • Ок, учтем.
          Вот такая формулировка:
          “Создайте объект, для хранения данных о закупках от поставщиков. Обеспечьте заполнение
          данных объекта при проведении документов. Информацию о закупках необходимо хранить в
          разрезе поставщиков и товаров, необходимые показатели для учета – количество и стоимость
          закупок.”
          более понятная?

  30. Д/З выполнил.
    Трудностей не возникло, посему комментировать особо и нечего…
    Создал  пару общих модулей – клиентский и серверный, в них разместил все интерфейсные процедуры.
    Усложнил задание – проверка заполнение единиц измерения в ТЧ производиться только для номенклатуры товар, для услуг не проверяется. Освоил очень полезный механизм привязки сообщений к полям ТЧ.
     

  31. Задание выполнил.
    Для привязки менеджера к контрагенту использовал независимый регистр сведений КонтрагентыМенеджеры с измерением Контрагенты и ресурсом Менеджер типа Пользователи.
    Текущий Менеджер определяется через функцию СинхронизацияПользователей() из прошлого задания.
    В обработке проведения документа КонтактСКлиентом запросом по данному регистру выясняется, есть ли данный контрагент в регистре, если да, то менеджер в документе заменяется текущим менеджером.
    Запись в регистр производится через СоздатьМенеджерЗаписи().
    Хранение цен на товары прозводится через независимый регистр сведений ЦеныНаТовары (измерения-Номенлатура,ПрайсЛист (справочник ПрайсЛисты), ресурс – Цена).
    В документах по учету ТМЦ добавил два реквизита – ПрайсЛист и ОбщаяСумма. В обработчиках ТоварыНоменклатураПриИзменении() через функцию ЗаполнитьДанные(), возвращающую структуру,
    заполняются поля Единица и Цена. Цена определяется как ЦеныНаТовары.ПолучитьПоследнее(Дата,Отбор) на дату в документе.
    В обработчике ПрайсЛистПриИзменении() делается пересчет цены и суммы товаров в ТЧ документа.
    Пересчет суммы производится так:
    Если ПересчитатьКоличество Тогда
    Количество = ?(Цена>0,Цел(Сумма/Цена),0);
    Иначе Цена = ?(Количество>0,Сумма/Количество,0).
    Итоговую сумму документа на форме выношу в подвал, а в ПередЗаписью() заполняю реквизит ОбщаяСумма для журнала документов.
    Для хранения остатков создал регистр ОстаткиТоваров(вид – остатки).Измерения – номенклатура,качество, ресурсы – количество.
    Регистраторы для него – документы по учету ТМЦ.
    Для приходных движений создал регистр ЗакупкаТоваров (вид – обороты).Измерения – номенклатура,контрагент, ресурсы – количество,Сумма.
    Регистратор для него – документ ПоступлениеТоваров.
    запись в регистры настроил через конструктор движений.
    Разрешение изменения базовой единицы проверяю в обработчике ЕдиницаНачалоВыбора(). Вызывается функция общего серверного модуля
    БылиДвиженияПоРегистрам(Номенклатура). Она возвращает ложь, если выборки ЗакупкаТоваров.Выбрать(,,Отбор) и
    ОстаткиТоваров.Выбрать(,,Отбор) пустые.Результат присваивается СтандартнойОбработке.
    В журнал добавил 2 графы – Контрагент, Сумма.

  32. ДЗ выполнил.
    Затруднений в процессе никаких не возникло, так что комментировать особо нечего. Все подробно “разжевано” в видеоуроках.
    Отмечу некоторые моменты:
    Все пересчеты реализовал в клиентском общем модуле “ОбработкаТабличныхЧастейКлиент”.
    Создал константу “ПересчитыватьКоличествоПриИзмененииСуммы” тип – “Булево”.
    Отображение итоговой суммы сделал включением подвала в ТЧ документов и указания свойства “ПутьКДаннымПодвала” = Объект.Товары.ИтогСумма у реквизита ТЧ “Сумма”.
    Также при проведении реализовал пересчет количества, если указана единица, отличная от базовой.

    • Да и забыл, менеджера пишу при проведении в реквизит Контрагента – “ОсновнойМенеджер”, предварительно проверив запросом, есть ли еще документы “КонтактСКлиентом”, кроме текущего.

  33. Задание выполнил
    Создал Независимый Периодический РегистрСведений МенеджерыКлиента Измерения Контрагент Ресурс Пользователи.
    Документ КонтактСКлиентом, в ОбработкеЗаполнения создаю структуру ДанныеЗаполнения . Потом получаю ГУИД ПользователиИнформационнойБазы, по ГУИДу на хожу в справочнике Пользователи пользователя,  полученную ссылку добавляю в структуру.
    Проведение. Ищу запросом записи в РегистрСведений МенеджерыКлиента запись с контрагентом если есть в Регистре записи ни чего не добавляется.
    Создал Переодический Независимый  РегистрСведений ЦеныНоменклатура Измерения: номеклатура, ВидПрайса. Ресурс Цена.
    В модуле формы как Поступления товара так РеализацияТоваров. Обработке приИзменениеНомеклатуры Вызываю серверную функцию общего модуля ПолучитьЦену Там Методом РегистрСведений ПолучитьПоследнее(). Получаю цену. Отбор это структура из номенклатуры и видПрайса. Также клиентской функцией ПересчитатьСумму из общего модуля пересчитываю сумму.
    В обработках приИзмененииКоличества и приИзменениеЦены вызываю функцию из общего модуля ПересчитатьСумму().
    ПриИзмененииСуммы.  Непонял как использовать вариант с константами?
    Поэтому в обработке создаю Список добавляю варианты «По количеству» «По цене» вызываю диалог методом Список.ВыбратьЭлемент. От выбора в условиях пересчитываю. Если нет выбора или плохо считается использую терминирующие сообщения.
    Отображение Итоговой суммы использую подвал Как в уроке.
    Создал РегистрНакопленияОстаткиМатериалов Измерения: Номенклатура, качество. Ресурс: Количество.
    Для документов Поступления товара и  РеализацияТоваров ОбработкуПроведения создал конструктором. Для учета количества в базовых единицах. Придумал только чтобы в движение количество умножалось на коэффициент из Спр ЕдИЗмерения. Движение.Количество = ТекСтрокаТовары.Количество*ТекСтрокаТовары.ЕдиницаИзмерения.К
    Запрет на изменение БазовайЕденицы в Спр.Номенклатура. Реализовал в Модуле формы в событии приОткрытии. Там запрос к РегистрНакопления.ОстаткиМатериалов. если записей нет по номеклатуре  то поле БазоваяЕдиница Доступно.
    Создал Регистр Накопления Закупки вид регистра обороты Измерения контрагент ресурсы сумма.
    Проводка документов в регистр конструктором  .
    Журнал Документов  Для отображения суммы в документ ПоступлениеТоваров добавил реквизит сумма на форме его нет заполняется он  перед сохранением  итоговым значение суммы из ТЧ товары.

  34. Привязку менеджеров к клиентам удобно реализовать  с помощью периодического регистра сведений с независимым режимом записи я его назвал «МенеджерыКлиентов». Для удовлетворения требования, что в один момент времени с клиентом может работать только один менеджер, необходимо в качестве измерения регистра использовать клиента, а в качестве ресурса менеджера.
    Проверку того, что документ КонтактСКлиентом является новым (для заполнения реквизита Менеджер) реализовал в обработчике события «ПриОткрытии», в виде следующего условия ЗначениеЗаполнено(Объект.Ссылка) .
    При проведении документа, с помощью запроса по  срезу последних с отбором  в параметрах виртуальной таблицы по Контрагенту проверяется, есть ли данные в регистре, и если их нет (первый контакт)  в регистр сведений МенеджерыКлиентов добавляется запись, закрепляя менеджера из документа за данным контрагентом.
    Для учета цен в различных прайс-листах создал справочник ТипыЦен и периодический регистр сведений ЦеныНоменклатуры с независимым режимом записи и измерениями Номенклатура и ТипЦены и ресурсом Цена. В документы прихода и расхода добавлен реквизит ТипЦены.
    Для получения цены при изменении Номенклатуры в документах использовалась процедура общего серверного модуля с флагом «Вызов сервера», которая в запросе обращалась к виртуальной таблице регистра сведений ЦеныНоменклатурыСрезПоследних, фильтр по Номенклатуре и типу цен устанавливался через параметры этой таблицы.
    Для считывания значения константы, устанавливающей правило перерасчета при изменении суммы, из формы документа вызывается функция общего серверного модуля, которая просто возвращает значение константы.
    Для хранения остатков используется регистр остатков с измерениями Номенклатура и Качество, при этом для хранения в базовой единице количество из документа умножается на коэффициент единицы измерения из соответствующей строки документа.
    Для реализации проверки наличия движений в регистре остатков номенклатуры использовал запрос по оборотам регистра без установки периодов начала и окончания, но с фильтром по номенклатуре в параметрах виртуальной таблицы. Проверка вызывается в обработчике события ПередЗаписью модуля справочника Номенклатура и в случае не пустого результат запроса запрещает изменять ед. измерения.
    Поскольку постановка задачи о хранения данных по закупкам от поставщиков не отличается полнотой, то для хранения этих данных я выбрал оборотный регистр «Закупки» в качестве измерений которого использовал Поставщика и Номенклатуру, а в качестве ресурсов Количество. Движения по регистру осуществляют документ Поступление, поскольку Авансовый отчет отражает факт поступления от собственного сотрудника.
    Вопросы:
    Допустим в документах необходимо пересчитывать уже введенные цены номенклатуры при изменении типа цены, при этом желательно получить цены для всех номенклатурных позиций одним запросом, передав в него параметром список номенклатуры из таблицы формы. Каким образом можно реализовать данный функционал, ведь таблица формы, как я понял, не обладает методами, позволяющими перебрать все строки таблицы или выгрузить колонку в список значений.

    • >ведь таблица формы, как я понял, не обладает методами
      Здесь нужно смотреть не методы элементов формы, а методы реквизитов формы.
      Ведь нас интересуют данные объекта. А если бы интересовала видимость, доступность элементов или текущая строка, тогда бы мы обращались к элементам формы (таблица формы).
      Поэтому нужный тип данных – ДанныеФормыКоллекция, именно таким типом обладает Объект.Товары (посмотрите в отладчике).
      У этого типа есть метод Выгрузить(), который получит таблицу значений, далее ее можно и передавать в запрос.
      Конечно, все это нужно будет делать на сервере, в контекстном методе. Поскольку потребуется работать с данными формы.

  35. Задание сделала! :) Итак, по порядку:
    1. Привязку менеджеров к клиентам сделала через РегистСведений.МенеджерыКлиенты (Измерение – Контрагент, Ресурс – Менеджер) , регистр непериодический и независимый.
    2. В доке “Контакт” добавила реквизиты “Менеджер” и “Контрагент”, указала в свойстве  “Проверка заполнения” –>  “Выдавать ошибку”.
    Для рекзивита “КонтактноеЛицо”, указала в свойстве “Связи параметров выбора” –> “Отбор.Вдалелец(Контрагент)”
    В МО дока “Контакт” :
    – в процедуре “ОбработкаЗаполнения”
    <code>
    Если ДанныеЗаполнения=Неопределено Тогда
    Менеджер =ОбщиеФункцииСервер.СинхронизацияПользователей();    
    КонецЕсли;
    /<code>
    – в процедуре “ОбработкаПроведения”, делаю обращение через запрос к РС МенеджерыКлиенты через СрезПоследних, если Запрос.Пустой() тогда произвожу запись в РС  МенеджерыКлиенты через Набор.Записать(ложь), ниже привожу текст запроса
    ВЫБРАТЬ
    |    МенеджерыКлиентыСрезПоследних.Контрагент
    |ИЗ
    |    РегистрСведений.МенеджерыКлиенты.СрезПоследних КАК МенеджерыКлиентыСрезПоследних
    |ГДЕ
    |    МенеджерыКлиентыСрезПоследних.Контрагент = &Контрагент
    |    И МенеджерыКлиентыСрезПоследних.Менеджер = &Менеджер
    3.Хранение цен на товары организовала через РегистНакопления.ЦеныПоПрайсам (Измерения – Товар, ВидЦены – тип Справочники.ВидЦен, специально создан для хранения инфы о видах цен ; Ресурсы – Цена)
    4.Работа над удобством работы с доками прихода и расхода товара.

    4.1 Добавила новый реквизит “ВидЦены”, тип Справочники.ВидЦен.
    4.2 Автоматическую подстановку цен при выборе номенклатуры организовала через событие “ПриИзменииТовара”, где обращаюсь в общий  модуль, к созданной в прошлом ДЗ  и немного модифицированной в этом ДЗ, функции на получение единицы, которая через параметр возвращает теперь и  Цену, цену нахожу через ПолучитьПоследнее
    <code>Перем Цена;
    ТабТМЦ = Элементы.Товары.ТекущиеДанные;

    ТабТМЦ.Ед =
    ОбщиеФункцииСервер.ПолучитьЕдСервер(ТабТМЦ.ТМЦ,Объект.Дата,Объект.ВидЦены,Цена)
    ТабТМЦ.Цена = Цена;/<code>
    В ОМ, кусочек из функции “ПолучитьЕдСервер”:
    <code>Отбор = Новый Структура(“Товар,ВидЦены”,Товар,ВидЦены);
    Цена = РегистрыСведений.ЦеныПоПрайсам.ПолучитьПоследнее(Дата,Отбор).Цена;
    /<code>
    4.3 Для пересчета цены, кол-ва и суммы создала ОМ с процедурой : ЗаполнениеДокументаКлиент.ВычисляемСумму(ТабТМЦ,Пар),
    где  ТабТМЦ = Элементы.Товары.ТекущиеДанные; Пар – признак (1 – если идет изменение суммы и Неопределено – если изменяют кол-во либо цену)
    В процедуре “ВычисляемСумму”, в зависимости от параметра “Пар”, вызываю либо:
    – процедуру ПересчетСуммы(ТД), где ТД.Сумма =  ТД.Кво * ТД.Цена;
    -процедуру ПересчетКвоЦена(ТД), где обращаюсь к другому ОМ —> ОбщиеФункцииСервер.ЧитаемКонстанту() , где проверяю значение Константы.ИзменятьКолПриИзмСуммы (тип Булево) и взависимости от результата при изменении пользователем суммы меняю или кол-во или цену.
    5.Создала РегистрНакопления.ОстаткиТовара (Измерения – Товар, Качество, Ресурсы – Кво; Вид регистра – Остатки), в документах Поступление, Авансовый отчет и Отгрузка с помощью Конструктора движений прописала движения по данному регистру. При присвоении ресурсу Кво привожу кол-о из документа к базовой единице
    Движение.Кво = ТекСтрокаТовары.Кво*ТекСтрокаТовары.Ед.Кооф;
    6. Проверку, которая запрещает изменение баз.ед. в товаре, если есть движения в регистрах сделала через Событие элемента формы БазЕд “ПриИзменении” , где проверяю,  если элемент не новый, т.е Ссылка не пустая, тогда проверяю Обороты по регистрам по данному товару.
    <code>
    &НаКлиенте
    Процедура БазЕдПриИзменении(Элемент)
    Если Не Объект.Ссылка.Пустая() Тогда
    Если ПроверкаТМЦСервер(Объект.Ссылка) Тогда
    Объект.БазЕд = БазЕдДоИзм;
    предупреждение(“Нельзя менять баз.ед.! Уже есть движения!”);
    КонецЕсли;    
    КонецЕсли;
    КонецПроцедуры
    &НаСервереБезКонтекста
    Функция ПроверкаТМЦСервер(Товар)
    Отбор = Новый Структура(“Товар”, Товар);
    ТЗ = РегистрыНакопления.ОстаткиТовара.Обороты(,,Отбор);
    Если ТЗ.Количество()<>0 Тогда
    Возврат Истина;    
    КонецЕсли;
    ТЗ = РегистрыНакопления.Закупка.Обороты(,,Отбор);
    Если ТЗ.Количество()<>0 Тогда
    Возврат Истина;    
    КонецЕсли;
    Возврат ложь;    
    КонецФункции /<code>
    7. Создала РегистрНакопления.Закупка(Измерения – Котрагент,Товар,  Ресурсы – Кво,Сумма; Вид регистра – Обороты). В документ Поступление прописала движения по этому регистру.
    8.Создала журнал “ДокмуентыЗакупки”, для того, чтобы отразить сумму по док-там, в каждый док ввела реквизит СуммаИтог и в МО документа в процедуре  ПередЗаписью прописываю
    СуммаИтог = Товары.Итог(“Сумма”);
    ————————————-
    Мне интересно –  мое решение (пункт6) насколько оно правильно??? или все же делать подобную проверку в модуле формы не стоит???

     
     
     

     

    • Ошиблась при описании , РегистСведений.МенеджерыКлиенты – у меня  периодический (в течении дня) и независимый.

    • Пункт 6.
      Все же лучше делать проверку в модуле объекта. Ведь она будет работать для любой формы, и даже при программной записи.
      Событие, которое вас интересует – ПередЗаписью.
      Вместо использования метода лучше использовать запрос, который вернет количество записей.

  36. MashkaRomashkina 30.11.2010 в 18:04

    Задание выполнила.
    Менеджер, работающий с клиентом у меня – реквизит справочника Контрагенты. Можно сделать также через РегистрСведений, но пока необходимости отслеживать изменение Менеджера с течением времени вроде нету.
    Запрос для определения существующих Контактов с контрагентом:
     
    “ВЫБРАТЬ ПЕРВЫЕ 1
    | КонтактСКлиентом.Ссылка
    |ИЗ
    | Документ.КонтактСКлиентом КАК КонтактСКлиентом
    |ГДЕ
    | КонтактСКлиентом.Ссылка <> &Ссылка
    | И КонтактСКлиентом.Контрагент = &Контрагент”;
    “ВЫБРАТЬ ПЕРВЫЕ 1 | КонтактСКлиентом.Ссылка |ИЗ | Документ.КонтактСКлиентом КАК КонтактСКлиентом |ГДЕ | КонтактСКлиентом.Ссылка <> &Ссылка | И КонтактСКлиентом.Контрагент = &Контрагент”;
    Хранение цен реализовала в периодическом РегистреСведений с измерениями ТипЦены, Номенклатура, ресурсом Цена.
    Цену для подстановки в документ определяю  запросом по виртуальной таблице ПрайсЛисты.СрезПоследних.
    Пересчеты организовала вызовом такой функции общего клиентского модуля:

    Функция Пересчет(Изменено,Реквизит1,Реквизит2) Экспорт
    Если Изменено = “Кво” Или Изменено = “Цена” Тогда
    Вычисление = Реквизит1*Реквизит2;
    ИначеЕсли Изменено = “Сумма” Тогда
    Вычисление = ?(Реквизит2<>0,Реквизит1/Реквизит2,0);
    КонецЕсли;
    Возврат Вычисление;
    КонецФункции
    Вызывается при изменении реквизитов табл. части например, для суммы:

    Процедура ТоварыСуммаПриИзменении(Элемент)
    ТД = Элементы.Товары.ТекущиеДанные;
    Если ВозвратКонстантыПересчетЦены() = Истина Тогда
    ТД.Цена = ОбщиеФункцииКлиент.Пересчет(“Сумма”,ТД.Сумма,ТД.Количество);
    Иначе
    ТД.Количество = ОбщиеФункцииКлиент.Пересчет(“Сумма”,ТД.Сумма,ТД.Цена);
    КонецЕсли;
    КонецПроцедуры
    Добавила регистр Остатки с измерениями Номенклатура, СтепеньБрака и ресурсом Кол-во, организовала проведение документа ПоступлениеТоваров .
    Проверку на возможность изменения баз.ед.изм. произвожу в процедуре БазоваяЕдиницаНачалоВыбора, вызывая функцию с запросом по таблице оборотов регистра Остатки. Выбираю первое движение, номенклатуру отбираю в параметрах виртуальной таблицы. Если движения были – СтандартнаяОбработка =Ложь;
    Закупки храню в оборотном регистре накопления с измерениями: контрагент, номенклатура и ресурсами: кол-во, сумма. Движения по регистру при проведении прихода.

    Создала журнал закупок с нужными графами, в ПоступленииТоваров добавила реквизит шапки Сумма, кот. заполняю в процедуре ПередЗаписью модуля объекта.

     

  37. Задание выполнил.
    Создал периодический независимый РС СведенияОМенеджерахКлиентов. Измерение Контрагент, ресурс Менеджер (справочник Пользователи).
    Справочник Контакты все-таки переделал в документ. В ПриЗаписи() для новых документов (новый это документ или нет определяю в ПередЗаписью()) делаю запись в РС СведенияОМенеджерахКлиентов.
    Создал справочник ТипыЦен. Создал периодический независимый РС ЦеныНоменклатуры. Измерения – Номенклатура, ТипЦены. Ресурс – Цена.
    Провел работу над юзабилити документов “Поступление товаров”, “Реализация товаров”. В документ “Поступление товаров” добавил реквизит Сумма, куда записывается итоговая сумма (для журнала документов).
    Для автоматической подстановки цены использую вызов функции общего серверного модуля. Функции передается номенклатура и тип цен, а она возвращает в форме структуры единицу измерения и цену по прайсу.
    Пересчет суммы сделал в форме документов, не стал заморачиваться с функцией в общем модуле, хотя так оптимальнее.
    Создал перечисление КолонкиТЧ, создал константу ПересчетКолонкиТЧ, тип – перечисление, данные – “Цена”, “Количество”. В зависимости от значения константы, передаю наименование колонки и данные для пересчета в функцию серверного общего модуля.
    Отображение итоговой суммы документа сделал в подвале, путь к данным подвала Объект.Товары.ИтогСумма
    Для полей Номенклатура, ЕдиницаИзмерения и Количество установил проверку на заполнение в свойствах реквизитов.
    Создал РН остатков ОстаткиТоваров. Измерения –  Номенклатура, Качество, ЕдиницаИзмерения. Ресурс – Количество. Регистраторами РН являются документы “Поступление товаров”, “Реализация товаров”.
    Организовал движение по РН ОстаткиТоваров в документе “Поступление товаров”.  Предварительно в запросе группирую количество по номенклатуре и единицам измерения.
    В процедуре ТоварыЕдиницаИзмеренияОбработкаВыбора() вызываю функцию общего серверного модуля, которая получает остатки по РН ОстаткиТоваров для указанной номенклатуры и единицы измерения (кроме движений самого документа). Если количество равно нулю, то единица измерения изменяется на ВыбранноеЗначение.
    Поскольку из условия не понятно, для чего будут использоваться данные о закупках от поставщиков, создал оборотный РН Закупки. Измерения Поставщик, Номенклатура, Качество. Ресурсы Количество, Сумма. Регистратор – документ “Поступление товаров”, организовал проведение по этому регистру.
    Создал журнал “Документы закупки”, для графы “Сумма” использовал добавленный в документ “Поступление товаров” реквизит Сумма, который заполняется в ПриЗаписи() документа.
     
     

  38. Не совсем понятно в задании  в 3-м обзаце, казается документа “КонтактСКлиентом” : “При проведении документа необходимо выполнить анализ, если происходит первый контакт с контрагентом, то необходимо в качестве менеджера  нужно установить значение, указанное в документе????? ”  Что имеется в виду, в каком документе? По условию менеджер заполняется при создании документа автоматически текущим пользователем! Что-то я тут не могу разобраться что собственно нужно сделать .

    • Если бы была такая формулировка, то ясность бы наступила?
      “При проведении документа необходимо выполнять анализ, если происходит первый контакт с контрагентом, то необходимо в качестве менеджера для контрагента нужно установить значение, указанное в документе.”

      Выше речь идет о том, что нужно будет создать объект, где контрагенты связываются с менеджерами..

  39. Евгений, Вы не раз упоминали, что нужно минимизировать количество серверных вызовов. Пытаюсь придерживаться этого правила.
    Вот, при решении ДЗ возникла ситуация: при выборе номенклатуры нужно делать вызов серверной функции, чтобы определить, во-первых, базовую единицу измерения, а во-вторых, цену по прайсу. Делать два вызова не оптимально, поэтому получил все запросом в одной серверной функции и возвращаю значения на клиента в виде структуры с ключами ЕдИзм и ЦенаПоПрайсу.
    На Ваш взгляд, как лучше возвращать с сервера на клиент несколько “разнородных” значений? Структурой или как-то по другому?

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

  40. ДЗ выполнил, делаю все быстро, трудностей нет.  пока всегда думаю о при процессоре  клиенте и сервере, так как ранее не писал на 8.2, а на 8.1 есть уже опыт с текущими объектами. По возможности смотрю уроки, все решения в уроках приводится. Хотелось бы что бы ДЗ излагалось более подробнее, может даже  в виде видео. Демонстрации того, что должно получится. ИМХО

    • «Хотелось бы что бы ДЗ излагалось более подробнее, может даже  в виде видео. Демонстрации того, что должно получится. ИМХО» Да было бы неплохо. Постоянно отклоняюсь от задания и из-за этого время его выполнения увеличивается в несколько раз.

      • Этот момент учтем.
        С другой стороны, если задание будет четким и полностью ясным, то оно не будет соответствовать реальности..

    • AlexAl-77, по моему изложение задания в форме видео – “как должно быть”, это “тепличные условия” для разработчика. :) В реале задачи ставят далеко не так четко, как в условиях по ДЗ и одна из наших необходимостей – это понять, чего хочет заказчик. Если же заставить его оформлять задания видео-презентациями, то ничего хорошего из этого не выйдет.

      • В целом соглашусь.
        Порой формулировки пользователей бывают очень туманными..