Базовый курс. Занятие №8
2-ое занятие по второму блоку базового курса.
Необходимо изучить следующие главы.
Глава 5. Журналы документов.
Глава 6. Настройка командного интерфейса.
Глава 7. Регистры.
Глава 8. Регистры накопления.
Глава 9. Регистры сведений.
Глава 10. Настройка форм.
Также нужно выполнить домашнее задание, текст которого доступен на странице.
Задание необходимо выполнять в ИБ после предыдущего ДЗ.
В этой же теме необходимо написать отчет о выполнении задания.
ps. Участники курса без доступа в мастер-группу отчитаться по домашним заданиям не получиться.
— залогиньтесь.
Если не активировали токен — посмотрите видео-инструкцию (видео N5)
Если вы залогинены, у Вас активирован токен доступа, но вы все равно видите эту запись —напишите нам на e-mail поддержки.
Задание сделано.
1) Для привязки менеджеров к клиентам создан независимый РС “КлиентыМенеджеров” (Измерение – Клиент (ведущее), Ресурс – Менеджер, с периодом в день). Сделала просмотр регистра с элемента Контрагенты, и движения регистра также осуществляются при проведении документа РегистрацияКонтактнойИнформации с проверкой по последней записи по Менеджеру (чтоб не повторять).
2) для цен создан РС “ЦеныНоменклатуры”, подчиненный регистратору УстановкаЦенНоменклатуры. В документе выбирается ВидЦен (справочник), в табличной части заполняется номенклатура, ед.из и цена. При движении по регистру идет пересчет в базовую ед.из.
3) в документах выполнен пересчет строк при изменении: номенклатуры, ед.из, количества, цены, суммы (в зависимости от константы ВариантПересчетаПриИзмененииСуммы (перечисление)), скидки – в документах реализации. При изменении ВидаЦены – запрос на замену цен и пересчет в случае согласия.
4) созданы РН Закупки (оборотный) и ОстаткиНоменклатуры (остаточный). Сделаны движения в документе ПоступлениеТоваров, при движениях количество пересчитывается в базувую ед.из.
5) самый лучший способ не дать пользователю сделать что-то не так – это вообще закрыть доступ к этому или дать выбор только из того что можно выбрать. в модуле объекта спр номенклатура создана процедура
Функция ЕстьВозможностьИзменитьБазувуюЕдиницу() Экспорт
Запрос = Новый Запрос;
Запрос.Текст = ”
|ВЫБРАТЬ ПЕРВЫЕ 1
| ОстаткиНоменклатуры.Номенклатура
|ИЗ
| РегистрНакопления.ОстаткиНоменклатуры КАК ОстаткиНоменклатуры
|ГДЕ
| ОстаткиНоменклатуры.Номенклатура = &Номенклатура
|”;
Запрос.УстановитьПараметр(“Номенклатура”, Ссылка);
Результат = Запрос.Выполнить();
Возврат Результат.Пустой();
КонецФункции // ЕстьВозможностьИзменитьБазувуюЕдиницу
Функция ЕстьВозможностьИзменитьБазувуюЕдиницу() Экспорт
Запрос = Новый Запрос;
Запрос.Текст = “
|ВЫБРАТЬ ПЕРВЫЕ 1
| ОстаткиНоменклатуры.Номенклатура
|ИЗ
| РегистрНакопления.ОстаткиНоменклатуры КАК ОстаткиНоменклатуры
|ГДЕ
| ОстаткиНоменклатуры.Номенклатура = &Номенклатура
|”;
Запрос.УстановитьПараметр(“Номенклатура”, Ссылка);
Результат = Запрос.Выполнить();
Возврат Результат.Пустой();
КонецФункции // ЕстьВозможностьИзменитьБазувуюЕдиницу
и в зависимости от возврата меняется доступность поля БазоваяЕдиницаИзмерения, а так же проверяется при записи в модуле объекта – защита от программного изменения.
6) Создан журнал, для вывода сумм в документах поступления/реализации создан реквизит СуммаДокумента, заполняющийся при записи документа.
Решение ДЗ №8
1. Создал независимый РегистрСведений МенеджерыКлиентов с периодичностью в пределах секунды. У регистра установил Измерение Клиент (спр. Контрагенты) и ресурс Менеджер (спр. Пользователи). В форме элемента спр-ка Контрагенты создал реквизит Менеджер (спр. Пользователи) и вывел его на форму. Далее в модуле формы определил ф-цию ПолучитьМенеджера() с директивой НаСервереБезКонтекста и с параметром ссылка на текущего Контрагента. Данная ф-ция находит текущего менеджера для данного клиента из рег-ра МенеджерыКлиентов. В ф-ции использую метод ПолучитьПоследнее, в котором указываю текущую дату и отбор по текущему клиенту. Далее в событии ПриОткрытии с помощи ф-ции ПолучитьМенеджера присваиваю реквизиту формы Менеджер значение.
Считаю так, что если в форме установлен новый менеджер и выбран другой, то необходимо его записать в регистр. Для этого в событии МенеджерПриИзменении устанавливаю Модифицированность=Истина. Затем в событии ПослеЗаписиНаСервере реализую алгоритм, который проверяет если форма модифицирована и Менеджер значение заполнено и оно отличается от значения возвращаемого функцией ПолучитьМенеджера, то необходимо добавить запись в регистр МенеджерыКлиентов.
Для записи использую класс РегистрСведенийМенеджерЗаписи.
2. В документе КонтактСКлиентом создал реквизит Менеджер (спр. Пользователи). В процедуре ОбработкаЗаполнения модуля объекта документа с помощью ф-ии общего серверного модуля СинхронизацияПользователей присваиваю значение реквизиту Менеджер.
Далее для реализации задачи «запись Менеджера при первом контакте» в процедуре ОбработкаПроведения решаю использовать ранее созданную ф-цию ПолучитьМенеджера(), которая возвращает ссылку спр. Пользователи и затем сравнивать её на пустую. Если ссылка пустая, то считать что ранее контактов не было, и производить запись в регистр сведений МенеджерыКлиентов. Для это ф-цию ПолучитьМенеджера() выношу в общий модуль ОбщиеФункцииСервер с признаком Экспорт. Изменяю где нужно ранее написанный код. Для добавления записи в регистр также использую класс РегистрСведенийМенеджерЗаписи.
Для реквизитов Контрагент и Менеджер выставляю свойство «ПроверкаЗаполнения» в значение «Выдавать ошибку». Для рек-та КонтактноеЛицо в своистве «Связи параметров выбора» определяю Отбор.Владелец(Контрагент).
3. Для хранения цен создал регистр сведений ЦеныНоменклатуры. В рег-ре определил 3 измерения: Номенклатура (спр. Номенклатура), Прайс с типом спр-к Прайсы ( который предварительно создал в конфигурации) и ЕдиницаИзмерения (спр. КлассификаторЕдиницИзмерения), а также определил ресурс цена с типом число.
4. Создал спр. Прайсы и определил для всех документов реквизит с данным типом. Вынес реквизит на формы. Далее на форме документов создал команду «Заполнение Цен» и вывел её на командную панель. В процедуре действия команды вызываю серверную процедуру модуля формы в которой в свою очередь вызываю функцию общего северного модуля ЗаполнитьЦены. В ф-цию передаются параметры ТЗ(табличная часть) и значение рек-та Прайс.Ф-ция возвращает ТЗ. Далее данная ТЗ с помощью метода Загрузить заполняет табличную часть документа. Внутри ф-ции ЗаполнитьЦены использую запрос с классом МенеджерВременныхТаблиц. Сначала получаю временную таблицу из ТЗ. Далее использую левое соединение с временной таблицей и регистром сведений ЦеныНоменклатуры по полям Номенклатура и Прайс. Так таб. Части во всех 3-х документов одинаковые, то использую эту функцию во всех документах.
Задания по юзабилити выполнил, проблем не было.
5. Создал Регистр накопления ОстаткиТоваров с видом Остатки. Измерения Номенклатура, Качество и Ресурс Количество. С помощью конструктора создал движения. В док ПоступлениеТоваров приход, а в АвансовыйОтчет и РеализацияТоваров расход.
6. Создал оборотный регистр Закупки, регистратор ПоступлениеТоваров. Измерения Поставщик и Номенклатура, ресурсы количество и сумма. С помощью контруктора создал движения в док ПоступлениеТоваров.
7. В событии НачалоВыбора элемента БазоваяЕдиница (спр. Номенклатура), вызываю серверную функцию ЕстьДвижения. Если ф-ция возвращает истина, то СтандартнаяОбработка=ложь. В ф-ции создал запрос по регистрам РегистрНакопления.Закупки и РегистрНакопления.ОстаткиТоваров, которые объединил.
Задание выполнил. Наконец-то! Тяжело догонять. Очень понравилось задание. Временами, чтобы не отстать окончательно от группы, Экономя время, подсматривал в решение. Контроль изменения базовой единицы, вероятно, занял бы у меня слишком много времени, если бы решал самостоятельно.
Задание выполнил, правда немного с опозданием. Сейчас приступлю к просмотру решения дз №8 и работы над ошибками. Спасибо.
Задание выполнено. Задание понравилось, решалось легко. Дополнительно для документов сделала пересчет цены при изменении единицы измерения.
выполнено, забыл что сумму в журнал нужно выводить через рекв документа. и как отменить изменение реква, при открытии отнимаю возможность изменения. забыл про свойство данные подвала(= не сложное дз какое то
Привязка менеджеров компании к клиентам реализовал на регистре сведений “КлинетыМенеджеров”. Регистр периодический, независимый. Измерения: Менеджер (тип Справочник “Пользователи”), ресурсы: Контрагент (тип справочник “Контрагенты”).
Документ “КонтактСКлиентом”. При создании нового документа реквизит “Менеджер” заполняется в процедуре “ОбработкаЗаполнения”. Код при проведении документа:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Отбор = Новый Структура(“Менеджер”, Менеджер);
Клиент = РегистрыСведений.КлиентыМенеджеров.ПолучитьПоследнее(Дата, Отбор);
Если НЕ ЗначениеЗаполнено(Клиент.Контрагент) Тогда
Запись = РегистрыСведений.КлиентыМенеджеров.СоздатьМенеджерЗаписи();
Запись.Период = Дата;
Запись.Менеджер = Менеджер;
Запись.Контрагент = Контрагент;
Запись.Записать();
КонецЕсли;
КонецПроцедуры
Процедура ОбработкаУдаленияПроведения(Отказ)
Запись = РегистрыСведений.КлиентыМенеджеров.СоздатьМенеджерЗаписи();
Запись.Период = Дата;
Запись.Менеджер = Менеджер;
Запись.Контрагент = Контрагент;
Запись.Удалить();
КонецПроцедуры
Для хранения цен созданы: перечисления “ТипыЦен”. Регистр сведений “ЦеныНоменклатуры” независимый, периодический (периодичность день), измерения “Номенклатура” (тип справочника “Номенклатура” и “ТипЦены” (тип перечисление “ТипыЦен”).
Реализация автоматической подстановки цен в документах по учету ТМЦ. В общем серверном модуле создана функция получения цены и единицы измерения, которая вызывается при изменении номенклатуры.
Процедура ТоварыНоменклатураПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ЦенаЕИ = ПроцедурыНаСервере.ПолучитьЦенуЕдиницуИзмеренияТовара(Объект.Дата, ТД.Номенклатура, Объект.ТипЦены);
ТД.ЕдиницаИзмерения = ЦенаЕИ.ЕдиницаИзмерения;
ТД.Цена = ЦенаЕИ.Цена;
КонецПроцедуры
Пересчет суммы при по цене и количеству
&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ТД.Сумма = ПроцедурыНаКлиенте.ПересчетатьСумму(ТД);
КонецПроцедуры
&НаКлиенте
Процедура ТоварыЦенаПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ТД.Сумма = ПроцедурыНаКлиенте.ПересчетатьСумму(ТД);
КонецПроцедуры
Функция ПересчетатьСумму(СтрокаТД)Экспорт
Возврат СтрокаТД.Количество * СтрокаТД.Цена;
КонецФункции
Пересчет количества или цены. Созданы перечисление “ВариантыПересчетаПоСумме”, констанат “ВариантПересчетаПоСумме”
Пример кода:
&НаКлиенте
Процедура ТоварыСуммаПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ПроцедурыНаСервере.ПересчетатьПоСумме(ТД.Количество, ТД.Цена, ТД.Сумма);
КонецПроцедуры
Процедура ПересчетатьПоСумме(Количество, Цена, Сумма)Экспорт
ВариантПересчета = Константы.ВариантПересчетаПоСумме.Получить();
Если ВариантПересчета = Перечисления.ВариантПересчетаПоСумме.ПересчетКоличества Тогда
Количество = Сумма / Цена;
ИначеЕсли ВариантПересчета = Перечисления.ВариантПересчетаПоСумме.ПересчетЦены Тогда
Цена = Сумма / Количество;
КонецЕсли;
КонецПроцедуры
Обязательно заполнения номенклатуры, единицы измерения и количества. Особенность здесь в том, что для номенклатуры типа “Услуга” единицы измерения может и не быть. Поэтому проверка заполнения единицы измерения реализована программно и вынесена в общий серверный модуль:
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
Отказ = ЗаполнениеДокументовСервер.ПроверитьЗаполнениеЕдиницыИзмерения(ЭтотОбъект, ПроверяемыеРеквизиты);
КонецПроцедуры
Функция ПроверитьЗаполнениеЕдиницыИзмерения(ДокОбъект, ПроверяемыеРеквизиты) Экспорт
ЗначениеВозврата = Ложь;
ИндексЕдиницыИзмерения = ПроверяемыеРеквизиты.Найти(“Товары.ЕдиницаИзмерения”);
Если ИндексЕдиницыИзмерения <> Неопределено Тогда
ПроверяемыеРеквизиты.Удалить(ИндексЕдиницыИзмерения);
Для каждого Товар Из ДокОбъект.Товары Цикл
Если Товар.Номенклатура.ВидНоменклатуры <> Перечисления.ВидыНоменклатуры.Услуга Тогда
Если НЕ ЗначениеЗаполнено(Товар.ЕдиницаИзмерения) Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = “Не заполнена колонка “”Единица измерения”” в строке ” + Товар.НомерСтроки + ” списка “”Товары”””;
Сообщение.Поле = “Товары[” + (Товар.НомерСтроки – 1) + “].ЕдиницаИзмерения”;
Сообщение.УстановитьДанные(ДокОбъект);
Сообщение.Сообщить();
ЗначениеВозврата = Истина;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Возврат ЗначениеВозврата;
КонецФункции
Созданы регистры накопления. Регистр остатков “ОстаткиТоваров” с измерениями “Номенклатура” (тип справочник “Номенклатура”), “Качество” (тип справочник “Качества”) и ресурсами Количество. Регистраторы “ПоступлениеТоваров” и “АвансовыйОтчет”.
Регистр оборотов “ЗакупкиТоваров” с измерениями “Номенклатура” (тип справочник “Номенклатура”) и “Контрагент” (тип справочник “Контрагент”) и ресурсами Количество, Сумма. Регистраторы “ПоступлениеТоваров”.
Особенность проведения по регистру “ОстаткиТоваров” в том, что необходимо пересчитывать количество поступившего товара, если его единица измерения отлична от базовой. Реализация
Процедура ОбработкаПроведения(Отказ, Режим)
Движения.ОстаткиТоваров.Записывать = Истина;
Движения.ЗакупкиТоваров.Записывать = Истина;
Для Каждого ТекСтрокаТовары Из Товары Цикл
Номенклатура = ТекСтрокаТовары.Номенклатура;
Количество = ТекСтрокаТовары.Количество;
ЕдиницаИзмерения = ТекСтрокаТовары.ЕдиницаИзмерения;
Движение = Движения.ОстаткиТоваров.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Номенклатура = Номенклатура;
Движение.Качество = ТекСтрокаТовары.Качество;
Если Номенклатура.БазоваяЕдиницаИзмерения <> ЕдиницаИзмерения Тогда
Количество = ЗаполнениеДокументовСервер.ПересчитатьКоличествоВБазовуюЕдиницу(Номенклатура, ЕдиницаИзмерения, Количество);
КонецЕсли;
Движение.Количество = Количество;
Движение = Движения.ЗакупкиТоваров.Добавить();
Движение.Период = Дата;
Движение.Номенклатура = ТекСтрокаТовары.Номенклатура;
Движение.Контрагент = Контрагент;
Движение.Количество = ТекСтрокаТовары.Количество;
Движение.Сумма = ТекСтрокаТовары.Сумма;
КонецЦикла;
КонецПроцедуры
Функция ПересчитатьКоличествоВБазовуюЕдиницу(Номенклатура, ЕдиницаИзмерения, Количество) Экспорт
ЗначениеВозврата = Количество;
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| ЕдиницыИзмеренияНоменклатуры.КоэффициентПересчета
|ИЗ
| Справочник.ЕдиницыИзмеренияНоменклатуры КАК ЕдиницыИзмеренияНоменклатуры
|ГДЕ
| ЕдиницыИзмеренияНоменклатуры.Владелец = &Владелец
| И ЕдиницыИзмеренияНоменклатуры.Ссылка = &ЕдиницаИзмеренияПоКлассификатору”;
Запрос.УстановитьПараметр(“Владелец”, Номенклатура);
Запрос.УстановитьПараметр(“ЕдиницаИзмеренияПоКлассификатору”, ЕдиницаИзмерения);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
ЗначениеВозврата = Количество * ВыборкаДетальныеЗаписи.КоэффициентПересчета;
КонецЕсли;
Возврат ЗначениеВозврата;
КонецФункции
Запрет изменения базовый единицы измерения в номенклатуре при наличии движения реализован так:
&НаКлиенте
Процедура БазоваяЕдиницаИзмеренияНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
СтандартнаяОбработка = НетДвиженияПоРегистрамНакопления(Объект.Ссылка);
Если НЕ СтандартнаяОбработка Тогда
Сообщить(“Есть движения по товару. Базовую единицу изменять нельзя”);
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция НетДвиженияПоРегистрамНакопления(Номенклатура)
Отбор = Новый Структура;
Отбор.Вставить(“Номенклатура”, Номенклатура);
ВыборкаЗакупкиТоваров = РегистрыНакопления.ЗакупкиТоваров.Выбрать(,,Отбор);
ВыборкаОстаткиТоваров = РегистрыНакопления.ОстаткиТоваров.Выбрать(,,Отбор);
ЗначениеВозврата = ВыборкаОстаткиТоваров.Следующий() ИЛИ ВыборкаЗакупкиТоваров.Следующий();
Возврат НЕ ЗначениеВозврата;
КонецФункции // НетДвиженияПоРегистрамНакопления()
Отчет по заданию 8 ( С задержкой по сроку —Грипп вмешался)
Привязку осуществляем в справочникие Контрагенты, посредством дополнительного реквизита «Менеджер»
Для выполнения второго пункта задания организуем проведение документа «РаботаСКлиентами»
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| КонтактСКлиентом.Ссылка
|ИЗ
| Документ.КонтактСКлиентом КАК КонтактСКлиентом
|ГДЕ
| КонтактСКлиентом.Контрагент = &Контрагент”;
Запрос.УстановитьПараметр(“Контрагент”, Контрагент);
Результат = Запрос.В ыполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Если НЕ ВыборкаДетальныеЗаписи.Следующий() Тогда
//Записать в справочник Контрагенты менеджера
Справочники.Контрагенты.НайтиПоНаименованию(Контрагент).Ссылка.Менеджер = Менеджер;
КонецЕсли
Для решения задачи назначения текущего пользователя создаем процедуру
ПриСозданииНаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Менеджер = ПользователиИнформационнойБазы.ТекущийПользователь();
Объект.менеджер = Справочники.Пользователи.НайтиПоНаименованию(Менеджер);
КонецПроцедуры
Организуем РС Измерения: Номенклатура, ТипЦен Ресурс Значение
Для этого создаем Справочник «ТипЦен»
Пункты Юзобилити для работы с документом выполнил все работает кроме:
Пересчет цены и уколичества при изменении суммы …….непонятно как можно менять по функции аргументы т.е сумма то является производной.
РегистрНакопления по Остаткам создал
Объект о закупках определен РегистрНакопления-обороты
Для реализации запрета изменения единиц измереня товара
Дорабатывае процедуру Справочника Номенклатуры ПриЗаписи:
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| РегистрОстатковТоваровОстатки.Номенклатура
|ИЗ
| РегистрНакопления.РегистрОстатковТоваров.Остатки КАК РегистрОстатковТоваровОстатки
|ГДЕ
| РегистрОстатковТоваровОстатки.Номенклатура = &Номенклатура”;
Запрос.УстановитьПараметр(“Номенклатура”, Ссылка);
Результат = Запрос.Выполнить().Выбрать();
Если Результат.Следующий() Тогда
Отказ = ИСТИНА;
КонецЕсли;
При создании журнала вопросов не возникло
>непонятно как можно менять по функции аргументы
См. решение.
Выполнено.
Вопросы, которые возникли в процессе:
1. Порядок измерений в оборотном регистре “Закупки” – “Номенклатура”, “Контрагент” – поставил первым “Номенклатура” как более селективное, хотя зависит от использования регистра.
2. Получение данных с разной детализацией для движения по регистрам “ОстаткиТоваров” и “Закупки” – для первого “Номенклатура”, “Качество”, для второго – “Номенклатура”. Проблему не решал – делается N движений по товару при наличии N строк по товару в документе.
3. Заметил, что “Регистратор” заполняется при проведении без заполнения в коде.
4. При построении “Журнал документов” использовал для получения суммы запрос, можно было добавить реквизит “ИтогоСумма” в документы “Приходная”, “АО”?
Добрый день!
Попробую описать проблему более просто…
В главе 8 Блока 2 приведется пример в котором на при нажатии кнопки проводится документ и в собственной процедуре проведения мы меняем комментарии и с помощью РеквизитФормыВЗначение и Значение в реквизитФормы он отображается на форме
Но все это делается на уровне модуля формы….
А если комментарий меняется в модуле обьекта?
Создаем Справочник…
У него реквизиты Комментарий, строка 50
и реквизит Отказ отЗаписи Булево
В Модуле объекта
Процедура ПередЗаписью(Отказ)
Комментарии=”Этот Комментарии должен отразиться на форме”;
Отказ=ОтказОтЗаписи;
КонецПроцедуры
Далее открываем форму, вводим наименование, ставим ОтказОтзаписи. Пробуем сохранить новый элемент. Получаем отказ. Однако в процедуре ПередЗаписью мы поменяли Комментарии, но он не отразился не форме. теперь если снять отказ от записи, сохранить элемент справочника и заново открыть то комментарий появится.
можно ли теперь каким-то образом передать на форму измененный комментарии или это только возможно реализовать в модуле формы.
Проблема в описанной ситуации как раз в отказе.
Ведь если его убрать, то все работает?
Что происходит: вы системе сообщаете, что нужно откатить транзакцию записи элемента справочника, соответственно все изменения будут отменены. В том числе изменение реквизитов формы.
Выполнено.
Добавлен периодический регистр сведений “Менеджеры контрагентов”. Если менеджер при записи контакта не соответствует срезу последних, то выводится предупреждение о невозможности провести контакт. Если записей по данному контрагенту в данном регистре нету, то документ проводится и запись добавляется.
Цены хранятся в периодическом регистре сведений. Измерения – ТипЦены, Номенклатура. Ресурс – Цена
При добавлении номенклатуры в ТЧ документов происходит получение цены и ед.изм. (доработана процедура, чтобы ед изм и цена получались за один серверный вызов – возвращается структура)
Константа пересчета цены или количества по сумме получается в общем модуле с повторным использованием возвр. знач. “на время сеанса”(метод универсальный, передается имя любой константы)
Итоговая сумма выводится в подвал колонки ТЧ сумма. Так же добавлен реквизит “СуммаДокумента”, который автоматически заполняется в обработчике “ПередЗаписью”, для нужд журнала.
Созданы регистры остатков(Изм: Номенклатура, Качество) и оборотов(Изм: Поставщик, Номенклатура) для хранения остатков товаров и закупок, соответственно. Понятно, что нужно еще делать проведение для реализации, но не будем бежать впереди паровоза :)
Данные из документов для записи в регистры получаются одним запросом и загружаются через таблицу значений в набор записей регистра.
Проверка и запрет изменения базовой ед. изм. реализована с помощью метода НайтиПоСсылкам():
<code>
ЭтоНовый = ЭтоНовый();
Если Не ЭтоНовый И БазоваяЕдиницаИзмерения <> Ссылка.БазоваяЕдиницаИзмерения Тогда
МассивСсылок = Новый Массив;
МассивСсылок.Добавить(Ссылка);
ТабСсылок = НайтиПоСсылкам(МассивСсылок);
мдРегНакопления = Метаданные.РегистрыНакопления;
мдРегСведений = Метаданные.РегистрыСведений;
Для Каждого Элемент Из Табссылок Цикл
обМетаданные = Элемент.Метаданные;
Если мдРегНакопления.Содержит(обМетаданные) Или мдРегСведений.Содержит(обМетаданные) Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = “Нельзя менять базовую единицу измерения.”;
Сообщение.Поле = “Объект.БазоваяЕдиницаИзмерения”;
Сообщение.Сообщить();
Отказ = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
</code>
1. В справочнике “Контрагенты” добавляем реквизит “Менеджер” с типом данных “Пользователи”
2. Копируем реквизит в документ “Контакт с клиентом” с указание обязательности заполенния.
3. Добавляем управляемую форму для документа со следующим кодом:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если ПустаяСтрока(Объект.ВерсияДанных) Тогда
Объект.Менеджер = глТекущийПользователь;
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПриЗаписиНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
Контрагент = Объект.Контрагент;
Если Контрагент.Менеджер.Пустая() Тогда
МенеджерКонтрагентаОбъект = Контрагент.ПолучитьОбъект();
МенеджерКонтрагентаОбъект.Менеджер = ТекущийОбъект.Менеджер;
МенеджерКонтрагентаОбъект.Записать();
КонецЕсли;
КонецПроцедуры
4. Добавляем справочник типы цен
5. Довляем периодический РС “ЦеныНоменклатуры” (Измерения “Номенклатура, ТипЦены”, Ресурсы “Цена”)
6. Добавляем во все необходимые документы реквизит “ТипЦен” и выводим его на форму
7. В модуле “ОбщиеФункцииСервер” добавляем функции:
Функция ПолучитЦенуНоменклатуры(Номенклатура, ТипЦены, Дата = Неопределено)Экспорт
Если Дата = Неопределено Тогда
Дата = ТекущаяДата();
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| ЦеныНоменклатурыСрезПоследних.Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
| &Дата,
| Номенклатура = &Номенклатура
| И ТипЦены = &ТипЦены) КАК ЦеныНоменклатурыСрезПоследних”;
Запрос.УстановитьПараметр(“Дата”, Дата);
Запрос.УстановитьПараметр(“Номенклатура”, Номенклатура);
Запрос.УстановитьПараметр(“ТипЦены”, ТипЦены);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
Возврат ВыборкаДетальныеЗаписи.Цена;
Иначе
Возврат 0;
КонецЕсли;
КонецФункции
Функция УменьшатьКоличествоПриИзмененииСуммы()Экспорт
Возврат Константы.УменьшатьКоличествоПриИзмененииСуммы.Получить() ;
КонецФункции
Функция ПолучитьЕдиницуИзмерения(Товар)Экспорт
//{{КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА
// Данный фрагмент построен конструктором.
// При повторном использовании конструктора, внесенные вручную изменения будут утеряны!!!
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| ЕдиницыИзмеренияНоменклатуры.Ссылка
|ИЗ
| Справочник.ЕдиницыИзмеренияНоменклатуры КАК ЕдиницыИзмеренияНоменклатуры
|ГДЕ
| ЕдиницыИзмеренияНоменклатуры.Владелец = &Товар
| И ЕдиницыИзмеренияНоменклатуры.ЕдиницаПоКлассификатору = &ЕдиницаПоКлассификатору
| И (НЕ ЕдиницыИзмеренияНоменклатуры.ПометкаУдаления)”;
Запрос.УстановитьПараметр(“ЕдиницаПоКлассификатору”, Товар.БазоваяЕдиница);
Запрос.УстановитьПараметр(“Товар”, Товар);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
Возврат ВыборкаДетальныеЗаписи.Ссылка;
Иначе
Возврат Справочники.ЕдиницыИзмеренияНоменклатуры.ПустаяСсылка();
КонецЕсли;
//}}КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА
КонецФункции // ПолучитьЕдиницуИзмерения()
8. В модуле “ОбщиеФункцииКлиент” добавляем процедуру
Процедура ПересчитатьСумму(Строка)Экспорт
Строка.Сумма = Строка.Количество *Строка.Цена;
КонецПроцедуры
Процедура ПриИзмененииПоСтроке(ТД,ЭтоИзменениеНоменклатуры, типЦены, Дата)Экспорт
Если ЭтоИзменениеНоменклатуры = Истина Тогда
ТД.Цена = ОбщиеФункцииСервер.ПолучитЦенуНоменклатуры(ТД.Номенклатура, ТипЦены, Дата);
ТД.ЕдиницаИзмерения = ОбщиеФункцииСервер.ПолучитьЕдиницуИзмерения(ТД.Номенклатура);
КонецЕсли;
ПересчитатьСумму(ТД);
КонецПроцедуры
Процедура ОбработатьИзменениеСуммы(Строка)Экспорт
Сообщение = Новый СообщениеПользователю;
Сообщение.Поле = “Товар[“+Строка.НомерСтроки+”].”;
Если ОбщиеФункцииСервер.УменьшатьКоличествоПриИзмененииСуммы() Тогда
Цена = Строка.Цена;
Если Цена = 0 Тогда
Сообщение.Текст = “Не указана цена!”;
Сообщение.Поле = Сообщение.Поле+”Цена”;
Сообщение.Сообщить();
Иначе
Строка.Количество = Строка.Сумма/Цена;
КонецЕсли;
Иначе
Количество = Строка.Количество;
Если Количество = 0 Тогда
Сообщение.Текст = “Не указано количество!”;
Сообщение.Поле = Сообщение.Поле+”Количество”;
Сообщение.УстановитьДанные(Строка);
Сообщение.Сообщить();
Иначе
Строка.Цена = Строка.Сумма/Количество;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
9. В обработчиках при изменении номенклатуры всех нужных документов добавляем код:
ТД.Цена = ОбщиеФункцииСервер.ПолучитЦенуНоменклатуры(ТД.Номенклатура, Объект.ТипЦены, Объект.Дата);
ОбщиеФункцииКлиент.ПересчитатьСумму(ТД);
10. Добавляем константу “УменьшатьКоличествоПриИзмененииСуммы”
11. Для вывода итога воспользуемся итогом полем табличной части Товары (Объект.Товары.ИтогСумма)
12. В реквизитах “Номенклатура, ед.изм., количество” указываем обязательность заполнения.
13. Для реквизита “КонтактноеЛицо” указываем связь параметра выбора Отбор.Владелец(Объект.Контрагент)
14. Добавляем РН “ОстаткиПоТоварам”, измерения “Номенклатура, Качество”, ресурс “Количество”
15. Добавляем оборотный РН “Закупки”, измерения “Контрагент, Номенклатура”, ресурс “Количество, Стоимость”
16. С помощью конструкторов добавляем обработчики проведения.
17. Для проверки запрета изменения баз.ед.изм. добавляем форму справочника со следующим обработчиком:
&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
Если Не ТекущийОбъект.ЭтоНовый() Тогда
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ 1
| ЗакупкиОбороты.Номенклатура,
| ЗакупкиОбороты.Номенклатура.БазоваяЕдиница КАК БазоваяЕдиница
|ИЗ
| РегистрНакопления.Закупки.Обороты(, , , Номенклатура = &Номенклатура) КАК ЗакупкиОбороты”;
Запрос.УстановитьПараметр(“Номенклатура”, ТекущийОбъект.Ссылка);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий() И ВыборкаДетальныеЗаписи.БазоваяЕдиница <> ТекущийОбъект.БазоваяЕдиница Тогда
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
18. Добавляем журанал документов.
Создала регистр Менеджеры контрагентов: независимый, периодичность в пределах дня.
В документ КонтактСКлиентом добавила реквизит Менеджер. В процедуре Обработка заполнения присваиваю ему значение текущего пользователя.
В модуле проведения по регистру Менеджеры контрагентов получаю срез последних по контрагенту, и если количество записей=0, добавляю новую запись 3. Создала справочник ТипыЦен. Документ «ПрайсЛист» с реквизитом шапки ТипЦены = Справочнику ТипыЦен и табличной частью Товары с реквизитами Номенклатура и Цена.
Создала регистр «ЦеныНоменклатуры», подчиненный документу ПрайсЛист с периодичностью По позиции регистратора. В модуле проведения документа ПрайсЛист добавляю записи в регистр ЦеныНоменклатуры. Процедуру Обработка проведения создавала с помощью конструктора.
Добавила в шапку ПоступлениеТоваров и РеализацияТоваров реквизит ТипЦены= СправочникСсылка.ТипыЦен. В процедуру при изменении реквизита Номенклатура добавила вызов функции получения цены:
<code>
&НаСервереБезКонтекста
Функция ПолучитьЦенуПоПрайсу(Номенклатура,ТипЦены,ДатаДок)
ТекЦена = РегистрыСведений.ЦеныНоменклатуры.ПолучитьПоследнее(ДатаДок,Новый Структура(“Номенклатура,ТипЦены”,Номенклатура,ТипЦены));
Возврат ТекЦена.Цена;
КонецФункции
</code>
Добавила константу ПересчетКоличестваПрИзмененииСуммы – булево.
В модуль ОбщиеФункцииКлиент добавила процедуру Пересчет
<code>
Процедура Пересчет(ТД,ИмяКолонки=””) Экспорт
Если ИмяКолонки = “Сумма” Тогда
Если ОбщиеФункцииСервер.ПересчитыватьКоличество() Тогда
ТД.Количество = ТД.Сумма/ТД.Цена;
иначе
ТД.Цена = ТД.Сумма/ТД.Количество;
КонецЕсли;
иначе
ТД.Сумма = ТД.Цена*ТД.Количество;
КонецЕсли;
КонецПроцедуры
</code>
Которую вызываю из процедур изменения реквизитов: Количество, Цена и Сумма.
Создала регистр накопления ОстаткиТоваров с измерениями Номенклатура, Качество и ресурсом Количество. С помощью конструктора создала обработку проведения документа Поступление товаров. При проведении пересчитываю количество в базовые единицы измерения. Коэффициент пересчета получаю из свойств Единицы измерения табличной части.
Создала оборотный регистр накопления Закупки с измерениями Поставщи, Товар и ресурсами Количество, Стоимость. Добавила в обработку проведения ПоступленияТоваров движения по регистру.
<code>
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
СуммаДокумента = Товары.Итог(“Сумма”);
КонецПроцедуры
Процедура ОбработкаПроведения(Отказ, Режим)
Движения.ОстаткиТоваров.Записывать = Истина;
Движения.Закупки.Записывать = Истина;
Для Каждого ТекСтрокаТовары Из Товары Цикл
Движение = Движения.ОстаткиТоваров.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Номенклатура = ТекСтрокаТовары.Номенклатура;
Движение.Качество = ТекСтрокаТовары.Качество;
Движение.Количество = ПолучитьКоличество(ТекСтрокаТовары.Количество,ТекСтрокаТовары.ЕдиницаИзмерения,ТекСтрокаТовары.Номенклатура);
Движение.ЕдИзм = ТекСтрокаТовары.ЕдиницаИзмерения;
Закупки = Движения.Закупки.Добавить();
Закупки.ВидДвижения =ВидДвиженияНакопления.Приход;
Закупки.Период = Дата;
Закупки.Поставщик = Контрагент;
Закупки.Товар = ТекСтрокаТовары.Номенклатура;
Закупки.Количество = ТекСтрокаТовары.Количество;
Закупки.Стоимость = ТекСтрокаТовары.Сумма;
КонецЦикла;
КонецПроцедуры
Функция ПолучитьКоличество(Количество,ЕдиницаИзмерения,Номенклатура)
Если ЕдиницаИзмерения.ЕдиницаПоКлассификатору=Номенклатура.БазоваяЕдиница Тогда
Возврат Количество;
иначе
Возврат Количество*ЕдиницаИзмерения.К;
КонецЕсли;
КонецФункции
</code>
В справочник Номенклатура в модуле формы проверяю при изменении базовой единицы наличие движений в регистрах Закупка и Остатки товаров:
<code>
&НаКлиенте
Перем ТекущаяБазоваяЕдиница;
&НаКлиенте
Процедура БазоваяЕдиницаПриИзменении(Элемент)
Если ЕстьДвижения(Объект.Ссылка) Тогда
Сообщить(“Нельзя изменить базовую единицу измерения!”);
Объект.БазоваяЕдиница = ТекущаяБазоваяЕдиница;
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ЕстьДвижения(Номенклатура)
Запрос = Новый Запрос;
Запрос.Текст = “ВЫБРАТЬ
| ОстаткиТоваров.Регистратор КАК Регистратор
|ИЗ
| РегистрНакопления.ОстаткиТоваров КАК ОстаткиТоваров
|ГДЕ
| ОстаткиТоваров.Номенклатура = &Товар
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| Закупки.Регистратор
|ИЗ
| РегистрНакопления.Закупки КАК Закупки
|ГДЕ
| Закупки.Товар = &Товар”;
Запрос.УстановитьПараметр(“Товар”,Номенклатура);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий()Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ТекущаяБазоваяЕдиница = Объект.БазоваяЕдиница;
КонецПроцедуры
</code>
Создала журнал документов ДокументыЗакупки. Включила в него документы Авансовый отчет и Поступление товаров. Указала графу Контрагент и Сумма = реквизиту документа СуммаДокумента. В документы ПоступлениеТовара, Авансовый отчет и реализация товаров добавлен реквизит Сумма документа. В модуле документа в процедуре ПередЗаписью заполняю его значением итога по колонке табличной части Сумма.
1. Для справочника Контрагенты создал реквизит Менеджер. В обработке заполнения документа КонтактСКлиентом использовал функцию ОбщиеФункцииСервер.СинхронизацияПользователей() для подстановки текущего пользователя. В обработке проведения проверяю на существование других документов типа КонтактСКлиентом для текущего контрагента. Для реквизита КонтактноеЛицо установлена связь параметров выбора по контрагенту.
2. Создал справочник ТипыЦенНоменклатуры. Создал периодический(в пределах дня) независимый регистр сведений ЦеныНоменклатуры, в котором указал два измерения ТипЦеныНоменклатуры, Номенклатура и ресурс Цена.
3. Добавил реквизит Прайс с типом СправочникСсылка.ТипыЦенНоменклатуры в документы поступления и реализации. В обработчиках события ТоварыНоменклатураПриИзменении форм документов поступления и реализации разместил код для нахождения базовой единицы измерения и цены (согласно выбранному прайс-листу) номенклатуры. Создал константу типа Булево для выбора варианта пересчета количества и цены табличной части документов. Написал необходимы код для пересчета. Для отображения итога по сумме документа, использовал подвал табличной части. Контактное лицо связал с контрагентом связью параметров выбора.
4. Создал регистры накопления ОстаткиТовара и Закупки с необходимыми измерениями и ресурсами. Воспользовался конструктором движений для написания кода заполнения регистров. При проведении документов, пересчитываю количество товара в базовую единицу.
5. В обработчике БазоваяЕдиницаПриИзменении формы справочника Номенклатура проверяю изменил ли пользователь значение базовой единицы. Для этого сравниваю текущее значение на форме ( Объект.БазоваяЕдиница) со старым значением в базе данных. Если значение базовой единицы было изменено, тогда проверяю, а были ли движения по номенклатуре. Эту проверку осуществляю с помощью объединенных(ОБЪЕДИНИТЬ ВСЕ) запросов к регистрам накопления.
6. Создал Журнал документов закупки. Создал реквизит СуммаДокумента для документов Закупка и АвансовыйОтчет. Этот реквизит заполняется в обработчике ПередЗаписью модулей документов: СуммаДокумента = Товары.Итог(“Сумма”).
Задание выполнил, но не доконца. Не получилось сделать обнавление или пересчёт табличной части, например если пользователь уже забил табличную часть документа с одним видом цен, а потом вдруг хочет другие. Так же не понял пересчёт кол-ва или цены с помощью константы.
С константой разобрался
Задание выполнено.
1.В справочнике «Контрагент» создал реквизит «Менеджер контрагента» тип «Пользователи».
2.В документе «КонтактСКлиентом» создан реквизит «Менеджер». В свойство «Проверка заполнения» установлено «Выдавать ошибку», такое же значение свойства «Проверка заполнения» установлено для реквизита «Контрагент». При проведении документа проверяется, если у контрагента не заполнен реквизит «Менеджер контрагента», то для контрагента устанавливаем менеджера из документа.
3.Создан справочник «Типы цен». Создан регистр сведений «Цены номенклатуры»: Измерения – Номенклатура (ведущее), ТипЦены; Ресурс – Цена. Регистр независимый с периодичностью день.
4.В документы закупки и отгрузки добавил реквизит «Тип цены». Для документов реализовано следующее:
5.Создан регистр остатков «Остатки номенклатуры». Измерения – Номенклатура, Качество. Ресурс – количество.
6.Создан регистр оборотов «Закупки». Измерения – Номенклатура, Контрагент. Ресурсы – количество, сумма.
7.Записи в регистры созданы с помощью конструктора. Для регистра «Остатки номенклатуры» количество корректируется по коэффициенту для единицы измерения.
8.Создан журнал «Документы закупки» с графами «Поставщик», «Сумма».
9.Для проверки движений номенклатуры по регистрам в общем серверном модуле создана функция
<code>
Функция ЕстьДвиженияПоНоменклатуре(Номенклатура) Экспорт
Запрос = Новый Запрос;
Запрос.Текст = “ВЫБРАТЬ ПЕРВЫЕ 1
| ОстаткиНоменклатуры.Регистратор
|ИЗ
| РегистрНакопления.ОстаткиНоменклатуры КАК ОстаткиНоменклатуры
|ГДЕ
| ОстаткиНоменклатуры.Номенклатура = &Номенклатура
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ ПЕРВЫЕ 1
| Закупки.Регистратор
|ИЗ
| РегистрНакопления.Закупки КАК Закупки
|ГДЕ
| Закупки.Номенклатура = &Номенклатура”;
Запрос.УстановитьПараметр(“Номенклатура”, Номенклатура);
Результат = Запрос.Выполнить();
флЕстьДвижения = Не Результат.Пустой();
возврат флЕстьДвижения;
КонецФункции
</code>
Это что было сделано для документов.
При выборе номенклатуры из регистра св. «Цены номенклатуры» по указанному типу цен в документе подставляется цена. Цена выбирается запрос через срез последних.
Пересчет суммы по цене и количеству.
Отображение итоговой суммы документа.
Реквизит «Контактное лицо контрагента» связан по владельцу «Контрагент».
Для реквизитов «Номенклатура», «Ед. изм.», «Количество» установлено обязательное заполнение.
Реализован пересчет реквизитов «Цена», «Количество» при изменении реквизита «Сумма». Вариант пересчета указывается в константе «Вариант пересчета» тип «Перечисление.ВараинтПересчета». В клиентском общем модуле описана процедура по пересчету строки в документе.
С каждым разом все труднее и труднее, времени все меньше и меньше, если такими темпами буду делать Д.З. то, наверное, скоро начну отставать…
А так Д.З. выполнено, наверное, опять с кучей недоделок….
Так как я решал задание в вашей выгрузке у меня возникли проблемы с правильностью писать запросы, обращения…
То есть, когда я писал в своей базе, у меня были какие-то свои понимания что и как я делал, а тут хоть и смотришь видео решения предыдущих заданий, но из них понимаешь только Важные моменты и подводные камни.
Поэтому есть предложения по Д.З.
Устраивать такие задания:
На сайте выкладываете какую-нибудь выгрузку с ошибкой (или несколько ошибок), объясняете в краткости что должно получиться и предлагаете пользователям найти ошибке чтобы все работало правильно… хорошие задания для того чтобы научиться разбираться в чудом коде.
Предложение взяли на заметку, рассмотрим! :)
Задание выполнил. Резюме:
1. Создал рег. св. МенеджерыКонтрагентов (незав, период. по дням, изм. Контрагент, рес. Менеджер).
2. Анализ на контакт: запрос к таблице документов, есть ли хоть один документ к моменту времени текущего документа, если нет, делаю запись в регистре. Как я понял, даже если к контрагенту уже привязан менеджер, но контактов не было (не введены документы), то нужно делать запись.
3. Создал рег. св. ЦеныНоменклатуры (незав, период. по дням, изм. Номенклатура, ТипЦен – справочник ТипыЦен, рес. Цена). Создал справочник ТипыЦен.
4. В документы прихода и расхода добавил рекв. ТипЦен. При изменении Номенклатуры заполняется ед. изм и цена, пересчитывается сумма. При изменении Количеста, Цена пересчитывается сумма. При изменении Сумма пересчитывается или цена или количество (в зависимости от константы ВариантПересчета). Все общие функции вынес в клиентские общие модули (из них делаю серверные вызовы). Вывожу на форму итог по таб. част Товары, также создал реквизит СуммаДокумента для приходных документов, заполняю его ПриЗаписи объекта.
4. Создал рег. нак ОстаткиНоменклатуры (остатки, изм. – Номенклатура, Качество, рес – Количество). При записи в него Количество привожу к базовой единице (умножением на коэффициент).
5. Создал рег. нак. ДанныеОЗакупках (обороты, изм.- Номенклатура, Контрагент, рес. – Количество, Сумма).
6. Проверку на движения по номенклатуре делаю в серверной функции. Лучше приведу часть кода:
<code>ДвиженияБыли = Ложь;
Для каждого РегистрНакопления Из Метаданные.РегистрыНакопления Цикл
ИмяРегистра = РегистрНакопления.Имя;
Если НЕ РегистрНакопления.Измерения.Найти(“Номенклатура”) = Неопределено
ИЛИ НЕ РегистрНакопления.Ресурсы.Найти(“Номенклатура”) = Неопределено
ИЛИ НЕ РегистрНакопления.Реквизиты.Найти(“Номенклатура”) = Неопределено Тогда
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| ОстаткиНоменклатуры.Регистратор
|ИЗ
| РегистрНакопления.ОстаткиНоменклатуры КАК ОстаткиНоменклатуры
|ГДЕ
| ОстаткиНоменклатуры.Номенклатура = &Номенклатура”;
Запрос.УстановитьПараметр(“Номенклатура”, Номенклатура);
Запрос.Текст = СтрЗаменить(Запрос.Текст, “ОстаткиНоменклатуры”, ИмяРегистра);
Результат = Запрос.Выполнить();
Если НЕ Результат.Пустой() Тогда
ДвиженияБыли = Истина;
Возврат ДвиженияБыли;
КонецЕсли;
КонецЕсли;
КонецЦикла;
</code> аналогично для регистров сведений.
6. С журналом проблем не возникло. Реквизит СуммаДокумента сделал заранее.
Привязку менеджера к клиенту обеспечиваем с помощью независимого регистра сведений МенеджерыКонтрагентов с периодичностью в пределах дня, измерения Пользователь, Контрагент. Для подстановки текущего пользователя используем серверную функцию ОбщиеФункцииСервер.ПолучитьТекущегоПользователя(). Для проверки первого контакта получаем срез последних регистра сведений МенеджерыКонтрагентов с отбором по контрагенту.
Хранение цен с помощью регистра сведений Цены. Измерение Прайс из справочника ВидыПрайсЛистов, Номенклатура, ресурс Цена. Для подстановки цен при изменении номенклатуры вызываем серверную функцию ПолучитьЦену(Прайс,Номенклатура), в которой получаем срез последних из регистра Цены.
Пересчет суммы по цене и количеству и пересчет цены или количества при изменении суммы делаем с помощью клиентских функций ПересчитатьСумму() и ПриИзмененииСуммы() (в этой функции для получения варианта пересчета из константы вызываем серверную функцию ПолучитьВариантПересчета()).
Для расчета реквизита Сумма документа используем клиентскую функцию ПересчитатьСуммуДокумента(), вызываем ее при изменении цены, количества, суммы в таблице товаров.
В регистрах накопления Остатки и Закупки при заполнении движений количество товаров пересчитываем в базовых единицах измерения с помощью коэффициента единицы измерения.
Проверку изменения базовой единицы измерения в процедуре ПередЗаписью модуля справочника Номенклатура запросом к регистрам Остатки и Закупки по данной номенклатуре, используем ПЕРВЫЕ 1, ОБЪЕДИНИТЬ.
Задание выполнил.
1. Создал регистр сведений Менеджеры Клиентов с изменением Контрагент-тип справочник Контрагенты , ресурсом Менеджер-тип Справочник Пользователи ,периодический (в пределах дня).
2. Создал реквизит Менеджер у документа Событие. В обработке формы при создании на сервере получаю текущего пользователя и присваиваю его реквизиту Менеджер. В задании с первым контактом я проверяю, а были ли вообще контакты у менеджера с данным контрагентом. Если контактов не было, то добавляю новый: <cod>
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если РежимЗаписи = РежимЗаписиДокумента.Проведение И ЭтоПервыйКонтактСКонтрагентом() Тогда
НаборЗаписей = РегистрыСведений.МенеджерыКлиентов.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Контрагент.Установить(Контрагент);
НаборЗаписей.Отбор.Период.Установить(Дата);
НоваяЗапись = НаборЗаписей.Добавить();
НоваяЗапись.Период = Дата;
НоваяЗапись.Контрагент = Контрагент;
НоваяЗапись.Менеджер = Менеджер;
НаборЗаписей.Записать();
КонецЕсли;
КонецПроцедуры
Функция ЭтоПервыйКонтактСКонтрагентом()
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| МенеджерыКлиентов.Контрагент
|ИЗ
| РегистрСведений.МенеджерыКлиентов КАК МенеджерыКлиентов
|ГДЕ
| МенеджерыКлиентов.Контрагент = &Контрагент
| И МенеджерыКлиентов.Менеджер = &Менеджер”;
Запрос.УстановитьПараметр(“Контрагент”, Контрагент);
Запрос.УстановитьПараметр(“Менеджер”, Менеджер);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
Возврат Ложь;
Иначе
Возврат Истина;
КонецЕсли;
КонецФункции // ЭтоПервыйКонтактСКонтрагентом()
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения) Если РежимЗаписи = РежимЗаписиДокумента.Проведение И ЭтоПервыйКонтактСКонтрагентом() Тогда НаборЗаписей = РегистрыСведений.МенеджерыКлиентов.СоздатьНаборЗаписей(); НаборЗаписей.Отбор.Контрагент.Установить(Контрагент); НаборЗаписей.Отбор.Период.Установить(Дата); НоваяЗапись = НаборЗаписей.Добавить(); НоваяЗапись.Период = Дата; НоваяЗапись.Контрагент = Контрагент; НоваяЗапись.Менеджер = Менеджер; НаборЗаписей.Записать(); КонецЕсли; КонецПроцедуры
Функция ЭтоПервыйКонтактСКонтрагентом()
Запрос = Новый Запрос; Запрос.Текст = “ВЫБРАТЬ | МенеджерыКлиентов.Контрагент |ИЗ | РегистрСведений.МенеджерыКлиентов КАК МенеджерыКлиентов |ГДЕ | МенеджерыКлиентов.Контрагент = &Контрагент | И МенеджерыКлиентов.Менеджер = &Менеджер”;
Запрос.УстановитьПараметр(“Контрагент”, Контрагент); Запрос.УстановитьПараметр(“Менеджер”, Менеджер);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий() Тогда Возврат Ложь; Иначе Возврат Истина; КонецЕсли; КонецФункции // ЭтоПервыйКонтактСКонтрагентом()
</cod>
Реквизитам Менеджер и Контрагент указал в свойствах Проверка Заполнения – «Выдавать ошибку». Также сделал возможность выбора контактных лиц контрагента, как и в предыдущем Д3
3. Задача хранения цен. Создан регистр сведений цены номенклатуры с реквизитами : Номенклатура, Тип цены- тип справочник Тип цен и ресурсом Цена. Регистр периодический с периодичностью День.
4. У документов поступление и продажа создан реквизит тип цен. В табличной части в обработке при изменении Номенклатуры добавил код:
<cod>
&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент)
ТекущиеДанные = Элементы.Товары.ТекущиеДанные;
ТекущиеДанные.ЕдиницаИзмерения = ОбщийМодульНаСервере.ПолучитьБазовуюЕдиницуИзмерения(ТекущиеДанные.Номенклатура);
ТекущиеДанные.Коэффициент = 1;
ТекущиеДанные.Цена = ОбработкаТабличныхЧастейСервер.ПолучитьЦенуНоменклатуры(Объект.Дата, ТекущиеДанные.Номенклатура, Объект.ТипЦены);
КонецПроцедуры
</cod>
Получение цены вынес в общий модуль, т.к. используется в разных документах. Функция:
<cod>
Функция ПолучитьЦенуНоменклатуры(НаДату, Номенклатура, ТипЦены) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| ЦеныНоменклатурыСрезПоследних.Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
| &НаДату,
| Номенклатура = &Номенклатура
| И ТипЦены = &ТипЦены) КАК ЦеныНоменклатурыСрезПоследних”;
Запрос.УстановитьПараметр(“НаДату”, НаДату);
Запрос.УстановитьПараметр(“Номенклатура”, Номенклатура);
Запрос.УстановитьПараметр(“ТипЦены”, ТипЦены);
Результат = Запрос.Выполнить().Выбрать();
Если Результат.Следующий() Тогда
Возврат Результат.Цена;
Иначе
Возврат 0;
КонецЕсли;
КонецФункции // ПолучитьЦенуНоменклатуры(НаДату, Номенклатура, ТипЦены)
</cod>
При изменении суммы, я использовал вызов серверной функции
<cod>
&НаКлиенте
Процедура ТоварыСуммаПриИзменении(Элемент)
ТекущиеДанные = Элементы.Товары.ТекущиеДанные;
СтруктураКоличествоЦена = ОбработкаТабличныхЧастейСервер.ПолучитьКоличествоЦену(ТекущиеДанные.Количество, ТекущиеДанные.Цена, ТекущиеДанные.Сумма);
ТекущиеДанные.Количество = СтруктураКоличествоЦена.Количество;
ТекущиеДанные.Цена = СтруктураКоличествоЦена.Цена;
КонецПроцедуры
</cod>
в которой вызывал функцию общего модуля:
<cod>
Функция ПолучитьКоличествоЦену(Количество, Цена, Сумма) Экспорт
СтруктураЗначений = Новый Структура(“Количество, Цена”, Количество, Цена);
Если Константы.ПересчетКоличества.Получить() Тогда
СтруктураЗначений.Количество = Сумма/?(Цена=0, Сумма, Цена);
Иначе
СтруктураЗначений.Цена = Сумма/?(Количество=0, 1, Количество);
КонецЕсли;
Возврат СтруктураЗначений;
КонецФункции // ПолучитьКоличествоЦену()
</cod>
, которая возвращала мне количество и цену.
5. Создал регистр накопления Остатки Товаров с заданными измерениями : Номенклатуры, Качеств – тип справочник Качество и ресурсом Количество. С помощью конструктора движений сделал движения проведения для документа Поступление по данному регистру. Но прежде чем записывать количество, я проверяю единицу измерения в текущей строке и сравниваю базовую единицу измерения с текущей и если не равны, то использую коэффициент для расчёта количества . Код проведения ниже.
6. Объектом хранения данных о закупке у меня будет оборотный регистр накопления Закупки с измерениями Контрагент и Номенклатура и ресурсами Количество и стоимость. Регистратором будет документ Поступление. Тогда код в процедуре Обработка Проведения в Поступлении будет следующим:
<cod>
Процедура ОбработкаПроведения(Отказ, Режим)
Движения.ОстаткиТоваров.Записывать = Истина;
Движения.Закупки.Записывать = Истина;
Для Каждого ТекСтрокаТовары Из Товары Цикл
Если ТекСтрокаТовары.ЕдиницаИзмерения.ЕдиницаПоКлассификатору <> ТекСтрокаТовары.Номенклатура.БазоваяЕдиницаИзмерения Тогда
Колво = ТекСтрокаТовары.Количество * ТекСтрокаТовары.Коэффициент;
Иначе
Колво = ТекСтрокаТовары.Количество;
КонецЕсли;
Движение = Движения.Закупки.Добавить();
Движение.Период = Дата;
Движение.Контрагент = Контрагент;
Движение.Номенклатура = ТекСтрокаТовары.Номенклатура;
Движение.Количество = Колво;
Движение.Стоимость = ТекСтрокаТовары.Сумма;
Движение = Движения.ОстаткиТоваров.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Номенклатура = ТекСтрокаТовары.Номенклатура;
Движение.Качество = ТекСтрокаТовары.Качество;
Движение.Количество = Колво;
КонецЦикла;
КонецПроцедуры
</cod>
7. В модуле формы При Создании На Сервере номенклатуры я проверяю, создаётся ли Новый или открывается существующий элемент справочника, в последнем случае выполняю проверку и запрещаю редактировать единицу измерения:
<cod>
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Не Параметры.Ключ.Пустая() Тогда
Элементы.БазоваяЕдиницаИзмерения.ТолькоПросмотр = БылиДвиженияПоНоменклатуре();
КонецЕсли;
КонецПроцедуры
&НаСервере
Функция БылиДвиженияПоНоменклатуре()
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ ПЕРВЫЕ 1
| ОстаткиТоваровОбороты.Номенклатура
|ИЗ
| РегистрНакопления.ОстаткиТоваров.Обороты(, , , Номенклатура = &Номенклатура) КАК ОстаткиТоваровОбороты”;
Запрос.УстановитьПараметр(“Номенклатура”, Объект.Ссылка);
Возврат Не Запрос.Выполнить().Пустой();
КонецФункции // ()
</cod>
8. В последнем задании добавил документам реквизит Сумма Документа и записываю её каждый раз в процедуре Перед Записью модуля объекта.
Добрый День!
У меня Вопрос по 8 заданию.
Проверку, которая будет запрещать изменять базовую единицу измерения для номенклатуры, если по ней уже есть движения в регистрах,
я реализовал так:
Модуль объекта справочник “Номенклатура”:
Процедура ПередЗаписью(Отказ)
ЭтоНовый = ЭтоНовый();
Если не (ЭтоНовый) и (БазоваяЕдиница<>Ссылка.БазоваяЕдиница)
тогда
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ ПЕРВЫЕ 1
| ОстаткиТоваров.Номенклатура
|ИЗ
| РегистрНакопления.ОстаткиТоваров КАК ОстаткиТоваров
|ГДЕ
| ОстаткиТоваров.Номенклатура = &Номенклатура
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ ПЕРВЫЕ 1
| ЗакупкаТоваров.Номенклатура
|ИЗ
| РегистрНакопления.ЗакупкаТоваров КАК ЗакупкаТоваров
|ГДЕ
| ЗакупкаТоваров.Номенклатура = &Номенклатура”;
Запрос.УстановитьПараметр(“Номенклатура”, Ссылка);
Результат = Запрос.Выполнить();
Если не результат.Пустой()
тогда
Сообщить(“Есть движения по номенклатуре. Базовую единицу менять нельзя”);
Отказ=Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
а как вернуть в этой процедуре ЕдиницеИзмерения старое значение и еще оповестить об этом октрытую форму элемента справочника “Номенклатуры”.
Вернуть старое значение можно обратившись к базе данных. Можно с помощью запроса, а можно с помощью Ссылка.БазоваяЕдиницаИзмерения.
Привязка тоже должна сработать без проблем.
В сообщении пользователю нужно указывать путь к данным “БазоваяЕдиницаИзмерения” и устанавливать текущий объект. Если не получиться, приведите код, который использовали, исправим ошибку.
Задание Выполнено.
Основные моменты решения:
Создан Справочник “ВидыПрайсЛистов”.
Создан Справочник “ПрайсЛисты”, реквизиты: “ВидПрайсЛиста”, “Номенклатура”,
“ЕдиницаИзмерения”, “ЦенаЗакупки”,”Цена продажи”.
Создано Перечисление “ВариантыПересчетаПриИзмененииСуммы” и константа “ВариантПересчетаПриИзмененииСуммы”
Создан Регистр Накопления ЗакупкаТоваров(Обороты)
Измерения: “Поставщик” составного типа “СправочникСсылка.Контрагенты, СправочникСсылка.Сотрудники”, “Номенклатура”
Ресурсы: “Количество”, “Стоимость”.
Создан Регистр Накопления ОстаткиТоваров(Остатки)
Измерения: “Номенклатура”,”Качество”
Ресурсы: “Количество”
Модуль Документа “Контактсклиентом”:
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
Менеджер=ОбщиеФункцииСервер.СинхронизацияПользователей();
КонецПроцедуры
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| КОЛИЧЕСТВО(РАЗЛИЧНЫЕ КонтактСКлиентом.Ссылка) КАК Кол
|ИЗ
| Документ.КонтактСКлиентом КАК КонтактСКлиентом
|ГДЕ
| КонтактСКлиентом.Контрагент = &Контрагент
| И КонтактСКлиентом.Проведен”;
Запрос.УстановитьПараметр(“Контрагент”, Контрагент);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
Если не (ВыборкаДетальныеЗаписи.Кол>1) Тогда
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| Контрагенты.Ссылка КАК СсылкаНаКонтрагент
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| Контрагенты.Ссылка = &Ссылка”;
Запрос.УстановитьПараметр(“Ссылка”, Контрагент);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий()
Тогда
НайденныйКонтрагентCсылка=ВыборкаДетальныеЗаписи.СсылкаНаКонтрагент;
Если не ЗначениеЗаполнено(НайденныйКонтрагентCсылка.Менеджер)
Тогда
НайденныйКонтрагент=НайденныйКонтрагентCсылка.ПолучитьОбъект();
НайденныйКонтрагент.Менеджер=Менеджер;
НайденныйКонтрагент.Записать();
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Модуль ФОрмы Документа “ПоступлениеТОваров”:
&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ТД.ЕдиницаИзмерения = ЗаполнениеДокументовСервер.ПолучитьЕдиницуИзмерения(ТД.Номенклатура);
ТД.Цена=ЗаполнениеДокументовСервер.ПолучитьЦенуЗакупки(ТД.Номенклатура,ТД.ЕдиницаИзмерения,Объект.ВидПрайсЛиста);
ПересчитатьСумму();
КонецПроцедуры
&НаКлиенте
Процедура ТоварыЕдиницаИзмеренияПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ТД.Цена=ЗаполнениеДокументовСервер.ПолучитьЦенуЗакупки(ТД.Номенклатура,ТД.ЕдиницаИзмерения,Объект.ВидПрайсЛиста);
ПересчитатьСумму();
КонецПроцедуры
&НаКлиенте
Процедура ПересчитатьСумму();
ТД = Элементы.Товары.ТекущиеДанные;
ТД.Сумма=ТД.Количество*ТД.Цена;
КонецПроцедуры
&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
ПересчитатьСумму();
КонецПроцедуры
&НаКлиенте
Процедура ТоварыЦенаПриИзменении(Элемент)
ПересчитатьСумму();
КонецПроцедуры
&НаКлиенте
Процедура ТоварыСуммаОкончаниеВводаТекста(Элемент, Текст, ДанныеВыбора, СтандартнаяОбработка)
// Вставить содержимое обработчика.
КонецПроцедуры
&НаКлиенте
Процедура ТоварыСуммаПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ПриИзмененииСуммы(ТД.Количество,ТД.Цена,ТД.Сумма);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПриИзмененииСуммы(Количество,Цена,Сумма)
ВариантПересчета=Константы.ВариантПересчетаПриИзмененииСуммы.Получить();
Если (ВариантПересчета=Перечисления.ВариантыПересчетаПриИзмененииСуммы.ПересчетКоличества) и (Цена<>0)
Тогда
Количество=Сумма/Цена;
ИначеЕсли (ВариантПересчета=Перечисления.ВариантыПересчетаПриИзмененииСуммы.ПересчетЦены) и (Количество<>0)
Тогда
Цена=Сумма/Количество;
КонецЕсли
КонецФункции
Общий Модуль “ЗаполнениеДокументовСервер”:
Функция ПолучитьЦенуЗакупки(Товар,ЕдиницаИзмерения,ВидПрайсЛиста) Экспорт
Если Не (ЗначениеЗаполнено(Товар) и ЗначениеЗаполнено(ВидПрайсЛиста) и ЗначениеЗаполнено(ЕдиницаИзмерения))
Тогда
Возврат 0;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| ПрайсЛисты.ЦенаЗакупки Цена
|ИЗ
| Справочник.ПрайсЛисты КАК ПрайсЛисты
|ГДЕ
| ПрайсЛисты.Номенклатура = &Товар
| И ПрайсЛисты.ЕдиницаИзмерения = &ЕдиницаИзмерения
| И ПрайсЛисты.ВидПрайсЛиста = &ВидПрайсЛиста
| И (НЕ ПрайсЛисты.ПометкаУдаления)”;
Запрос.УстановитьПараметр(“ВидПрайсЛиста”, ВидПрайсЛиста);
Запрос.УстановитьПараметр(“ЕдиницаИзмерения”, ЕдиницаИзмерения);
Запрос.УстановитьПараметр(“Товар”, Товар);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий()
Тогда Возврат ВыборкаДетальныеЗаписи.Цена;
Иначе Возврат 0;
КонецЕсли;
КонецФункции
Модуль документа “ПоступлениеТоваров”
Процедура ОбработкаПроведения(Отказ, Режим)
Движения.ЗакупкаТоваров.Записывать = Истина;
Для Каждого ТекСтрокаТовары Из Товары Цикл
Количество=ТекСтрокаТовары.Количество*ТекСтрокаТовары.ЕдиницаИзмерения.К;
Движение = Движения.ОстаткиТоваров.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Номенклатура = ТекСтрокаТовары.Номенклатура;
Движение.Качество = ТекСтрокаТовары.Качество;
Движение.Количество = Количество;
КонецЦикла;
Движения.ЗакупкаТоваров.Записывать = Истина;
Для Каждого ТекСтрокаТовары Из Товары Цикл
Количество=ТекСтрокаТовары.Количество*ТекСтрокаТовары.ЕдиницаИзмерения.К;
Движение = Движения.ЗакупкаТоваров.Добавить();
Движение.Период = Дата;
Движение.Поставщик = Контрагент;
Движение.Номенклатура = ТекСтрокаТовары.Номенклатура;
Движение.Количество = ТекСтрокаТовары.Количество;
Движение.Стоимость = ТекСтрокаТовары.Сумма;
КонецЦикла;
КонецПроцедуры
Модуль объекта справочник “Номенклатура”:
Процедура ПередЗаписью(Отказ)
ЭтоНовый = ЭтоНовый();
Если не (ЭтоНовый) и (БазоваяЕдиница<>Ссылка.БазоваяЕдиница)
тогда
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ ПЕРВЫЕ 1
| ОстаткиТоваров.Номенклатура
|ИЗ
| РегистрНакопления.ОстаткиТоваров КАК ОстаткиТоваров
|ГДЕ
| ОстаткиТоваров.Номенклатура = &Номенклатура
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ ПЕРВЫЕ 1
| ЗакупкаТоваров.Номенклатура
|ИЗ
| РегистрНакопления.ЗакупкаТоваров КАК ЗакупкаТоваров
|ГДЕ
| ЗакупкаТоваров.Номенклатура = &Номенклатура”;
Запрос.УстановитьПараметр(“Номенклатура”, Ссылка);
Результат = Запрос.Выполнить();
Если не результат.Пустой()
тогда
Сообщить(“Есть движения по номенклатуре. Базовую единицу менять нельзя”);
Отказ=Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Выполнено.
От единиц измерения создалось впечатление некоего сумбура – по-хорошему цену надо бы задавать в разрезе единиц измерения (по краней мере закупочную).
Вопрос: есть ли более оптимальный способ получать цену, чем
&НаСервере
Функция ПолучитьЦену(Товар)
Документ = РеквизитФормыВЗначение(“Объект”);
Отбор = Новый Структура(“Номенклатура, ТипЦен”, Товар, Документ.ТипЦен);
Таблица = РегистрыСведений.ЦеныНоменклатуры.СрезПоследних(Документ.Дата, Отбор);
Возврат Таблица.Итог(“Цена”);
КонецФункции // ПолучитьЦену()
Зачем нужна эта строка:
Документ = РеквизитФормыВЗначение(«Объект»);
?
Можно было бы написать так:
Отбор = Новый Структура(«Номенклатура, ТипЦен», Товар, Объект.ТипЦен);
Другой вариант – использование запроса.
Но по производельности в данном случае выигрыша не будет.
ДЗ выполнил.
Создал периодический (в пределах дня) регистр сведений (РС) МенеджерыКонтрагентов. Измерение Контрагент, Ресурс Менеджер.
В документе КонтактСКлиентом менеджера заполняю в ОбработкеЗаполнения, если ДанныеЗаполнения = Неопределено,использую функцию ОбщиеФункцииСервер.СинхронизацияПользователей().
В ОбработкеПроведения для анализа, что происходит первый контакт запросом выбираю все проведенные документы КонтактСКлиентом, у которых ссылка не равна текущему документу и Контрагент равен Контрагенту в документе. Если результат запроса пустой, используя НаборЗаписей, меняю данные в РС МенеджерыКонтрагентов.
Создал новый РС ЦеныНоменклатуры, периодичность в пределах дня, измерения – Номенклатура, Прайс (ссылка на соответсвующий справочник), Ресурс – Цена. В справочник Прайс пользователи будут заносить Виды цен (рознич., оптов. и т.д.).
В общем серверном модуле ОбщиеФункцииСервер реализовал функцию получения цены с параметрами Номенклатура, Прайс, Дата. Вызываю ее из всех документов при изменении Номенклатуры.
В общем модуле ОбщиеФункцииКлиент реализовал процедуру ПересчетСуммыПоЦенеИКоличеству(), в которую передаю строку документа (Элементы.Товары.ТекущиеДанные) как параметр СтрокаТЧ. Сама процедура:
Процедура ПересчетСуммыПоЦенеИКоличеству(СтрокаТЧ) Экспорт
СтрокаТЧ.Сумма = СтрокаТЧ.Количество * СтрокаТЧ.Цена;
КонецПроцедуры
В этом же общем модуле реализована процедура ПриИзмененииСуммыТЧ(), которая пересчитывает Количество или Цену при изменении Суммы в строке таб. части:
Процедура ПриИзмененииСуммыТЧ(СтрокаТЧ) Экспорт
ВариантПересчета = ОбщиеФункцииСервер.ПолучитьВариантПересчетаПриИзмененииСуммы();
Если ВариантПересчета =
ПредопределенноеЗначение(“Перечисление.ВариантыПересчетаПриИзмененииСуммы.Количество”) Тогда
Цена = СтрокаТЧ.Цена;
СтрокаТЧ.Количество = ?(Цена <> 0, СтрокаТЧ.Сумма/Цена, 0);
Иначе
Количество = СтрокаТЧ.Количество;
СтрокаТЧ.Цена = ?(Количество <> 0, СтрокаТЧ.Сумма/Количество, 0);
КонецЕсли;
КонецПроцедуры
Вариант пересчета (Кол-во или Цена) – значение перечисления, хранится в Константе, получаю на сервере.
Создал два регистра накопления.
1. ОстаткиНоменклатуры. Измерения – Номенклатура, Качество. Ресурс – Количкство.
2. Оборотный регистр Закупки. Измерения – Поставщик, Номенклатура, Ресурсы – Количество, Сумма.
Т.к. Количество в регистре следует учитывать в Базовых единицах, при проведении делаю пересчет из Единицы в документе в Базовую единицу, используя коэффициент.
Как нас научил Евгений (спасибо ему за это!), Коэффициент пересчета единицы измерения правильно хранить в самом документе, а не брать его из справочника. Так я и сделал. В документах создал обработчик При Изменении ЕдиницыИзмерения, в котором заполняю Коэффициент пересчета в базовую Единицу (в строке таб.части).
Проверку, запрещающую изменять БазовуюЕдиницу Номенклатуры сделал в событии ОбработкаПроверкиЗаполнения в модуле Объекта справочника Номенклатуры. В нем проверяю, если меняется именно ЕдиницаИзмерения (а не Наименование, например) то запросом выбираю данные из таблиц оборотов регистров накопления по данной Номенклатуре. Если в этих регистрах есть данные, то Отказ = Истина. Чтобы проверить что меняется именно ЕдиницаИзмерения сравниваю новое значение БазовойЕдиницы с тем, которое хранится в БД.
Чтобы в Журнале документов отображалась Сумма, сделал у Поступления и Авансового отчета доп. реквизит СуммаДок, заполняю его ПередЗаписью().
1. Для привязки менеджеров к клиентам создан периодический регистр сведений “МенеджерыКлиентов” с периодом один день, измерением Контрагент и ресурсом менеджер.
2. Текущий пользователь определяется по гуид и подставляется при открытии формы документа.
Проверка является ли контакт с контрагентом новым выполняется запросом к регистру сведений “МенеджерыКлиентов” с использованием фильтра контрагент, если результат запроса пустой то при проведении устанавливается значение указанное в документе.
3. Для хранения цен создан периодический регистр сведений “ЦеныНоменклатуры” с периодом день, с измерением номенклатура и ресурсом цена. В регистр записывается закупочная цена при проведении документа “Закупка”. Созданы константы для пересчета цен где хранятся коэффициенты пересчета. Продажные цены рассчитываются из закупочной цены. Пересчет происходит в серверной процедуре, куда параметрами передаются цена и коэффициент пересчета. Передавать коэффициент пересчета в процедуру получается довольно топорно )))
<code>
&НаСервереБезКонтекста
Функция ПолучитьКоэфициент()
ЦенаРозничная = Константы.РозничнаяЦена.Получить();
ЦенаМелкооптовая = Константы.МелкооптоваяЦена.Получить();
ЦенаОптовая = Константы.ОптоваяЦена.Получить();
Если Объект.ВидЦены = Перечисления.ВидыЦен.ОптоваяЦена тогда
возврат ЦенаОптовая;
ИначеЕсли Объект.ВидЦены = Перечисления.ВидыЦен.МелкооптоваяЦена тогда
возврат ЦенаМелкооптовая;
ИначеЕсли Объект.ВидЦены = Перечисления.ВидыЦен.РозничнаяЦена Тогда
возврат ЦенаРозничная;
КонецЕсли;
конецфункции
</code>
4. Все необходимые действия по улучшению юзабилити выполнены в модуле формы элемента документов.
5.Создан регистр накопления “Остатки товаров” , с видом остатки, регистраторами для него являются документы закупки и продажи. Движения создал конструктором.
6. Для хранения данных о закупках создан регистр накопления “Данные закупок” с видом обороты, Измерения – поставщики и товары, ресурсы количество и стоимость.
7. Проверка базовой единицы реализована запросом к регистру сведений “Цены Номенклатуры” и справочнику “Единицы измерения номенклатуры ” с фильтром единицы измерения с коэфициентом 1(базовые) и наименование номенклатуры, если результат не пустой (есть движение) происходит проверка единицы измерения сравнением с базовой.
запрос
<code>
ВЫБРАТЬ ПЕРВЫЕ 1
ЦеныНоменклатуры.Номенклатура,
ЕдиницыИзмеренияНоменклатуры.Наименование
ИЗ
РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ЕдиницыИзмеренияНоменклатуры КАК ЕдиницыИзмеренияНоменклатуры
ПО ЦеныНоменклатуры.Номенклатура = ЕдиницыИзмеренияНоменклатуры.Владелец
ГДЕ
ЕдиницыИзмеренияНоменклатуры.К = 1
И ЕдиницыИзмеренияНоменклатуры.Владелец = &Владелец
</code>
проверка
<code>
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Если НЕ Результат.Пустой() Тогда
Если ВыборкаДетальныеЗаписи.Наименование <> Объект.БазоваяЕдиница.Наименование Тогда
Сообщение = Новый СообщениеПользователю;
………..
Отказ = Истина;
</code>
Изменения в структуре:
Новый справочник ТипыЦен и реквизит ТипЦен для Поступления и Реализации. Новый реквизит Менеджер для справочника Контрагенты и документа КонтактСКлиентом. Новый журнал ДокументыЗакупки. Константа ВариантПересчета и Перечисление ВариантыПересчета для определения какой реквизитд документа пересчитывать. Регистр сведений ЦеныНоменклатуры и Регистры накопления: ОстаткиТоваров (остаточный), ЗакупкиОтПоставщиков (оборотный)
Установка менеджера:
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| КонтактСКлиентом.Ссылка
|ИЗ
| Документ.КонтактСКлиентом КАК КонтактСКлиентом
|ГДЕ
| КонтактСКлиентом.Контрагент = &Контрагент
| И КонтактСКлиентом.Проведен
| И КонтактСКлиентом.Ссылка <> &Ссылка”;
Запрос.УстановитьПараметр(“Контрагент”,Контрагент);
Запрос.УстановитьПараметр(“Ссылка”,Ссылка);
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
СпрОб = Контрагент.ПолучитьОбъект();
СпрОб.Менеджер = Менеджер;
СпрОб.Записать();
КонецЕсли;
Автоматическая цена при выборе номенклатуры сделал функцией общего модуля:
Функция ПолучитьЦенуНоменклатуры(Дата,Номенклатура,ЕдиницаИзмерения,ТипЦен) Экспорт
Возврат РегистрыСведений.ЦеныНоменклатуры.ПолучитьПоследнее(Дата,Новый Структура(“Номенклатура,ТипЦен,ЕдиницаИзмерения”,Номенклатура,ТипЦен,ЕдиницаИзмерения)).Цена;
КонецФункции
Остальное юзабилити так же без проблем сделано, отображение суммы документа сделано через реквизит объекта “ТоварыИтогСумма”, без строчки кода, но для отображения в журналах, а также удобства печати реквизит “Сумма” присутствует, заполняется перед записью.
Проведение документа ПоступлениеТоваров:
Движения.ОстаткиТоваров.Записывать = Истина;
Движения.ЗакупкиОтПоставщиков.Записывать = Истина;
Для Каждого СтрокаТЧ Из Товары Цикл
Движение = Движения.ОстаткиТоваров.ДобавитьПриход();
Движение.Номенклатура = СтрокаТЧ.Номенклатура;
Движение.ВидБрака = ?(ЗначениеЗаполнено(СтрокаТЧ.ВидБрака),СтрокаТЧ.ВидБрака,Справочники.ВидыБрака.БезБрака);
Движение.Количество = СтрокаТЧ.Количество * СтрокаТЧ.Коэффициент;
Движение.Период = Дата;
Движение = Движения.ЗакупкиОтПоставщиков.Добавить();
Движение.Номенклатура = СтрокаТЧ.Номенклатура;
Движение.Поставщик = Контрагент;
Движение.Количество = СтрокаТЧ.Количество * СтрокаТЧ.Коэффициент;
Движение.Стоимость = СтрокаТЧ.Сумма;
Движение.Период = Дата;
КонецЦикла;
Проверка при изменении базовой ед.изм:
Если Не ЭтоНовый и Ссылка.БазоваяЕдиница <> ЭтотОбъект.БазоваяЕдиница Тогда
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| ОстаткиТоваров.Регистратор
|ИЗ
| РегистрНакопления.ОстаткиТоваров КАК ОстаткиТоваров
|ГДЕ
| ОстаткиТоваров.Номенклатура = &Номенклатура”;
Запрос.УстановитьПараметр(“Номенклатура”,Ссылка);
Результат = Запрос.Выполнить();
Если Не Результат.Пустой() Тогда
Отказ = Истина;
Сообщить(“Нельзя изменять базовую единицу измерения, товар уже участвовал в движениях!”);
КонецЕсли;
КонецЕсли;
С журналом так же проблем не возникло.
1.Создала периодический регистр сведений Менеджеры с измерением Контрагент и ресурсом Менеджер.
В модуле документа “Событие” добавила 2 процедуры ОбработкаЗаполнения и ОбработкаПроведения.
ОбработкаЗаполнения:
Если ЭтоНовый() Тогда Менеджер=Справочники.Пользователи.НайтиПоРеквизиту(“ПользовательИБ”,ПользователиИнформационнойБазы.ТекущийПользователь().УникальныйИдентификатор);
КонецЕсли;
ОбработкаПроведения:
Запрос=новый запрос(“ВЫБРАТЬ
| МенеджерыСрезПоследних.Менеджер
|ИЗ
| РегистрСведений.Менеджеры.СрезПоследних(&Дата, Контрагент = &Контрагент) КАК МенеджерыСрезПоследних”);
Запрос.УстановитьПараметр(“Контрагент”,Контрагент);
Запрос.УстановитьПараметр(“Дата”,Дата);
Выборка= Запрос.Выполнить().Выбрать().Следующий();
Если не Выборка Тогда
РегистрМенеджеры=РегистрыСведений.Менеджеры.СоздатьМенеджерЗаписи();
РегистрМенеджеры.Менеджер=Менеджер;
РегистрМенеджеры.Контрагент=Контрагент;
РегистрМенеджеры.Период=Дата;
РегистрМенеджеры.Записать();
КонецЕсли;
У реквизитов Менеджер и Контрагент в свойстве Проверка заполнения установила “Выдавать ошибку”.
У реквизита Контактное лицо Связь параметров выбора с реквизитом Контрагент. (Отбор.Владелец(Контрагент))
2. Добавила справочник Цены номенклатуры, документ УстановкаЦенНоменклатуры, Регистр сведений периодический ЦеныНоменклатуры.
В документах закупок и отгрузки добавила рекизит СуммаДокумента.
Добавила константу ПересчетЦены с типом Булево
3. Создала регистр Накопления Товары(Остатки)
с измерениями Качество и Номенклатура.
ресурсы: Количество
4. Создала регистр накопления ТоварыОтПоставщиков (Остатки)
измерения: Контрагент, Номенклатура
ресурсы: Количество, Стоимость
5. В модуле справочника Номенклатура добавила в процедуру ПриЗаписи проверку на возможность изменение базовой единицы.
6.Создала журнал документов “Документы закупки” для документа Авансовый отчет и Поступление товаров с графами контрагент и Сумма документа (Ссылка, дата, номер, стандартные )
. полностью код приводить не стала, т.к. сообщение получается очень большим.
Задание выполнено. Создан независимый периодический регистр сведений МенеджерыКонтрагентов, Измерение – Контрагент, ресурс-МенеджерКонтрагента. В документе КонтактыМенеджеров реализовано первоначальное заполнение регистра. <code> Процедура ОбработкаПроведения(Отказ, РежимПроведения) Запрос = Новый Запрос; Запрос.Текст = “ВЫБРАТЬ | МенеджерыКонтрагентовСрезПоследних.МенеджерКонтрагента |ИЗ | РегистрСведений.МенеджерыКонтрагентов.СрезПоследних КАК МенеджерыКонтрагентовСрезПоследних |ГДЕ | МенеджерыКонтрагентовСрезПоследних.Период = &Период | И МенеджерыКонтрагентовСрезПоследних.Контрагент = &Контрагент | И МенеджерыКонтрагентовСрезПоследних.МенеджерКонтрагента = &МенеджерКонтрагента”; Запрос.УстановитьПараметр(“Контрагент”, Контрагент); Запрос.УстановитьПараметр(“МенеджерКонтрагента”, Менеджер); Запрос.УстановитьПараметр(“Период”, Дата); Результат = Запрос.Выполнить(); Если Результат.Пустой() Тогда НовыйМенеджер = РегистрыСведений.МенеджерыКонтрагентов.СоздатьМенеджерЗаписи(); НовыйМенеджер.Контрагент = Контрагент; НовыйМенеджер.МенеджерКонтрагента=Менеджер; НовыйМенеджер.Период=ТекущаяДата(); НовыйМенеджер.Записать(); КонецЕсли; КонецПроцедуры </code> Для хранения цен создан независимый периодический (день) регистр сведений ЦеныНоменклатуры, измерения – Номенклатура, ТипЦен (перечисление), ресурс- Цена. Практически все пересчеты в табличных частях документов учета ТМЦ выполнил еще в 7-м домашнем задании. Здесь лишь модифицировал функцию получения цены <code> &НаСервереБезКонтекста Функция ПолучитьЦену(Ссылка, Дата, Прайс) Отбор = Новый Структура(“Номенклатура, ТипЦен”, Ссылка, Прайс); Цена = РегистрыСведений.ЦеныНоменклатуры.ПолучитьПоследнее(Дата, Отбор).Цена; Возврат Цена; КонецФункции // ПолучитьЦену() </code> Для удобства выполнения обратного пересчета от суммы на форму вывел флажок со значением булевской константы ПересчетКоличества, и пересчет выполняется в зависимости от выбора пользователя без изменения значения константы (по умолчанию по значению константы). Остатки товаров хранятся в регистре накопления ОстаткиТоваров (вид – Остатки, Измерения -Номенклатура, Качество, ресурс -Количество). Информация о закупках хранится в регистре накопления Закупки (вид – Обороты, измерения – Контрагент, номенклатура, ресрурсы-количество, стоимость). Для запрета изменения базовой единицы в модуле объекта справочника Номенклатура перед записью выполняется проверка <code> Процедура ПередЗаписью(Отказ) ЭтоНовый = ЭтоНовый(); Запрос = Новый Запрос; Запрос.Текст = “ВЫБРАТЬ ПЕРВЫЕ 1
| ОстаткиТоваров.Регистратор
|ИЗ
| РегистрНакопления.ОстаткиТоваров КАК ОстаткиТоваров
|ГДЕ
| ОстаткиТоваров.Номенклатура = &Номенклатура”;
Запрос.УстановитьПараметр(“Номенклатура”, ЭтотОбъект.Ссылка); Результат = Запрос.Выполнить(); Если НЕ Результат.Пустой() Тогда Сообщение = Новый СообщениеПользователю; Сообщение.Текст = “Нельзя менять базовую единицу, есть движения”; Сообщение.Поле = “БазоваяЕдиница”; Сообщение.УстановитьДанные(ЭтотОбъект); Сообщение.Сообщить(); Отказ=Истина; КонецЕсли; КонецПроцедуры </code> Создан журнал ДокументыЗакупки.
Мой коммент уже второй день в ожидании модерации. Что-то не так?
Все ок.
Создал Регистр сведений МенеджерыКонтрагентов (Измерения-Контрагент (Запрет незаполненных значений- да), ресурсы-Менеджер(Проверка заполнения-выдавать ошибку), в пределах дня, независимый). В М.Ф. документа КонтактСКлиентом:
<code>
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Объект.Менеджер = ОбщиеФункцииСервер.СинхронизацияПользователей();
КонецПроцедуры
/<code>
Запись в Регистр сведений МенеджерыКонтрагентов делаю в М.О. документа КонтактСКлиентом:
<code>
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| МенеджерыКонтрагентовСрезПоследних.Период,
| МенеджерыКонтрагентовСрезПоследних.Контрагент,
| МенеджерыКонтрагентовСрезПоследних.Менеджер
|ИЗ
| РегистрСведений.МенеджерыКонтрагентов.СрезПоследних КАК МенеджерыКонтрагентовСрезПоследних
|ГДЕ
| МенеджерыКонтрагентовСрезПоследних.Контрагент = &Контрагент”;
Запрос.УстановитьПараметр(“Контрагент”, Контрагент);
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
РСМенеджер = РегистрыСведений.МенеджерыКонтрагентов.СоздатьМенеджерЗаписи();
РСМенеджер.Период =Дата;
РСМенеджер.Контрагент = Контрагент;
РСМенеджер.Менеджер = Менеджер;
РСМенеджер.Записать();
Иначе
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Если НЕ ВыборкаДетальныеЗаписи.Менеджер = Менеджер Тогда
Сообщить (“Сегодня: “+Дата+” должен работать с клиентом “+ВыборкаДетальныеЗаписи.Менеджер);
Менеджер = ОбщиеФункцииСервер.СинхронизацияПользователей();
Отказ = Истина;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
/<code>
Хранение цен обеспечиваю Регистром сведений ЦеныНоменклатуры (Измерения- Номенклатура (Запрет незаполненных значений- да)), ТипЦены-СправочникСсылкаТипЦены(Запрет незаполненных значений- да),в пределах дня, независимый.
В документах ПоступлениеТоваров, АвансовыйОтчет, РеализацияТоваров создал реквизит ТипЦеныНоменклатуры- СправочникСсылка.ТипыЦены. В М.Ф. документов реализую автоматическую подстановку цен при выборе номенклатуры, согласно Регистру сведений ЦеныНоменклатуры. Пересчитываю сумму по цене и количеству. Анализируя константу ВариантПересчетаСуммы-Тип: ПеречислениеСсылка.ВариантыПересчета, пересчитываю цену или количество. Отображаю итоговую сумму документа. В документе РеализацияТоваров реквизит КонтактноеЛицо: Связи параметров выбора = Отбор.Владелец(Контрагент).
Создал Р.Н. ОстаткиТовара: Измерения- Номенклатура,Качество. Ресурсы-Количество. Регистраторы: ПоступлениеТоваров, РеализацияТоваров.
Создал Р.Н. Закупки(Обороты):Измерения-Поставщик,Номенклатура. Ресурсы-Количество, Стоимость. Регистратор-ПоступлениеТоваров.
В процедере ОбработкаПроведения документа ПоступлениеТоваров подкорректировал КОНСТРУКТОР_ДВИЖЕНИЙ_РЕГИСТРОВ.
В М.О. справочника Номенклатура в процедуре ПередЗаписью:
<code>
Если НЕ ЭтоНовый() Тогда
Если Ссылка.БазоваяЕдиница <> ЭтотОбъект.БазоваяЕдиница Тогда
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ 1
| Закупки.Номенклатура
|ИЗ
| РегистрНакопления.Закупки КАК Закупки
|ГДЕ
| Закупки.Номенклатура = &Номенклатура
|
|ОБЪЕДИНИТЬ
|
|ВЫБРАТЬ
| ОстаткиТовара.Номенклатура
|ИЗ
| РегистрНакопления.ОстаткиТовара КАК ОстаткиТовара
|ГДЕ
| ОстаткиТовара.Номенклатура = &Номенклатура”;
Запрос.УстановитьПараметр(“Номенклатура”, Ссылка);
Результат = Запрос.Выполнить();
Если НЕ Результат.Пустой() Тогда
Сообщить(“Есть движения по регистрам “+ Наименование+ ” – изменить базовую единицу нельзя!”);
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецЕсли;
/<code>
Создал журнал документов ДокументыЗакупки с графами: Контрагент, ПодотчетноеЛицо, СуммаДокумента.
К сожалению код в М.Ф. документов (для удобства работы пользователей) повторяется. Нужно вынести егокуда-то в отдельную процедуру.
>Нужно вынести егокуда-то в отдельную процедуру.
Если быть более точным – в общий модуль
Задание выполнено.
Для контрагентов создан реквизит “Менеджер”
Созданы регистры сведений Цены Номенклатуры, регистры накоплений Остатки (остатки) и ДанныеОЗакупках (обороты). Движения по регистрам сделаны конструктором и немного подправлены вручную. Создан журанл документов и реквизит документа Закупки для вывода в форме журнала.
А вот дальше был небольшой затык с формулировкой задания.
Для всех документов по учету ТМЦ реализуйте следующее поведение:
Автоматическую подставку цен при выборе номенклатуры, согласно указанного прайса.
Затык в том, что я не смог представить ситуацию, когда мы приходуем товар не по закупочным ценам, а цены продажные (опт и мелкоопт) должны, на мой взгляд, назначаться от некой базовой розничной цены.
Возможно я немного ушел от задания, но реализация получилась следующей.
Создан спрвочник ВидыЦен в котором есть два преопределенных значения Закупочные и Розничные. В справочнике запрещено создавать элементы с тем же названием, другие виды цен назначаются пользователем.
В документе ПоступлениеТоваров добавлены реквизиты табличной части РознЦена и РознСумма.
При подборе номенклатуры цены заполняются следующим кодом:
&НаСервереБезКонтекста
Функция ПолучитьЦену(ТОвар,Цена,РознЦена)
Отбор = Новый Структура;
Отбор.Вставить(“Номенклатура”,Товар);
ТЗ = РегистрыСведений.ЦеныНоменклатуры.СрезПоследних(Текущаядата(),ОТбор);
НайденнаяСтрока = ТЗ.Найти(Справочники.ВидыЦен.Закупочная, “ВидЦены”);
Если НайденнаяСтрока <> Неопределено Тогда
Цена = НайденнаяСтрока.Цена;
КонецЕсли;
НайденнаяСтрока = ТЗ.Найти(Справочники.ВидыЦен.Розничная, “ВидЦены”);
Если НайденнаяСтрока <> Неопределено Тогда
РознЦена = НайденнаяСтрока.Цена;
КонецЕсли;
Возврат Цена;
А при проведении документа мы не только делаем движения по регистрам остатка но и записываем базовые цены для номенклатуры в регистр сведений. правда, этот кусок кода меня сильно смущает
Процедура ОбработкаПроведения(Отказ, Режим)
Движения.Остатки.Записывать = Истина;
Движения.ДанныеОЗакупках.Записывать = Истина;
Для Каждого ТекСтрокаТовары Из Товары Цикл
Движение = Движения.Остатки.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Номенклатура = ТекСтрокаТовары.Номенклатура;
Движение.Качество = ТекСтрокаТовары.Качество;
Движение.остаток = ТекСтрокаТовары.Количество;
ДвижениеЗак = Движения.ДанныеОЗакупках.Добавить();
ДвижениеЗак.Период = Дата;
ДвижениеЗак.Контрагент = Контрагент;
ДвижениеЗак.Номенклатура = ТекСтрокаТовары.Номенклатура;
ДвижениеЗак.Стоимость = ТекСтрокаТовары.Сумма;
ДвижениеЗак.Количество = ТекСтрокаТовары.Количество;
Набор =РегистрыСведений.ЦеныНоменклатуры.СоздатьНаборЗаписей();
набор.Отбор.Период.Установить(ТекущаяДата());
Набор.Отбор.Номенклатура.Установить(ТекСтрокаТовары.Номенклатура);
Запись= набор.Добавить();
запись.ВидЦены=Справочники.ВидыЦен.Закупочная;
Запись.Период=Текущаядата();
запись.Номенклатура=ТекСтрокаТовары.Номенклатура;
запись.Цена=ТекСтрокаТовары.Цена;
Запись= набор.Добавить();
запись.ВидЦены=Справочники.ВидыЦен.Розничная;
Запись.Период=Текущаядата();
запись.Номенклатура=ТекСтрокаТовары.Номенклатура;
запись.Цена=ТекСтрокаТовары.РознЦена;
КонецЦикла;
Набор.Записать();
КонецПроцедуры
В документах Авансовый отчет и Реализация товаров добавлен реквизит ВидЦен, и в зависимости от него мы подставляем нужную цену
&НаСервереБезКонтекста
Функция ПолучитьЦену(ТОвар,ВидЦены)
Отбор = Новый Структура;
Отбор.Вставить(“Номенклатура”,Товар);
Отбор.Вставить(“ВидЦены”,ВидЦены);
Цена = РегистрыСведений.ЦеныНоменклатуры.ПолучитьПоследнее(Текущаядата(),Отбор);
Возврат Цена.Цена
КонецФункции // ПолучитьЦены()
В вашей реализации я бы посоветовал для регистра “Цены номенклатуры” указать подчинение регистратору. В противном случае нужно будет очень аккуратно обрабатывать события перепроведение измененного документа и отмену проведения.
Подобную обработку сможете увидеть в решении ДЗ№8.
Согласен. Спасибо за замечание. Заодно попробую реализовать документ для изменения всех цен товара с таблицой значений на форме.
В итоге сделал через табличную часть.
Возможно при проведении документа обработать ТаблицуЗначений из формы?
То есть хочется в модуль объекта передать содержимое реквизита формы?
Для этого можно использовать дополнительные свойства объекта.
То есть код будет таким.
В модуле формы:
&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
ТекущийОбъект.ДополнительныеСвойства.Вставить(“НашаТаблица”, РеквизитФормыВЗначение(“Таблица”));
КонецПроцедуры
В модуле объекта обращаетесь к ней:
ДополнительныеСвойства.НашаТаблица
Спасибо за ответ!
1. Создан регистр сведений “СопоставлениеМенеджеровКлиентам” непериодический независимый, измерение “контрагент” ресурс “менеджер”
2. В документе “КонтактсКлиентом” поверяю, а новый ли и если новый присваиваю пользователя полученного из общегоМодуляНаСервере.Синхронизацияпользователей
3. На событии ОбработкаПроведения через МенеджерЗаписи проверяю на наличие и если нет то добавляю.
4. “КонтактныеЛица “связью параметров выбора связал с контрагентом
5.Создал справочник “ВидыПрайсЛистов”
6. Создал регистр сведений “ЦеныНоменклатуры” измерения “Номенклатура”, “ВидыПрайсЛистов” ресурс Цена
7.На всех документах добавил реквизит “ВидПрайса”
8. Во всех документах добавил функцию на сервербез контекста “ПолучениеЦеныПоПрайсу”с параметрами (Номенклатура,ВидПрайса) а в них вобращаюсь к общему модулю “ЗаполнениеДокументовСервер” и там получаю в функции запросом цену на товар.
9. Пересчёт суммы строки документов вынес в общий модуль “ЗаполнениеДокументовСервер” функция “ПересчетСуммыСтрокиДокумента” параметры количество и цена, а на форме функцией “ПрересчетСуммы” на сервере без контекста обращаюсь к этой функции.
10. Определил Константу “ПересчетЦены” тип Булеан, определил функцию “ПолучитьВидРасчета” получаю значение константы и в функции при изменении суммы в зависимости от возвращаемого значения пересчитываю либо количество , либо цену.
11. Поставил на проверку реквизиты во всех документах “Номенклатура”, “Ед.Изм.”,”Количество”
12. Создал регистр “ОстаткиТоваров” вид регистра остатки, измерения “Товар”,”Качества” Ресурс “Количество”, определил регистраторами “ПоступлениеТоваров. и “Авансовый отчет”
Конструкторами заполнил движения.
13. Создал регистр “ЗакупкиОтПоставщиков” вид регистра обороты, измерения поставщик(контрагенты, сотрудники), номенклатура и ресурсы количество и стоимость
добавил движения конструктором, а потом объединил уменьшая количество циклов при проведении.
14. При записи на модуле обьекта запросом проверил на наличие в регистрах единицы измерения, если ничего не нашёл, меняем. если хоть чтото есть то даже не перезаписываем.
Кажись нагнал группу.
Задание выполнено. Примеры кода не привожу, чтобы никого не шокировать.
1. Добавлен регистр сведений МенеджерыКонтрагентов.
2. В документе КонтактСКлиентом через процедуру ОбработкаЗаполнения реализовано автозаполнение реквизита Менеджер значением текущего пользователя. В процедуре ОбработкаПроведения через запрос находим Менеджера контрагента, если результат пустой – через менеджер записи регистра сведений заносим новую запись в РС МенеджерыКонтрагентов.
3. Созданы перечисления ТипыЦен, ВариантыПересчета, константа ВариантПересчета, регистр сведений Прайс. Добавлен реквизит ТипЦены в ПоступлениеТоваров, АвансовыйОтчет, РеализацияТоваров.
4. Для элементов формы Номенклатура, Цена, Количество, Сумма документов ПоступлениеТМЦ и РеализацияТМЦ добавлены обработчики событий. Код обработчиков продублировал, в общий модуль однострочные функции выносить не стал. Вызвала затруднение передача в параметры функции значения реквизита ТипЦены.
5. Создан регистр накопления ОстаткиТМЦ (измерения Номеклатура, Качество; ресурс – Количество; регистратор – ПоступлениеТМЦ). Добавил движения через конструктор движений.
6. Сомневался, какой тип нужен по тексту задания для регистра ДанныеОЗакупках. Изначально сделал регистр сведений для получения информации о динамике изменения цены и объемов закупок у поставщиков, затем переделал его в регистр накопления. Для учета по партиям он не годится, поэтому выбрал вид регистра – обороты. По тексту задания мне не совсем ясно какую информацию мы хотим получать отсюда.
7. В справочнике Номенклатура в процедуре ПередЗаписью добавил запрос об оборотах регистра ОстаткиТМЦ. Если результат запроса не пустой, то запись отменяется.
8. Создал журнал документов ДокументыЗакупки. Добавил в него документ ПоступлениеТМЦ, Авансовый отчет Добавил форму документа. Для этих документов добавил реквизит ИтогоСумма, в который перед записью добавляется итог по колонке Сумма ТЧ Товары.
>По тексту задания мне не совсем ясно какую информацию мы хотим получать отсюда.
Эти данные будут использоваться для анализа закупок (отчеты) за различные периоды.
Поэтому обортный регистр накопления – правильное решение. Текст задания уточним.
1. Создал периодический независимый регистр сведений МенеджерыКлиентов. Измерения: Клиент(ведущее), КонтактноеЛицо, ресурс: Менеджер.
Добавил требуемую проверку в обработку проведения документа КонтактСКлиентом
2. Создал периодический независимый регистр сведений ЦеныНоменклатуры. Измерения: Номенклатура(ведущее), Прайс (переч-е ВидыПрайсов), ресурс: Цена
При проведении ПриходнойНакладной автоматически прописывается закупочная цена и создаются оптовая(+5%), мелкооптовая(+10%) и розничная(+25%).
Несколько приходных в один день с одинаковой номенклатурой и разными ценами не контролирую, т.е. в цене товара будет последняя цена последнего прихода за день.
3. Создал перечисление ВариантыПересчета и константу ВариантПересчетаПриИзмененииСуммы;
Реализовал процедуру пересчета цены и количества на клиенте и требуемые пересчеты, отображения.
4. Создал регистр ОстаткиТоваров(тип остатки). При проведении документов количество умножаю на коэффициент единицы измерения в строке.
Пока контроль остатков товара при продаже не провожу.
5. Создал оборотный регистр Закупки (регистратор ПриходнаяНакладная). Измерения: Поставщик,Товар, ресурсы: Количество, Сумма
При проведении приходной накладной сворачиваю ТЧ по Товар,Количество,Сумма и пишу в регистр Закупки.
6. Добавил запрет на изменение базовой единицы через запрос с “ВЫБРАТЬ ПЕРВЫЕ 1” и фильтром по Товару.
В процедуре ПриСозданииНаСервере модуля формы эл-та спр-ка Номенклатуры написал:
<code>
Если НЕ (Объект.ЭтоГруппа ИЛИ Объект.Ссылка.Пустая()) Тогда
Элементы.БазоваяЕдиница.Доступность=НеБылоДвиженийПоНоменклатуреСервер(Объект.Ссылка);
КонецЕсли;
</code>
7. Создал требуемый журнал “Документы закупки”
Задание выполнено.
Задание выполнено.
Для привязки менеджеров к клиентам создан независимый регистр сведений “МенеджерыКонтрагентов” с периодичностью в пределах дня. Обработка проведения выглядит так:
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
ТЗ = “ВЫБРАТЬ
| Контакт.Ссылка
|ИЗ
| Документ.Контакт КАК Контакт
|ГДЕ
| Контакт.Контрагент = &Контрагент
| И Контакт.МоментВремени < &МоментВремени”;
Запрос = Новый Запрос;
Запрос.Текст=ТЗ;
Запрос.УстановитьПараметр(“Контрагент”, Контрагент);
Запрос.УстановитьПараметр(“МоментВремени”, МоментВремени());
Если Запрос.Выполнить().Пустой() Тогда
Запись = РегистрыСведений.МенеджерыКонтрагентов.СоздатьМенеджерЗаписи();
Запись.Контрагент = Контрагент;
Запись.Менеджер = Менеджер;
Запись.Период = Дата;
Запись.Записать();
КонецЕсли;
КонецПроцедуры
Создан справочник КатегорииЦен с предопределенными элементами “Входные” и “Розничные”, а также независимый регистр сведений “Цены” с периодичностью День, измерения – Товар, КатегорияЦен (ссылки); ресурс – Цена (число). Соответственно, из справочника Номенклатура убрал реквизит Цена.
В документах поступления и реализации при вводе нового документа в процедуре ОбработкаЗаполнения устанавливается категория цен (Входные и Розничные, соответственно). При выборе номенклатуры вызывается серверная функция, в параметрах которой передаются ссылка на товар, на категорию цен документа. Функция возвращает структуру с данными выбранного товара (ключи – “ЕдиницаИзмерения” и “Цена”), цена теперь берется из регистра сведений. Пересчет суммы при изменении кол-ва и цены был сделан еще в 7-м задании. Для обратного пересчета (от суммы) была заведена константа, индекс значения которой запоминается в клиентской переменной модуля формы при ее открытии (чтобы не читать константу с сервера при каждом изменении суммы).
Создал регистры накопления “ОстаткиТоваров” (остатки), измерения – Товар, СтепеньБрака, ресурс – Количество, и “Закупки” (обороты), измерения – Поставщик, Товар, ресурсы – Количество, Сумма.
При проведении док-та Поступление товаров создаются записи по обоим регистрам, тут каких-то сложностей не возникло. Запись количества производится с учетом единицы измерения, указанной в строке, если она не является базовой, то производится пересчет по заданному коэффициету.
Для проверки возможности изменения базовой единицы, в модуль объекта справочника номенклатура в процедуре ПередЗаписью вставлен такой код:
ОбъектСтарый = ЭтотОбъект.Ссылка.ПолучитьОбъект();
ОбъектСтарый.Прочитать();
Если ОбъектСтарый.БазоваяЕдиницаИзмерения <> БазоваяЕдиницаИзмерения Тогда
ТЗ = “ВЫБРАТЬ ПЕРВЫЕ 1
| ОстаткиТоваров.Регистратор
|ИЗ
| РегистрНакопления.ОстаткиТоваров КАК ОстаткиТоваров
|ГДЕ
| ОстаткиТоваров.Товар = &Товар”;
Запрос = Новый Запрос;
Запрос.Текст = ТЗ;
Запрос.УстановитьПараметр(“Товар”, ЭтотОбъект.Ссылка);
Если НЕ Запрос.Выполнить().Пустой() Тогда
Сообщить(“По данному товару существуют движения!
|Изменение базовой единицы измерения запрещено!”, СтатусСообщения.Внимание);
БазоваяЕдиницаИзмерения = ОбъектСтарый.БазоваяЕдиницаИзмерения;
Отказ = Истина;
Возврат;
КонецЕсли;
КонецЕсли;
Достаточно проверять один регистр, так как при закупке движения появляются по двум регистрам одновременно (пока, во всяком случае). Далее наверняка будут движения по расходу товара, где так же будет задействован регистр ОстаткиТоваров.
Уже после отправки коммента выяснил, что при таком коде нельзя ввести новый товар, забыл вставить проверку на то, что записываем новый товар, а не изменяем старый, с помощью метода ЭтоНовый(). Вывод – надо тщательнее тестировать решения :)
Все верно :)
Есть еще вопрос. В моей конфигурации список единиц измерения товара хранится не в подчиненном справочнике, а в табличной части у Номенклатуры. Для того чтобы в документе при выборе единицы измерения выдавались только нужные единицы уже нельзя использовать отбор по владельцу в связях параметров выбора. Использую обработчик события НачалоВыбора для поля ЕдиницаИзмерения:
&НаКлиенте
Процедура ТоварыЕдиницаИзмеренияНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ДанныеВыбора = Новый СписокЗначений;
ДанныеВыбора.ЗагрузитьЗначения(ОбщиеФункции.ПолучитьЕдиницыИзмеренияТовара(Элементы.Товары.ТекущиеДанные.Товар));
КонецПроцедуры
В серверном общем модуле, соответственно, есть функция:
Функция ПолучитьЕдиницыИзмеренияТовара(Товар) Экспорт
Запрос = Новый Запрос;
Запрос.Текст = “ВЫБРАТЬ
| Единицы.ЕдиницаИзмерения КАК ЕдИзм
|ИЗ
| Справочник.Номенклатура.ЕдиницыИзмерения КАК Единицы
|ГДЕ
| Единицы.Ссылка = &Товар”;
Запрос.УстановитьПараметр(“Товар”, Товар);
Возврат Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку(“ЕдИзм”);
КонецФункции
Мне интересно, это оптимальный способ или как-то можно было все-таки настроить через связи параметров выбора?
И еще, при использовании такого метода выбор значения осуществляется не в отдельном окне, а быстрым выбором (даже если в конфигураторе в свойствах поля проставить Быстрый выбор = Нет). Пока элементов мало это даже удобно, но как быть если придется накладывать сложный фильтр для иерархического справочника с большим количеством элементов (и где кол-во после фильтрации также довольно большое)?
При такой структуре задачу через связи параметров выбора не решить.
Можно предложить такое решение:
1. СтандарнаяОбработка = Ложь;
2. Открываете вручную форму выбора (ОткрытьФорму(…))
3. Передаете в открываемую форму отбор в виде списка значений, который получаете на стороне сервера.
Задание выполнено, перечислю основные моменты:
1. Привязка менеджеров к клиентам осуществлялась с помощью независимого и периодического (в пределах секунды) регистра сведений (измерения: “Контрагент”; ресурсы: “Менеджер”).
2. В документе контакта с клиентом реализована подстановка текущего пользователя при создании нового документа, а также, при проведении выполняется проверка: если в регистре сведений нет ни одной записи с контрагентом, указанном в документе, тогда соответствующая запись добавляется в регистр. Для удобства использовался класс “РегистрСведенийМенеджерЗаписи”.
3. Создан независимый и периодический (в пределах дня) регистр сведений для хранения цен на номенклатуру. Измерения: “Прайс”, “Номенклатура”; ресурсы: “Цена”.
4. В документах закупки/отгрузки реализована возможность выбора прайса для заполнения цен номенклатуры. Реализована возможность пересчета суммы, цены и количества. Чтобы каждый раз не делать вызов сервера для считывания константы варианта пересчета при редактировании табличной части, значение константы один раз помещается в специально созданный реквизит формы в обработчике события “ПриСозданииНаСервере”.
5. Созданы регистры накопления – для хранения остатков номенклатуры (тип: “Остатки”; измерения: “Номенклатура”, “СтепеньБрака”; ресурсы: “Количество”) и для хранения оборотов покупок (тип “Обороты”; измерения: “Поставщик”, “Номенклатура”; ресурсы: “Количество”, “Сумма”). Движения по этим 2-м регистрам осуществляет документ закупки.
6. Реализована проверка на возможность изменения базовой единицы номеклатуры. Если есть хотя бы одно движение в любом из 2-х регистров накопления, тогда менять единицу измерения нельзя. Проверку лучше делать в модуле объекта справочника “Номенклатура”, в обработчике события “ПередЗаписью”, однако я сделал эту проверку в форме – для разнообразия.
7. Создан журнал документов с необходимыми графами.
В качестве усовершенствования можно при смене прайса в документах отгрузки/поступления заменять цену номенклатуры в табличной части согласно выбранному прайсу и пересчитывать сумму (как в 1С:Бухгалтерии).
Дополнительно добавил важную проверку, подсмотренную у kst. При проведении количество пересчитывается в базовые единицы только если в табличной части указана единица измерения, отличная от базовой для данной номенклатуры.
Подскажите, пожалуйста: получается, что нужно пересчитывать цену с учетом коэффициента единицы измерения? Ведь при задании цены мы нигде не указываем единицу измерения, значит цена задается для базовой единицы.
>получается, что нужно пересчитывать цену с учетом коэффициента единицы измерения?
Предлагаю не учитывать.
Логично, что пользователь задает цену для выбранной единицы измерения.
Задание выполнил
Создал регистр сведений МенеджерыКонтрагентов независимый, периодичность в пределах секунды,
Измерение Контрагент, ресурс Менеджер.
В созданный документ КонтактСклиентом подставляю пользователя в процедуре
<code>
Процедура ПриОткрытии(Отказ)
Если Объект.Менеджер.Пустая() тогда
Объект.Менеджер = ОбщиеФункцииСервер.СинхронизацияПользователей();
КонецЕсли;
КонецПроцедуры
/<code>
Установку значения менеджера для контрагента (запись в регистр МенеджерыКОнтрагентов
делаю процедурой модуля документа
<code>
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| МенеджерыКонтрагентовСрезПоследних.Менеджер
|ИЗ
| РегистрСведений.МенеджерыКонтрагентов.СрезПоследних КАК МенеджерыКонтрагентовСрезПоследних
|ГДЕ
| МенеджерыКонтрагентовСрезПоследних.Период <= &Дата
| И МенеджерыКонтрагентовСрезПоследних.Контрагент = &Контрагент
| И МенеджерыКонтрагентовСрезПоследних.Менеджер = &Менеджер”;
Запрос.УстановитьПараметр(“Дата”, Дата);
Запрос.УстановитьПараметр(“Контрагент”, Контрагент);
Запрос.УстановитьПараметр(“Менеджер”, Менеджер);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Если НЕ ВыборкаДетальныеЗаписи.Следующий() Тогда
МенеджерК=РегистрыСведений.МенеджерыКонтрагентов.СоздатьМенеджерЗаписи();
МенеджерК.Период=Дата;
МенеджерК.Контрагент=Контрагент;
МенеджерК.Менеджер=Менеджер;
МенеджерК.Записать();
Иначе
КонецЕсли;
КонецПроцедуры
/<code>
Для хранения цен создал регистр сведений ценыНоменклатуры (в пределах дня, независимый),
измерения Номенклатура, видЦены
Организовал поведение документов в соответствии с заданием
Создал регистрНакопления ОстаткиТоваров измерения Номенклатура, Качество, регистраторы- документы
по движению товаров, а также создал регистрНакопления с видом Обороты ЗакупкиУпоставщиков с
измерениями Номенклатура, Поставщик, ресурсы количество, стоимость.
Сделал приход по регистрам при проведении документов прихода
Сделал проверку в модуле справочника Номенклатура для возможности смены базовой единицы
<code>
Процедура ПриЗаписи(Отказ)
Если ЭтоНовый И ЗначениеЗаполнено(БазоваяЕдиница) Тогда
Единица = Справочники.ЕдиницыИзмеренияНоменклатуры.СоздатьЭлемент();
Единица.Владелец = Ссылка;
Единица.ЕдиницаПоКлассификатору = БазоваяЕдиница;
Единица.К = 1;
Единица.Записать();
Иначе
Если ВидНоменклатуры=Перечисления.ВидыНоменклатуры.Товар тогда
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| ОстаткиТоваров.Номенклатура,
| ОстаткиТоваров.НомерСтроки,
| ОстаткиТоваров.ВидДвижения
|ИЗ
| РегистрНакопления.ОстаткиТоваров КАК ОстаткиТоваров
|ГДЕ
| ОстаткиТоваров.Номенклатура = &Номенклатура”;
Запрос.УстановитьПараметр(“Номенклатура”, Ссылка);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл //т.е. в записях регистра есть такая номенклатура
Сообщить(“Нельзя изменять базовую единицу, есть записи”);
Отказ=Истина;
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
/<code>
Создал журнал как требовалось;
Задание выполнено.
Для привязки менеджеров к клиентам создал не подчиненный регистратору Регистр Сведений “МенеджерыКонтрагентов” с периодичностью в пределах дня. Измерение – Контрагент, Ресур – Менеджер. При такой структуре регистра автоматически будет выполнятся условие задания о единственном менеджере в один момент времени.
При проведении документа, при необходимости, делаю запись в регистр сведений “МенеджерыКонтрагентов” используя класс НаборЗаписей.
Для ведения различных прайсов добавил справочник ТипыЦен и для хранения цен создал регистр сведений ЦеныНоменклатуры с измерениями Номенклатура, ТипЦены и ресурсом Цена. Регистр периодический (в пределах дня) не подчиненный регистратору.
Необходимое поведение для документов настроил. Немного застопорился с константой, необходимой для пересчета ТЧ. Остановился на варианте с добавлением на форму доп. реквизита, значение которому присваивается в событии ПриСозданииНаСервере().
Создал регистр накопления ОстаткиНоменклатуры и для документов прихода организовал заполнение движений, используя конструктор. Количество пересчитываю с учетом коэффициента выбранной в документе единицы измерения.
Для хранения данных о закупках создал оборотный регистр накопления.
Проверку на возможность изменения базовой единицы измерения номенклатуры организую запросом к в виртуальной таблице ОстаткиНоменклатурыОбороты по текущей номенклатуре в событии ПередЗаписью.
Создал журнал Поступление, добавил в документы поступления доп. реквизиты, чтобы отображалась сумма документа в журнале. Добавил и настроил необходимые графы в журнале.
Задание выполнено.
Привязка Пользователей к клиентам сделана на независимом периодическом регистре сведений. Реквизит “Менеджер” в контактах заполняю из ПараметраСеанса.ТекущийПользователь. Использование глобальной переменной – не понравилось.
Хранение цен номенклатуры также в независимом периодическом регистре сведений.
Удобство работы по заполнению цены, количества и суммы были у меня реализованы еще прошлом задании. Добавил, лишь, зависимость расчета от константы.
В связи с этим есть вопрос. Сейчас реализовал так, что в каждом событии из табличной части 3х документов свой собственный код на 2-6 строчек. Хотелось бы сделать единую процедуру для всех этих событий. Лучше всего будет создать Общий клиентский модуль и передавать в него ссылку на текущие данные или есть другое, более качественное решение?
Запись движений в регистре ОстаткиТоваров (тип Остатки) и Закупки (тип Обороты) сделаны с помощь конструктора с изменениями в строках по количеству и ЕдиницеИзмерения. Базовую единицу получаю функцией. Скорее всего, не производительно и существует другое решение через запросы.
В связи с этим еще один вопрос. предположим у нас есть справочник контрагентов и справочник контактных лиц контрагентов, связанных по владельцу. Какое из решений будет более производительным:
Я делаю выборку из справочника контактных лиц и в полях выбора указываю реквизит владелец а через точку указываю наименование. Или Выборка из справочника контактных лиц, сделать с ней соединение справочника Контрагентов по связи владелец и в полях выборки указать Контрагент.Наименование. На месте наименования может быть любой реквизит.
В части задания, где необходимо реализовать проверку на смену базовой единицы измерения, мне кажется, есть один подводный камень. Интересно умышленный или нет :) Собственно, саму проверку реализовать не сложно выборкой записей из регистров. Но, важно не забыть и про смену единицы измерения. Нужно не только поменять реквизит в справочнике номенклатура, но и заменить базовую единицу в справочнике ЕдиницыИзмерений.
>создать Общий клиентский модуль и передавать в него ссылку на текущие данные
Это правильное решение.
> Какое из решений будет более производительным
Если я правильно понял речь идет о двух вариантах запроса.
Они будут равнозначны, ведь при преобразовании запроса к sql все равно будет сделано соединение таблицы Контрагенты к Контактным лицам.
Но первый вариант является предпочтительным, ввиду более короткой записи.
Благодарю!
Задание выполнил.
Для привязки менеджеров(спр. «пользователи» ) использую периодический регистр сведений, где в качестве измерения используется справочник контрагент, период а в качестве ресурса менеджер спр. «пользователи», режим записи «независимый».
В Документ «КонтактыМенеджеровСКлиентами» добавил реквизит «менеджер» с типом справочники «пользователи». Для контроля заполнения реквизитов «контрагент», «менеджер» устанавливаю «выдавать ошибку» в проверке заполнения на уровне реквизитов объекта документа. При создании нового документа в модуле объекта в событии ОбработкаЗаполнения заполняю реквизит «менеджер» текущим пользователем. Если это первый контакт данного менеджера с клиентом, добавляю в регистр сведений данные о привязке контрагента к менеджеру. Можно конечно использовать реквизит справочника контрагентов но мне кажется правильнее использовать регистр сведений с привязкой к периоду, с учетом этого мы можем отследить какой менеджер работал в тот или иной момент времени с данным контрагентом.
Для хранения цен номенклатуры создал периодический регистр сведений «Цены номенклатуры» с периодичностью «день», для хранения типов цены добавил в систему справочник «Тип цены». В регистре сведений в качестве измерений использую саму номенклатуру и тип цены в качестве ресурса свойство «цена» тип число. Добавил константы «Основной тип цены покупки» и «Основной тип цены продажи» для автоматической подстановки в документы «Реализация» , «Поступление» типа цен в реквизит типцены, при вводе нового док-та событии объекта «ОбработкаЗаполнения». Так же добавил константу «Вариант пересчета при изменении суммы» со вариантом типа перечисления(новый) «Вариант пересчета».
Для заполнения цены по выбранной номенклатуре выполняю запрос к БД в док-х «поступления» и реализации к виртуальной таблице ЦеныНоменклатурыСрезПоследних.
Добавлен пересчет в табличных частях документов при изменении цены и количества. Также в зависимости от состояния константы «вариант пересчета» пересчитывается цена или количество от суммы. На уровне реквизитов в док-х задал обязательность заполнения «номенклатуры», «ед.изм.» и «кол-во».
Для хранения остатков товаров создал регистр накопления «ОстаткиТовара» с видом остатки. Измерения «Номенклатура», «Качество», ресурс «количество».
При проведении док-та «постпупление» (количество * коэффициент) записываю количество в баз. Ед. измерения.
Для хранения закупок добавил Регистр накопления «Покупки» с видом «Обороты», измерения «поставщик», «номенклатура» , ресурсы «количество» и «стоимость», Регистратор «Поступление». Добавил в обработку проведения док-та «Поступление» движения по этому регистру.
Добавил журнал документов «Документы поступления» с нужными графами и добавил в подсистему «Закупки».
Для запрета изменения базовой ед. изм. В модуле объекта справочника «Номенклатура»,обращаюсь запросом к регистру накопления «Остатки товара» и если есть запись о движении данной номенклатуры Если РезультатЗапроса.Пустой() тогда отказ=истина;
Задание выполнено. :)
В справочнике контрагентов и в документе “Контакты” завел реквизит “Менеджер”. В момент проведения проверяю, заполнен ли реквизит у контрагента. Если не заполнен – получаю объект и устанавливаю значение реквизита, которое равно текущему пользователю.
Для хранения цен создал регистр сведений “ЦеныНоменклатуры”, периодический, независимый. Цены хранятся в разрезе номенклатуры и типа цен (новый справочник “ТипыЦен”). В документы добавлен реквизит “ТипЦен”. При изменении номенклатуры запросом получаю цены на момент документа (если он уже существует), либо на текущую дату.
Пересчет суммы и цены сделан уже в дом.задании №7. Согласно заданию переделал пересчет цены или количества в зависимости от значений константы “СпособПересчета” (числовая, 0 – пересчет цены, 1 – пересчет количества). Хотя пересчет количества не очень нравится, поскольку может получится 1.25 табуретки :)
Для итоговой суммы в табличной части документа влючен режим подвала и выводится итог реквизита “Сумма”. Для улучшения в документ заведен реквизит “СуммаДокумент”, который заполняется перед записью документа. И исправлен вывод печатной формы, чтобы итог подставлялся из этого реквизита. а не суммировался при прохождении цикла.
Создано два регистра: ОстаткиТоваров (вид остатки) и Закупки (вид оборот). При проведении поступления движения фиксируются в обоих регистрах.
Категорически не согласен с пунктом задания, в котором сказано о создании движения только для приходных накладных. А как же выведение регистров в 0? Поэтому для реализации также фиксирую расход по регистру остатки товаров.
Для проверки запрета изменения базовой единицы в ПередЗаписью модуля объекта номенклатуры делаю следующее:
1. Проверяю, не новый ли товар
2. Проверяю, изменена ли базовая единица
3. Запросом получаю данные по обоим регистрам. Если есть хотя бы одна запись – Отказ выставляется в Истину
<code>
//проверка на существование движений по номенклатуре
Если НЕ ЭтоНовый Тогда
Если Ссылка.БазоваяЕдиницаИзмерения <> ЭтотОбъект.БазоваяЕдиницаИзмерения Тогда
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ 1
| ОстаткиТовара.Номенклатура
|ИЗ
| РегистрНакопления.ОстаткиТовара КАК ОстаткиТовара
|ГДЕ
| ОстаткиТовара.Номенклатура = &Номенклатура
|
|ОБЪЕДИНИТЬ
|
|ВЫБРАТЬ РАЗЛИЧНЫЕ ПЕРВЫЕ 1
| Закупки.Номенклатура
|ИЗ
| РегистрНакопления.Закупки КАК Закупки
|ГДЕ
| Закупки.Номенклатура = &Номенклатура”;
Запрос.Параметры.Вставить(“Номенклатура”, Ссылка);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Сообщить(“Существуют движения по номенклатуре ” + Наименование + ”
|Изменение базовой единицы невозможно!”);
Отказ = Истина;
КонецЦикла;
КонецЕсли;
КонецЕсли;
</code>
Журнал документов закупки создан. Определены графы “Контрагент” и “СуммаДокумента”
P.S. Вроде ничего не забыл написать :)
Оперативно сделано :)
Кстати, при проверке на изменение базовой единицы можно не делать выборку из запроса, а просто проверять на Пустой(). Так будет правильней
Совершенно верно.