Базовый курс. Занятие №8
2-ое занятие по второму блоку базового курса.
Необходимо изучить следующие главы.
Глава 5. Журналы документов.
Глава 6. Настройка командного интерфейса.
Глава 7. Регистры.
Глава 8. Регистры накопления.
Глава 9. Регистры сведений.
Глава 10. Настройка форм.
Также нужно выполнить домашнее задание, текст которого доступен на странице.
Задание необходимо выполнять в ИБ после предыдущего ДЗ.
В этой же теме необходимо написать отчет о выполнении задания.
ps. Участники курса без доступа в мастер-группу отчитываться по домашним заданиям не могут.
— залогиньтесь.
Если не активировали токен — посмотрите видео-инструкцию (видео N5)
Если вы залогинены, у Вас активирован токен доступа, но вы все равно видите эту запись —напишите нам на e-mail поддержки.
Выполнил работу над ошибками ЗД7.
Выполнил ДЗ8.
Сложности возникли на этапе работы с формой. Помню было видео в котором Вы показывали как считать данные из полей формы и из базы, что они различны. Но найти этот урок оказалось также не тривиальной задачей)
В итоге все получилось.
Привязку менеджеров компании сделал с помощью независимого периодического регистра сведений “МенеджерыКлиентов”. В документе “КонтактСКлиентом” создал реквизит “Менеджер”. Для подстановки менеджера использовал процедуру ПриСозданииНаСервере формы документа.
Связь Контактных лиц с Контрагентами сделал с помощью свойства СвязиПараметровВыбора. Обязательные для заполнения реквизиты делал при помощи свойства ПроверкаЗаполнения: ВыдаватьОшибку.
Создал справочник ТипыЦенНоменклатуры и независимый регистр сведений ЦеныНоменклатуры. В документах реализации, закупки и авансовом отчете создал реквизит “ТипыЦен”.
Серверные функции по работе с табличной частью форм документов закупки, реализации и авансового отчета вынес в общий модуль.
Создал регистры накопления “ОстаткиТоваров” (вид Остатки) и Закупки (вид Обороты) регистраторы – документы “Авансовый отчет” и “Закупка”.
Для графы “Итого” журнала документов закупки создал одноименный реквизит в соответствующих документах и обеспечил его заполнение в процедуре ПередЗаписью модуле объекта.
Привязка менеджеров сделана через регистр сведений, сложностей не возникло
В документе «Контакт с клиентом» запись в регистр сведений производится, если после проверки запросом в регистре сведений записей по данному клиенту нет.
Также в качестве эксперимента пыталась сделать проверку через запрос по документам (но проверка на Результат.пустой() всегда возвращалась со значением ложь, даже если документов не было (при этом проверяла через консоль – в ней не выводилось ни одной строки)
Цены номенклатуры хранятся в отдельном регистре сведений. Для удобства внесения информации в регистр создан документ «ВводЦен», который является регистратором по данному регистру. Цены вносятся в разрезе измерений Номенклатура, ВидЦены, ЕдИзмерения
С организацией удобства работы сложностей не возникло, все типовые процедуры вынесены в общий модуль. Были сложности с подстановкой цены номенклатуры.
Регистр накопления остатков – сложностей с организацией проведения не было, пользовалась конструктором.
С журналом документов сложностей не возникло
В целом испытывала ощутимые сложности в работой с запросами. Например, так и не поняла, почему нельзя в одном запросе получать данные нескольких таблиц, например – БазовуюЕдиницу для номенклатуры и цену этой номенклатуры из регистра сведений.
Получать данные из нескольких таблиц можно, но их нужно связывать между собой. В приведенном примере нужно обеспечить связь по номенклатуре.
Задание выполнила, все получилось.
————————————————————————–
Для привязки менеджера к клиенту введен независимый Регистр сведений “МенеджерыКлиента” (Измерение –
Контрагент; ресурс – Менеджер) с периодичностью в пределах дня.
**********************************************************************
// МодульОбъекта док Контакты с клиентом
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
Менеджер = ПараметрыСеанса.ТекущийПользователь;
КонецПроцедуры
——————
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Отбор = Новый Структура(“Контрагент”, Контрагент);
Если РегистрыСведений.МенеджерыКлиента.ПолучитьПоследнее(,Отбор).Менеджер =
Справочники.Пользователи.ПустаяСсылка() Тогда
МенЗапись = РегистрыСведений.МенеджерыКлиента.СоздатьМенеджерЗаписи();
МенЗапись.Период = Дата;
МенЗапись.Контрагент = Контрагент;
МенЗапись.Менеджер = Менеджер;
МенЗапись.Записать();
КонецЕсли;
КонецПроцедуры
//Конец модуляОбъекта док Контакты с клиентом
**********************************************************************
Для хранения цен введен независимый Регистр Сведений “ЦеныНоменклатуры” (Измерения: ТипЦены (новый
справочник),Номенклатура; ресурс – Цена, реквизит – ЕдиницаИзмерения) с периодичностью в пределах
дня.
В документах ПоступлениеТоваров и РеализацияТоваров новый реквизит “ТипЦены”.
Введена новая константа “ВариантПересчетаПриИзмененииСуммы” – тип
ПеречислениеСсылка.ВариантыПересчетаВДокументе.
Новый Регистр Накопления “ОстаткиТоваров”, вид “Остатки” (Измерение – Номенклатура,Качество; ресурс
– Количество)
**********************************************************************
// Модуль формы док ПоступлениеТоваров/РеализацияТоваров
&НаКлиенте
Процедура ТоварыТоварПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ТД.ЕдиницаИзмерения = ОбщийМодульНаСервере.ПолучитьБазовуюЕдиницу
(ТД.Номенклатура,ТД.Номенклатура.БазоваяЕдиница);
ТД.К = ТД.ЕдиницаИзмерения.Коэффициент;
Если не ПустаяСтрока(Объект.ТипЦены) тогда
ТД.Цена = ОбщийМодульНаСервере.ПолучитьЦенуПоТипуЦен(ТД.Номенклатура,
Объект.ТипЦены, Объект.Дата);
ОбщийМодульНаКлиенте.ПересчетСуммы(ТД);
КонецЕсли;
КонецПроцедуры
————————–
&НаКлиенте
Процедура ТоварыЕдиницаИзмеренияПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ВремКоэфф = ТД.К;
ТД.К = ТД.ЕдиницаИзмерения.Коэффициент;
Если ВремКоэфф <> 0 Тогда
ВремЦена = ТД.Цена * ТД.К / ВремКоэфф;
ТД.Цена = ВремЦена;
КонецЕсли;
КонецПроцедуры
————————–
&НаКлиенте
Процедура ТипЦеныПриИзменении(Элемент)
Если Элементы.Товары.ТекущиеДанные<>Неопределено тогда
Для каждого ТД Из Объект.Товары Цикл
ТД.ЕдиницаИзмерения = ОбщийМодульНаСервере.ПолучитьБазовуюЕдиницу
(ТД.Номенклатура, ТД.Номенклатура.БазоваяЕдиница);
ТД.К = ТД.ЕдиницаИзмерения.Коэффициент;
Если не ПустаяСтрока(Объект.ТипЦены) тогда
ТД.Цена = ОбщийМодульНаСервере.ПолучитьЦенуПоТипуЦен
(ТД.Номенклатура, Объект.ТипЦены, Объект.Дата);
ОбщийМодульНаКлиенте.ПересчетСуммы(ТД);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
—————————-
&НаКлиенте
Процедура ДатаПриИзменении(Элемент)
ТипЦеныПриИзменении(“Дата”);
КонецПроцедуры
—————————-
&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ОбщийМодульНаКлиенте.ПересчетСуммы(ТД);
КонецПроцедуры
—————————-
&НаКлиенте
Процедура ТоварыЦенаПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ОбщийМодульНаКлиенте.ПересчетСуммы(ТД);
КонецПроцедуры
—————————–
&НаКлиенте
Процедура ТоварыСуммаПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ОбщийМодульНаКлиенте.ПриИзмененииСуммы(ТД);
КонецПроцедуры
// Конец модуля формы док ПоступлениеТоваров
**********************************************************************
//ОбщийМодульНаКлиенте
Процедура ПересчетСуммы(ТекСтрока) экспорт
ТекСтрока.Сумма = ТекСтрока.Количество*ТекСтрока.Цена;
Конецпроцедуры
—————————–
Процедура ПриИзмененииСуммы(ТекСтрока) экспорт
ВидПересчета = ОбщийМодульНаСервере.ПолучитьКонстантуНаСервере();
Если ВидПересчета = “Количество” тогда
Если ТекСтрока.Цена<>0 тогда
ТекСтрока.Количество = ТекСтрока.Сумма/ТекСтрока.Цена;
КонецЕсли;
Иначе
Если ТекСтрока.Количество<>0 тогда
ТекСтрока.Цена = ТекСтрока.Сумма/ТекСтрока.Количество;
КонецЕсли;
Конецесли;
КонецПроцедуры // ПриИзмененииСуммы()
**********************************************************************
//ОбщийМодульНаСервере
Функция ПолучитьЦенуПоТипуЦен(Товар, ТипЦен, Дата) экспорт
Отбор = Новый Структура(“Номенклатура,ТипЦены”,Товар,ТипЦен);
Цена = РегистрыСведений.ЦеныНоменклатуры.ПолучитьПоследнее(Дата, Отбор).Цена;
Возврат Цена;
КонецФункции
——————————
Функция ПолучитьКонстантуНаСервере() экспорт
Возврат Строка(Константы.ВариантПересчетаПриИзмененииСуммы.Получить());
КонецФункции
**********************************************************************
//МодульОбъекта док ПоступлениеТоваров
Процедура ОбработкаПроведения(Отказ, Режим)
// регистр ОстаткиТоваров Приход
Движения.ОстаткиТоваров.Записывать = Истина;
Для Каждого ТекСтрокаТовары Из Товары Цикл
Движение = Движения.ОстаткиТоваров.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Номенклатура = ТекСтрокаТовары.Номенклатура;
Движение.Качество = ТекСтрокаТовары.СтепеньБрака;
БазЕдИзмКоэф = ОбщийМодульНаСервере.ПолучитьБазовуюЕдиницу
(ТекСтрокаТовары.Номенклатура,ТекСтрокаТовары.Номенклатура.БазоваяЕдиница).Коэффициент;
Если БазЕдИзмКоэф<>ТекСтрокаТовары.К тогда //пересчет в базовые единицы
Движение.Количество = ТекСтрокаТовары.Количество
/БазЕдИзмКоэф*ТекСтрокаТовары.К;
иначе
Движение.Количество = ТекСтрокаТовары.Количество;
КонецЕсли;
КонецЦикла;
// регистр ЗакупкиОтПоставщиков
Движения.ЗакупкиОтПоставщиков.Записывать = Истина;
Для Каждого ТекСтрокаТовары Из Товары Цикл
Движение = Движения.ЗакупкиОтПоставщиков.Добавить();
Движение.Период = Дата;
Если ТипЗнч(Поставщик) = Тип(“СправочникСсылка.Контрагенты”) Тогда
Движение.Поставщик = Поставщик;
иначе
Движение.Поставщик = Справочники.Контрагенты.ПустаяСсылка();
КонецЕсли;
Движение.Номенклатура = ТекСтрокаТовары.Номенклатура;
БазЕдИзмКоэф = ОбщийМодульНаСервере.ПолучитьБазовуюЕдиницу
(ТекСтрокаТовары.Номенклатура,ТекСтрокаТовары.Номенклатура.БазоваяЕдиница).Коэффициент;
Если БазЕдИзмКоэф<>ТекСтрокаТовары.К тогда //пересчет в базовые единицы
Движение.Количество = ТекСтрокаТовары.Количество
/БазЕдИзмКоэф*ТекСтрокаТовары.К;
иначе
Движение.Количество = ТекСтрокаТовары.Количество;
КонецЕсли;
Движение.Стоимость = ТекСтрокаТовары.Сумма;
КонецЦикла;
КонецПроцедуры
—————————-
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
СуммаДокумента = Товары.Итог(“Сумма”);
КонецПроцедуры
//Конец МодуляОбъекта док ПоступлениеТоваров
**********************************************************************
Проверка на изменение базовой единицы номенклатуры, имеющей движение в регистрах реализована в Общем
модуле и вызывается из процедураы модуля объекта Номенклатура
Процедура ПередЗаписью(Отказ)
НовыйЭл = ЭтоНовый();
Если не НовыйЭл Тогда
ЕстьСсылки = Неопределено;
Если Ссылка.БазоваяЕдиница <> БазоваяЕдиница И
ОбщийМодульНаСервере.НайтиСсылкиНаБазовуюЕдиницу(Ссылка) Тогда
Сообщить(“Нельзя менять базовую единицу, по ней есть
движения!”,СтатусСообщения.Важное);
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
——————————–
//Модуль объекта Номенклатура
Процедура ПередЗаписью(Отказ)
НовыйЭл = ЭтоНовый();
Если не НовыйЭл Тогда
ЕстьСсылки = Неопределено;
Если Ссылка.БазоваяЕдиница <> БазоваяЕдиница И
ОбщийМодульНаСервере.НайтиСсылкиНаБазовуюЕдиницу(Ссылка) Тогда
Сообщить(“Нельзя менять базовую единицу, по ней есть
движения!”,СтатусСообщения.Важное);
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
——————————–
//ОбщийМодульНаСервере
Функция НайтиСсылкиНаБазовуюЕдиницу(Товар) экспорт
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ ПЕРВЫЕ 1
| ЦеныНоменклатуры.ЕдиницаИзмерения.Ссылка КАК ЕдиницаИзмерения
|ИЗ
| РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
|ГДЕ
| ЦеныНоменклатуры.ЕдиницаИзмерения.ЕдиницаПоКлассификатору =
&ЕдиницаПоКлассификатору
| И ЦеныНоменклатуры.ЕдиницаИзмерения.Владелец = &Товар
| И (НЕ ЦеныНоменклатуры.ЕдиницаИзмерения.ПометкаУдаления)”;
Запрос.УстановитьПараметр(“ЕдиницаПоКлассификатору”, Товар.БазоваяЕдиница);
Запрос.УстановитьПараметр(“Товар”, Товар);
Результат = Запрос.Выполнить();
Возврат НЕ Результат.Пустой();
КонецФункции
Повредил “пишущую” руку поэтому под отстал, буду наверстывать. ДЗ 8 Сделал. Кое что я сделал не так как в Ваших решениях. Вопросы:
У Вас при проведении Поступления с использованием запроса по регистру остатков в РезультатеЗапроса не указан ВидДвижения. Тем не менее Движение идет в “приход”. Это так по умолчанию?
У Вас при проверки возможности изменения базовой ед.измерения в запросе указывается выбрать количество … Не “проще/легче серверу” “выбрать первые 1” или здесь есть некая “хитрость”
Что эффективней для регистра сведений при получении из него информации чтение набора записей с установленными фильтрами или запрос?
Остальные вопросы в мастер группу отправляю.
По умолчанию – вид движения Приход.
Действительно, “Выбрать Первые 1” это более эффективная конструкция – серверу не нужно делать никаких вычислений.
В простых случаях результат будет одинаковый (запрос и объектное чтение). Однако, запрос это более эффективное средство. В частности в запросе можно учитывать ограничения на уровне записей (RLS). Поэтому для любого чтения данных рекомендуется использовать запрос.
Задание выполнено. Не без ошибок конечно, но помогло в разрешении вопросов решение Д/З. На подробное описание решения катастрофически не хватает времени.
P.S. В одной из мастер группе базового курса от 05.04.11 мы рассматривали тип “Форматированный документ”. В версии платформы 8.2.10.(дальше цифр не помню, у клиентов дело было) я такого типа не нашел, а в версии 8.2.13.202 он есть (может и в ранних версиях есть, просто с этой работаю).
Форматированный документ появился в релизе 8.2.11.
Плотно отвлекся от учебы работой на выходных и далее — поэтому опоздал…
1) Добавил регистр сведений «МенеджерыКлиента». Измерения — Контрагент(СправочникСсылка.Контрагенты), Ресурсы — Менеджер(СправочникСсылка.Пользователи). Периодичность — в пределах секунды, реж.записи — независимый.
2)В МО документа ИсторияКонтактов в Процедуре ОбработкаЗаполнения для ЭтоНовый() заполнилняю дату и менеджера(текущим пользователем).
<code>
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
// Вставить содержимое обработчика.
Если ЭтоНовый() Тогда
Дата = наСервере_ВремяНаСервере.ПолучитьВремяНаСервере();
ТекПользователь = Справочники.Пользователи.НайтиПоРеквизиту(“ПользовательИБ”, ПользователиИнформационнойБазы.ТекущийПользователь().УникальныйИдентификатор);
Если ЗначениеЗаполнено(ТекПользователь) Тогда
Менеджер = ТекПользователь;
Иначе
Сообщить(“Необходимо выполнить синхронизацию пользователей!”);
КонецЕсли;
КонецЕсли
КонецПроцедуры
</code> В МО ИсторияКонтактов в процедуре ОбработкаПроведения если у Контрагента нет Менеджера — добавляю в РС текущего из документа
<code>
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
// Вставить содержимое обработчика.
Отбор = Новый Структура(“Контрагент”,Контрагент.Ссылка);
ПоследняяЗапись = РегистрыСведений.МенеджерыКлиента.ПолучитьПоследнее(,Отбор).Менеджер;
Если НЕ ЗначениеЗаполнено(ПоследняяЗапись) Тогда
Набор = РегистрыСведений.МенеджерыКлиента.СоздатьНаборЗаписей();
Набор.Отбор.Контрагент.Установить(Контрагент);
Запись = Набор.Добавить();
Запись.Контрагент = Контрагент;
Запись.Менеджер = Менеджер;
Запись.Период = дата;
Набор.Записать();
КонецЕсли;
КонецПроцедуры
</code>
4)Добавил РС «ЦеныНоменклатуры». Измерения — Номенклатура(СправочникСсылка.Номенклатура, ведущее), ТипЦены(СправочникСсылка.ТипЦены). Ресурсы — Цена. Периодичность — в пределах дня, реж.записи — независимый.
5)В «ДокРеализации» добавил реквизит — ТипЦены. В МФ «ДокРеализации» с учетом этого изменил
<code>
&НаКлиенте
Процедура СтрокиНоменклатураПриИзменении(Элемент)
//авто заполнить цену
ТЦ = Объект.ТипЦены;
Если ЗначениеЗаполнено(ТЦ) Тогда
ДатаДокумента = Объект.Дата;
ТД = Элементы.Строки.ТекущиеДанные;
ТД.Цена = ПолучитьЦену(ТД.Номенклатура, ТЦ, ДатаДокумента);
ТД.ЕдИзмНом = ПолучитьОснЕдИзмНом(ТД.Номенклатура); ПересчитатьСумму();
КонецЕсли
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьЦену(Ссылка, ТЦ, ДатаДокумента)
//Сейчас цена живет в регистре сведений
//Возврат Ссылка.Цена;
Отбор = Новый Структура(“Номенклатура,ТипЦены”, Ссылка, ТЦ);
ЦенаНомкл = РегистрыСведений.ЦеныНоменклатуры.ПолучитьПоследнее(ДатаДокумента,Отбор).Цена;
Если ЗначениеЗаполнено(ЦенаНомкл) Тогда
Возврат ЦенаНомкл;
Иначе
Сообщить(“Для номенклатуры нет цены!”);
Возврат 0;
КонецЕсли;
КонецФункции //
</code>
6)Добавил перечисление «ПересчетОтСуммы» – два элемента «ПересчетКоличества» и «ПересчетЦены». Добавил константу «ПересчетОтСуммы» тип – «ПеречислениеСсылка.ПересчетОтСуммы». В МФ «ДокРеализации» с учетом этого добавил пересчет кол-во или цены при изменении суммы
<code>
&НаКлиенте
Процедура СтрокиСуммаПриИзменении(Элемент)
ТД = Элементы.Строки.ТекущиеДанные;
ТекНастройка=””;
РезультатПересчета = ПересчитатьОтСуммы(ТД.Колво, ТД.Цена, ТД.Сумма, ТекНастройка);
Если ЗначениеЗаполнено(РезультатПересчета) И ЗначениеЗаполнено(ТекНастройка) Тогда
Если ТекНастройка=1 Тогда
ТД.Колво = РезультатПересчета;
ИначеЕсли ТекНастройка=2 Тогда
ТД.Цена = РезультатПересчета;
Иначе
//ничего
Сообщить(“Пересчитать от суммы нельзя!”)
КонецЕсли;
Иначе
Сообщить(“Пересчитать от суммы нельзя!”)
//надо еще вернуть старую сумму
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПересчитатьОтСуммы(ТДКолво, ТДЦена, ТДСумма, ТекНастройка)
КонстПересч = Константы.ПересчетОтСуммы.Получить();
Если КонстПересч=Перечисления.ПересчетОтСуммы.ПересчетКоличества И ЗначениеЗаполнено(ТДЦена) Тогда
ИтогПересч = Окр(ТДСумма/ТДЦена,2);
ТекНастройка = 1;
ИначеЕсли КонстПересч=Перечисления.ПересчетОтСуммы.ПересчетЦены И ЗначениеЗаполнено(ТДКолво)Тогда
ИтогПересч = Окр(ТДСумма/ТДКолво,2);
ТекНастройка = 2;
Иначе
ИтогПересч = 0;
ТекНастройка = 0;
КонецЕсли;
Возврат ИтогПересч;
КонецФункции
</code>
Остальное поведение документов по учету ТМЦ уже было.
7) Добавил РН «ОстаткиТоваров». Измерения — Номенклатура, Качество. Ресурсы — Колво. Реквизиты — ЕдИзм. В процедуре движения добавил пересчет количества в основную ЕдИзм
<code>
Процедура ОбработкаПроведения(Отказ, Режим)
// регистр ОстаткиТоваров Приход
Движения.ОстаткиТоваров.Записывать = Истина;
Для Каждого ТекСтрокаСтроки Из Строки Цикл
Движение = Движения.ОстаткиТоваров.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Номенклатура = ТекСтрокаСтроки.Номенклатура;
Движение.Качество = ТекСтрокаСтроки.Качество;
БЕИзм = ТекСтрокаСтроки.Номенклатура.Ссылка.БазоваяЕдиницаИзмерения;
ЕИДокум = ТекСтрокаСтроки.ЕдИзмНом.ЕдИзм;
Если ЕИДокум = БЕИзм Тогда
Движение.Колво = ТекСтрокаСтроки.Колво;
Движение.ЕдИзм = ТекСтрокаСтроки.ЕдИзмНом;
Иначе
//ищу коэф.пересчета ед.измерения
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| ЕдиницыИзмеренияНоменклатуры.ЕдИзм,
| ЕдиницыИзмеренияНоменклатуры.КоэфПересчета
|ИЗ
| Справочник.ЕдиницыИзмеренияНоменклатуры КАК ЕдиницыИзмеренияНоменклатуры
|ГДЕ
| ЕдиницыИзмеренияНоменклатуры.Владелец = &Владелец
| И ЕдиницыИзмеренияНоменклатуры.ЕдИзм = &ЕдИзм”;
Запрос.УстановитьПараметр(“Владелец”, Движение.Номенклатура);
Запрос.УстановитьПараметр(“ЕдИзм”, ЕИДокум);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
ВыборкаДетальныеЗаписи.Следующий();
Движение.Колво = Окр(ТекСтрокаСтроки.Колво*ВыборкаДетальныеЗаписи.КоэфПересчета,3);
//в движениях проставляю Базовую ед.изм
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| ЕдиницыИзмеренияНоменклатуры.Ссылка
|ИЗ
| Справочник.ЕдиницыИзмеренияНоменклатуры КАК ЕдиницыИзмеренияНоменклатуры
|ГДЕ
| ЕдиницыИзмеренияНоменклатуры.Владелец = &Владелец
| И ЕдиницыИзмеренияНоменклатуры.ЕдИзм = &ЕдИзм”;
Запрос.УстановитьПараметр(“Владелец”, Движение.Номенклатура);
Запрос.УстановитьПараметр(“ЕдИзм”, БЕИзм);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
ВыборкаДетальныеЗаписи.Следующий();
Движение.ЕдИзм = ВыборкаДетальныеЗаписи.Ссылка;
КонецЕсли
КонецЦикла;
// регистр ЗакупкиОтПоставщиков
Движения.ЗакупкиОтПоставщиков.Записывать = Истина;
Для Каждого ТекСтрокаСтроки Из Строки Цикл
Движение = Движения.ЗакупкиОтПоставщиков.Добавить();
Движение.Период = Дата;
Движение.Поставщик = Поставщик;
Движение.Номенклатура = ТекСтрокаСтроки.Номенклатура;
Движение.Колво = ТекСтрокаСтроки.Колво;
Движение.Цена = ТекСтрокаСтроки.Цена;
Движение.Сумма = ТекСтрокаСтроки.Сумма;
Движение.ЕдИзм = ТекСтрокаСтроки.ЕдИзмНом.ЕдИзм;
КонецЦикла;
КонецПроцедуры </code>
8) Добавил РН «ЗакупкиОтПоставщика». Измерения — Поставщик, Номенклатура. Ресурсы — Колво, Цена, Сумма. Движения сделал конструктором.
9)Проверку, которая запрещает изменять базовую ед.изм для номенклатуры, если по ней уже есть движения реализовал в МО Справочника «Номенклатура»
<code>
Процедура ПередЗаписью(Отказ)
// Проверить при изменении у номенклатуры основной ед.изм чтобы по ней не было движений
Если Не ЭтоНовый() Тогда
//проверяю только у старичков
СтараяБазЕдИзм = Ссылка.БазоваяЕдиницаИзмерения;
Если Не БазоваяЕдиницаИзмерения = СтараяБазЕдИзм Тогда
//необходимо проверять регистры – не должно быть движений с ЕдИзм = Ссылка.БазоваяЕдиницаИзмерения
//перед проверкой найдем СтараяБазЕдИзм в ЕдИзмНоменклатуры
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| ЕдиницыИзмеренияНоменклатуры.Ссылка
|ИЗ
| Справочник.ЕдиницыИзмеренияНоменклатуры КАК ЕдиницыИзмеренияНоменклатуры
|ГДЕ
| ЕдиницыИзмеренияНоменклатуры.Владелец = &Владелец
| И ЕдиницыИзмеренияНоменклатуры.ЕдИзм = &ЕдИзм”;
Запрос.УстановитьПараметр(“Владелец”, Ссылка);
Запрос.УстановитьПараметр(“ЕдИзм”, СтараяБазЕдИзм);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
КолЗап=ВыборкаДетальныеЗаписи.Количество();
Если КолЗап>1 Тогда
Сообщить(“В ЕдИзмНоменклатуры две одинаковые записи по этой номенклатуре! Изменение базовой единицы измерения не возможно!”);
Отказ = Истина;
Иначе
ВыборкаДетальныеЗаписи.Следующий();
ЕдИзмДляПоиска = ВыборкаДетальныеЗаписи.Ссылка;
КонецЕсли;
Если НЕ Отказ Тогда
//первая проверка в ОстаткиТоваров
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ ПЕРВЫЕ 1
| ОстаткиТоваров.Номенклатура,
| ОстаткиТоваров.ЕдИзм
|ИЗ
| РегистрНакопления.ОстаткиТоваров КАК ОстаткиТоваров
|ГДЕ
| ОстаткиТоваров.Номенклатура = &Номенклатура
| И ОстаткиТоваров.ЕдИзм = &ЕдИзм”;
Запрос.УстановитьПараметр(“ЕдИзм”, ЕдИзмДляПоиска);
Запрос.УстановитьПараметр(“Номенклатура”, Ссылка);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
КолЗап=ВыборкаДетальныеЗаписи.Количество();
Если КолЗап>0 Тогда
Сообщить(“Изменение базовой единицы измерения не возможно!-Есть движения в РН ОстаткиТоваров”);
Отказ = Истина;
КонецЕсли;
КонецЕсли;
Если НЕ Отказ Тогда
//вторая проверка в ЗакупкиОтПоставщиков — все аналогично /первая проверка в ОстаткиТоваров
КонецЕсли
КонецЕсли;
КонецЕсли
КонецПроцедуры
</code>
Спасибо, заработало! Код тот уже стерла, сравнить не с чем, но я, видимо, саму структуру Отбор пыталась передавать, а не ПараметрыФормы.
Задание выполнил:
1. Для задачи поиска движений по товару при изменении базовой ед.изм.
в серверный общий модуль ОбщиеФункцииСервер добавил универсальную
проверку на наличия записей в любых регистрах накопления и сведений
по измерениям, соответствующим по типу переданной Ссылке.
Сознательно не использовал Запросы, хотел сделать на “объектах”.
<code>
//Проверка наличия записей в регистрах накопления и сведений
//по измерениям, соответствующим переданной Ссылке.
Функция НаличиеДвиженийПоСсылке(Ссылка,СтрДиагностики) Экспорт
Если Ссылка.Пустая() Тогда
СтрДиагностики=”Передана пустая ссылка.”;
Возврат Ложь;
КонецЕсли;
ТипОбъекта=ТипЗнч(Ссылка);
СтрЕстьЗаписиВРегистрах=””;
Для каждого Рег Из Метаданные.РегистрыСведений Цикл
Для каждого Измерение Из Рег.Измерения Цикл
Если Измерение.Тип.СодержитТип(ТипОбъекта) Тогда
МенеджерРег=РегистрыСведений[Рег.Имя];
Измерение_Имя=Измерение.Имя;
Набор= МенеджерРег.СоздатьНаборЗаписей();
Набор.Отбор[Измерение.Имя].Установить(Ссылка);
Набор.Прочитать();
Если Набор.Количество()>0 Тогда
СтрЕстьЗаписиВРегистрах=СтрЕстьЗаписиВРегистрах+”, “+Рег.Имя+” (“+Измерение_Имя+”)”;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Для каждого Рег Из Метаданные.РегистрыНакопления Цикл
Для каждого Измерение Из Рег.Измерения Цикл
Если Измерение.Тип.СодержитТип(ТипОбъекта) Тогда
МенеджерРег=РегистрыНакопления[Рег.Имя];
Измерение_Имя=Измерение.Имя;
Выборка=МенеджерРег.Выбрать(,,Новый Структура(“”+Измерение_Имя,Ссылка));
Если Выборка.Следующий()>0 Тогда
СтрЕстьЗаписиВРегистрах=СтрЕстьЗаписиВРегистрах+”, “+Рег.Имя+” (“+Измерение_Имя+”)”;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Если СтрДлина(СтрЕстьЗаписиВРегистрах)>0 Тогда
СтрДиагностики=”Записи в регистрах: “+Сред(СтрЕстьЗаписиВРегистрах,2);
Возврат Истина;
Иначе
СтрДиагностики=”Нет записей в регистрах.”;
Возврат Ложь;
КонецЕсли;
КонецФункции // НаличиеДвиженийПоСсылке()
</code>
Вопрос: Хотя в видео было сказано, что достаточно кода:
<code>
Набор= МенеджерРег.СоздатьНаборЗаписей();
Набор.Отбор[Измерение.Имя].Установить(Ссылка);
</code>
для установки отбора, но так почему-то
не получилось и пришлось вызывать:
<code>
Набор.Прочитать();
</code>
2. В серверном общем модуле ОбщиеРаботаСноменклатурой получаю цену
из регистра сведений по измерениям и дате:
<code>
Функция ПолучитьЦену(Товар,КатегорияЦены,Дата) Экспорт
Отбор=Новый Структура(“Номенклатура,КатегорияЦен”,Товар,КатегорияЦены);
Срез=РегистрыСведений.ЦеныНоменклатуры.СрезПоследних(Дата,Отбор);
Если Срез.Количество()>0 Тогда
Возврат Срез[0].Цена;
КонецЕсли;
Возврат 0;
КонецФункции // ПолучитьЦену()
</code>
3. Модуль формы документа ПоступлениеТовара новые процедуры
(процедура Пересчитать() перезаполняет цены из рег. свед.
и пересчитывает суммы в ТЧ):
<code>
&НаКлиенте
Процедура ТоварыТоварПриИзменении(Элемент)
ТД=Элементы.Товары.ТекущиеДанные;
Если НЕ ТД.Товар.Пустая() Тогда
ТД.ЕдиницаИзмерения=ОбщиеРаботаСНоменклатурой.БазоваяЕдИзм(ТД.Товар);
Если НЕ Объект.КатегорияЦены.Пустая() Тогда
ТД.Цена=ОбщиеРаботаСНоменклатурой.ПолучитьЦену(ТД.Товар,Объект.КатегорияЦены,Объект.Дата);
ТоварыЦенаПриИзменении(Элемент);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
УстановитьСумму();
КонецПроцедуры
&НаКлиенте
Процедура ТоварыЦенаПриИзменении(Элемент)
УстановитьСумму();
КонецПроцедуры
&НаКлиенте
Процедура УстановитьСумму()
ТД=Элементы.Товары.ТекущиеДанные;
ТД.Сумма=ТД.Количество*ТД.Цена*ТД.ЕдиницаИзмерения.Коэффициент;
КонецПроцедуры // УстановитьСумму()
&НаКлиенте
Процедура КатегорияЦеныПриИзменении(Элемент)
Пересчитать();
КонецПроцедуры
&НаКлиенте
Процедура Пересчитать()
Если НЕ Объект.КатегорияЦены.Пустая() Тогда
Если Объект.Товары.Количество()>0 Тогда
Если Вопрос(“Пересчитать цены товаров?”, РежимДиалогаВопрос.ДаНет) = КодВозвратаДиалога.Да Тогда
Для каждого Строка Из Объект.Товары Цикл
Строка.Цена=ОбщиеРаботаСНоменклатурой.ПолучитьЦену(Строка.Товар,Объект.КатегорияЦены,Объект.Дата);
Строка.Сумма=Строка.Цена*Строка.Количество*Строка.ЕдиницаИзмерения.Коэффициент;
КонецЦикла;
ОбновитьОтображениеДанных();
КонецЕсли;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ТоварыСуммаПриИзменении(Элемент)
ПересчитатьЦену=ОбщиеФункцииСервер.ПрПересчитатьЦенуСервер();
Если ПересчитатьЦену Тогда
ТД=Элементы.Товары.ТекущиеДанные;
ТД.Количество=?(ТД.Количество=0,1,ТД.Количество);
ТД.Цена=ТД.Сумма/(ТД.Количество*ТД.ЕдиницаИзмерения.Коэффициент);
Иначе
ТД=Элементы.Товары.ТекущиеДанные;
ТД.Цена=?(ТД.Цена=0,1,ТД.Цена);
ТД.Количество=ТД.Сумма/(ТД.Цена*ТД.ЕдиницаИзмерения.Коэффициент);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ПересчитатьЦеныТовара(Команда)
Пересчитать();
КонецПроцедуры
</code>
4. Модуль объекта документа КонтактСКлиентом:
<code>
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
Если ТипЗнч(ДанныеЗаполнения) = Тип(“СправочникСсылка.Контрагенты”) Тогда
Контрагент = ДанныеЗаполнения.Ссылка;
ИначеЕсли ТипЗнч(ДанныеЗаполнения) = Тип(“СправочникСсылка.КонтактныеЛица”) Тогда
Контрагент = ДанныеЗаполнения.Владелец;
КонтактноеЛицо = ДанныеЗаполнения.Ссылка;
КонецЕсли;
Менеджер=ОбщиеФункцииСервер.ТекущийПользовательВСпрПользователи();
КонецПроцедуры
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
// Проверим Есть ли у клиента уже документы Контакт
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ ПЕРВЫЕ 1
| КонтактСКлиентом.Ссылка КАК ДокКонтакт
|ИЗ
| Документ.КонтактСКлиентом КАК КонтактСКлиентом
|ГДЕ
| КонтактСКлиентом.Контрагент = &Контрагент
| И КонтактСКлиентом.Проведен
| И КонтактСКлиентом.МоментВремени < &МоментВремени”;
Запрос.УстановитьПараметр(“Контрагент”, Контрагент.Ссылка);
Запрос.УстановитьПараметр(“МоментВремени”, ЭтотОбъект.МоментВремени());
Если Запрос.Выполнить().Пустой() Тогда
Набор= РегистрыСведений.МенеджерыКлиента.СоздатьНаборЗаписей();
Набор.Отбор.Контрагент.Значение=Контрагент;
Набор.Прочитать();
Запись=Набор.Добавить();
Запись.Период=Дата;
Запись.Контрагент=Контрагент;
Запись.Менеджер=Менеджер;
Набор.Записать()
КонецЕсли;
КонецПроцедуры
</code>
К сожалению, ситуация на работе складывается так, что в будни могу только смотреть видеокурсы, домашку же приходится переносить на выходные дни, вылетая из графика, поэтому все делаю с запозданием.
Привязка менеджеров к клиентам реализована периодическим регистром сведений МенеджерыКонтрагентов.
В документе “КонтактСКлиентом” реквизит менеджер заполняется из ПараметрСеанса.ТекущийПользователь. При проведении документа “КонтактСКлиентом” анализируется наличие других документов с этим же контрагентом (выполняется запросом) и, если
таких нет, то выполняется запись в регистр сведений, фиксируя связь менеджера и контрагента на дату документа. Выбор контактного лица осуществляется в справочнике “КонтактныеЛицаКонтрагентов” с настроенным свойством “Связи параметров выбора” по “Отбор.Владелец (Контрагент)”. Хранение видов цен реализовано одноименным справочником. Хранение самих цен реализовано периодическим регистром сведений ЦеныНаТовары (ВидЦены/Номенклатура, Цена). Автоматическая подстановка цен производится при изменении реквизита ВидЦены методом СрезПоследних по виду цены и дате документа.
Подстановка цены при выборе номенклатуры производится методом ПолучитьПоследнее по Номенклатуре, Виду цены и дате документа.
Созданы регистры накопления ОстаткиТоваров и Закупки и движения по ним в приходной накладно йи авансовом отчете. Проверка на использование Базовой единицы производится в обработке события НачалоВыбора для реквизита БазоваяЕдиница, запрос по регистру ОстаткиТоваров, если он не пустой, то изменять единицу уже нельзя. Для отображения в журнале сумм документов в документы добавлен реквизит “СуммаПоДокументу” и в обработке ПередЗаписью выполняется расчет значения этого реквизита “Основная.Итог(“Сумма”)”.
В общем и целом затруднений нет, но забуксовал на ситуации, когда во всех документах имеется одинаковый функционал (пересчет цен, сумм, работа с табличной частью). Хорошо бы все это вынести в общие процедуры, но я так и не придумал красивого решения, посмотрю как это сделано у вас.
Задание выполнил, больших трудностей не возникло.
В документе “Контакт с клиентом” при проведении записывается первый контакт с клиентом в регистр сведений через набор записей.
Процедура пересчета табличных частей документов вынесена в общий модуль “ОбщиеФункцииКлиент”
<code>
Процедура Пересчет(Элемент, ТД) Экспорт
Если Элемент.Имя = “ТоварыСумма” Тогда
Если ОбщиеФункцииСервер.ПолучитьВарПересчетаСервер() = 0 Тогда
ТД.Цена = ТД.Сумма/ТД.Количество;
Иначе
ТД.Количество = ТД.Сумма/ТД.Цена;
КонецЕсли;
Иначе
ТД.Сумма = ТД.Количество*ТД.Цена;
КонецЕсли;
КонецПроцедуры
</code>
Документ “Поступление товаров” делает движения по регистрам при обходе результата запроса, а не табличной части:
<code>
Процедура ОбработкаПроведения(Отказ, Режим)
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ РАЗЛИЧНЫЕ
| ПоступлениеТоваровТовары.Номенклатура,
| ПоступлениеТоваровТовары.Качество,
| ПоступлениеТоваровТовары.ЕдиницаИзмерения.К КАК Коэф,
| ПоступлениеТоваровТовары.Количество,
| ПоступлениеТоваровТовары.Сумма,
| ПоступлениеТоваровТовары.Ссылка.Контрагент
|ИЗ
| Документ.ПоступлениеТоваров.Товары КАК ПоступлениеТоваровТовары
|ГДЕ
| ПоступлениеТоваровТовары.Ссылка = &Ссылка”;
Запрос.УстановитьПараметр(“Ссылка”, Ссылка);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Движения.ОстаткиТоваров.Записывать = Истина;
Движения.Покупки.Записывать = Истина;
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Движение = Движения.ОстаткиТоваров.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Товар = ВыборкаДетальныеЗаписи.Номенклатура;
Движение.Качество = ВыборкаДетальныеЗаписи.Качество;
Движение.Количество = ВыборкаДетальныеЗаписи.Количество * ВыборкаДетальныеЗаписи.Коэф;
// регистр Покупки
Движение = Движения.Покупки.Добавить();
Движение.Период = Дата;
Движение.Поставщик = ВыборкаДетальныеЗаписи.Контрагент;
Движение.Товар = ВыборкаДетальныеЗаписи.Номенклатура;
Движение.Количество = ВыборкаДетальныеЗаписи.Количество * ВыборкаДетальныеЗаписи.Коэф;
Движение.Стоимость = ВыборкаДетальныеЗаписи.Сумма;
КонецЦикла;
КонецПроцедуры
</code>
Задание выполнил. Для хранения менеджера создал у контрагента реквизит. При проведении документа «Событие» пишу менеджера контрагенту, если поле менеджера пустое.
Цены хранятся стандартно – в регистре сведений. Для получения цены создал функцию в общем модуле (сервер). Также создал функции пересчета строки документа в общем модуле (клиент).
Создал два регистра Остатки номенклатуры и Закупки (оборотный регистр). Проведение по регистрам реализовал следующим образом:
<code>
Движения.Закупки.Записывать = Истина;
Движения.ОстаткиТоваров.Записывать = Истина;
Запрос = Новый Запрос;
Запрос.Текст = “ВЫБРАТЬ
| ПоступлениеТоваровТовары.Ссылка,
| ПоступлениеТоваровТовары.Номенклатура,
| ПоступлениеТоваровТовары.Коэффициент,
| ПоступлениеТоваровТовары.Количество,
| ПоступлениеТоваровТовары.Сумма,
| ПоступлениеТоваровТовары.Качество
|ПОМЕСТИТЬ Товары
|ИЗ
| Документ.ПоступлениеТоваров.Товары КАК ПоступлениеТоваровТовары
|ГДЕ
| ПоступлениеТоваровТовары.Ссылка = &Ссылка
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Товары.Номенклатура,
| Товары.Качество,
| СУММА(Товары.Количество * Товары.Коэффициент) КАК Количество,
| &Дата КАК Период
|ИЗ
| Товары КАК Товары
|
|СГРУППИРОВАТЬ ПО
| Товары.Номенклатура,
| Товары.Качество
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Товары.Номенклатура,
| СУММА(Товары.Коэффициент * Товары.Коэффициент) КАК Количество,
| &Дата КАК Период,
| &Контрагент КАК Поставщик,
| СУММА(Товары.Сумма) КАК Сумма
|ИЗ
| Товары КАК Товары
|
|СГРУППИРОВАТЬ ПО
| Товары.Номенклатура”;
Запрос.УстановитьПараметр(“Дата”,Дата);
Запрос.УстановитьПараметр(“Контрагент”,Контрагент);
Запрос.УстановитьПараметр(“Ссылка”,Ссылка);
Пакет = Запрос.ВыполнитьПакет();
Движения.ОстаткиТоваров.Загрузить(Пакет[1].Выгрузить());
Движения.Закупки.Загрузить(Пакет[2].Выгрузить());
</code>
Перед записью элемента номенклатуры добавил проверку возможности смены базовой единицы.
Для выполнения условия задания: «Необходимо обеспечить привязку менеджеров компании (тип данных – справочник «Пользователи») к клиентам. Считается, что в один момент времени с клиентом может работать только один менеджер, но с течением времени менеджер у контрагента может измениться» создан независимый регистр сведений «МенеджерыКлиентов». Периодичность – в пределах дня.
Измерение – «Контрагент».
Ресурс – «Менеджер».
В документе «КонтактСКонтрагентом» создан реквизит «Менеджер».
Для выполнения условия задания: «При создании нового документа в реквизит нужно подставлять текущего пользователя» в форме документа «КонтактСКонтрагентом» создана процедура «ПриСозданииНаСервере»:
<code>
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Объект.Ссылка = Документы.КонтактСКонтрагентом.ПустаяСсылка() Тогда
Объект.Менеджер = ПараметрыСеанса.глПользователь;
КонецЕсли;
КонецПроцедуры
</code>
Для выполнения условия задания: «При проведении документа необходимо выполнять анализ, если происходит первый контакт с контрагентом, то необходимо в качестве менеджера для контрагента нужно установить значение, указанное в документе» в модуле объекта документа «КонтактСКонтрагентом» написан код:
<code>
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
ПроверкаМенеджераКонтрагента();
КонецПроцедуры
Процедура ПроверкаМенеджераКонтрагента()
Запрос = Новый Запрос;
Запрос.Текст = ”
|ВЫБРАТЬ
| МенеджерыКлиентовСрезПоследних.Контрагент
|ИЗ
| РегистрСведений.МенеджерыКлиентов.СрезПоследних(, Контрагент = &Контрагент) КАК МенеджерыКлиентовСрезПоследних”;
Запрос.УстановитьПараметр(“Контрагент”, Контрагент);
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
ЗаполнитьМенеджераУКонтрагента();
КонецЕсли;
КонецПроцедуры
Процедура ЗаполнитьМенеджераУКонтрагента()
МенЗаписи = РегистрыСведений.МенеджерыКлиентов.СоздатьМенеджерЗаписи();
МенЗаписи.Период = Дата;
МенЗаписи.Контрагент = Контрагент;
МенЗаписи.Менеджер = Менеджер;
МенЗаписи.Записать();
КонецПроцедуры
</code>
Для выполнения условия задания: «обеспечьте, чтобы система позволяла выбирать контактныхлиц, указанного в документе контрагента» в модуле формы документа «КонтактСКонтрагентом» написан код:
<code>
&НаКлиенте
Процедура КонтактноеЛицоНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ДанныеВыбора = Новый СписокЗначений;
ДанныеВыбора.ЗагрузитьЗначения(КонтактныеЛицаКонтрагента(Объект.Контрагент));
КонецПроцедуры
&НаСервереБезКонтекста
Функция КонтактныеЛицаКонтрагента(Контрагент) Экспорт
ДанныеВыбора = Новый СписокЗначений;
Запрос = Новый Запрос;
Запрос.Текст = ”
| ВЫБРАТЬ
| КонтрагентыКонтактныеЛица.КонтактноеЛицо
|ИЗ
| Справочник.Контрагенты.КонтактныеЛица КАК КонтрагентыКонтактныеЛица
|ГДЕ
| КонтрагентыКонтактныеЛица.Ссылка = &Контрагент”;
Запрос.УстановитьПараметр(“Контрагент”, Контрагент);
СписокКонтактныхЛиц = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку(“КонтактноеЛицо”);
Возврат СписокКонтактныхЛиц;
КонецФункции
</code>
Для выполнения условия задания «Обеспечьте хранение цен на товары. При этом необходимо предусмотреть ведение различных прайс-листов, например, цены розничные, мелкооптовые и т.д. Цены задаютсяпользователем самостоятельно» сделано следующее:
– Создан справочник «ТипыЦенНоменклатуры»;
– Создан независимый регистр сведений «ЦеныНоменклатуры».
Для выполнения условия задания «В документах закупки и отгрузки создайте реквизит, в котором пользователь будет выбирать прайс, для заполнения цен текущего документа» в документах «ПоступлениеТоваров» и «РеализацияТоваров» создан реквизит «ТипЦенНоменклатуры».
Для повышения удобства работы с документами по учету ТМЦ создан общий модуль «УчетТМЦ» с кодом:
<code>
Функция ЦенаНоменклатуры(Номенклатура, ТипЦены, Дата) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| ЦеныНоменклатурыСрезПоследних.Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
| &Дата,
| Номенклатура = &Номенклатура
| И ТипЦены = &ТипЦены) КАК ЦеныНоменклатурыСрезПоследних”;
Параметры = Новый Массив(2);
Параметры[0] = Дата;
Параметры[1] = ВидГраницы.Включая;
Граница = Новый(Тип(“Граница”), Параметры);
Запрос.УстановитьПараметр(“Дата”, Граница);
Запрос.УстановитьПараметр(“Номенклатура”, Номенклатура);
Запрос.УстановитьПараметр(“ТипЦены”, ТипЦены);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
нВозврат = Выборка.Цена;
Иначе
нВозврат = 0;
КонецЕсли;;
Возврат нВозврат;
КонецФункции
Функция ПересчитатьСумму(Цена, Количество) Экспорт
Возврат Окр(Цена * Количество, 2);
КонецФункции
Функция ПриИзмененииСуммы(Цена, Количество, Сумма) Экспорт
лПриИзмененииСуммыПересчитатьЦену = Константы.ПриИзмененииСуммыПересчитатьЦену.Получить();
Если лПриИзмененииСуммыПересчитатьЦену И (Количество <> 0) Тогда
Цена = Окр(Сумма/Количество, 2);
ИначеЕсли (НЕ лПриИзмененииСуммыПересчитатьЦену) И (Цена <> 0) Тогда
Количество = Сумма/Цена;
КонецЕсли;
масВозврата = Новый Массив;
масВозврата.Добавить(Цена);
масВозврата.Добавить(Количество);
Возврат масВозврата;
КонецФункции
</code>
Данные процедуры вынесены в общий модуль для того, чтобы не повторять их и в документах поступления товаров, и в документах реализации.
Процедуры общего модуля вызываются из форм документов так:
<code>
&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент)
ТекДанные = Элементы.Товары.ТекущиеДанные;
ТекДанные.Цена = УчетТМЦ.ЦенаНоменклатуры(ТекДанные.Номенклатура, Объект.ТипЦенНоменклатуры, Объект.Дата);
ТекДанные.Сумма = УчетТМЦ.ПересчитатьСумму(ТекДанные.Цена, ТекДанные.Количество);
КонецПроцедуры
&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
ТекДанные = Элементы.Товары.ТекущиеДанные;
ТекДанные.Сумма = УчетТМЦ.ПересчитатьСумму(ТекДанные.Цена, ТекДанные.Количество);
КонецПроцедуры
&НаКлиенте
Процедура ТоварыЦенаПриИзменении(Элемент)
ТекДанные = Элементы.Товары.ТекущиеДанные;
ТекДанные.Сумма = УчетТМЦ.ПересчитатьСумму(ТекДанные.Цена, ТекДанные.Количество);
КонецПроцедуры
&НаКлиенте
Процедура ТоварыСуммаПриИзменении(Элемент)
ТекДанные = Элементы.Товары.ТекущиеДанные;
НовыеДанные = УчетТМЦ.ПриИзмененииСуммы(ТекДанные.Цена, ТекДанные.Количество, ТекДанные.Сумма);
ТекДанные.Цена = НовыеДанные[0];
ТекДанные.Количество = НовыеДанные[1];
КонецПроцедуры
</code>
Кроме того, в документе «РеализацияТоваров» создан фильтр по контактным лицам контрагента:
<code>
&НаКлиенте
Процедура КонтактноеЛицоНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ДанныеВыбора = Новый СписокЗначений;
ФормаКонтактов = ПолучитьФорму(“Документ.КонтактСКонтрагентом.Форма.ФормаДокумента”);
ДанныеВыбора.ЗагрузитьЗначения(ФормаКонтактов.КонтактныеЛицаКонтрагента(Объект.Контрагент));
КонецПроцедуры
</code>
Создан регистр накопления «ОстаткиТоваров».
Вид регистра – Остатки.
Измерения – «Номенклатура», «Качество»
Ресурсы – «Количество»
Реквизиты – «ЕдИзм»
В документе «ПоступлениеТоваров», в модуле объекта, для движения регистра «ОстаткиТоваров» в модуле объекта данного документа прописан код:
<code>
Процедура ОбработкаПроведения(Отказ, Режим)
Движения.ОстаткиТоваров.Записывать = Истина;
Для Каждого ТекСтрокаТовары Из Товары Цикл
Движение = Движения.ОстаткиТоваров.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Номенклатура = ТекСтрокаТовары.Номенклатура;
Движение.Качество = ТекСтрокаТовары.СтепеньБрака;
Движение.Количество = ТекСтрокаТовары.Количество;
Движение.ЕдИзм = ТекСтрокаТовары.ЕдИзм;
КонецЦикла;
КонецПроцедуры
</code>
Создан регистр накопления «Покупки».
Вид регистра – Обороты.
Измерения – «Контрагент», «Номенклатура»
Ресурсы – «Количество», «Стоимость»
Реквизиты – «ЕдИзм»
Для создания движений по регистру «Покупки» процедура «ОбработкаПроведения» из модуля объекта документа «ПоступлениеТовара» переписана соответствующим образом.
Для выполнения условия задания «Необходимо реализовать проверку, которая будет запрещать изменять базовую единицу измерения для номенклатуры, если по ней уже есть движения в регистрах» в процедуре «ПередЗаписью» модуля объекта справочника «Номенклатура» сделана соответствующая проверка:
<code>
Если (НЕ ЭтоНовый()) И (БазоваяЕдиницаИзмерения <> Ссылка.БазоваяЕдиницаИзмерения) Тогда
Если БылиДвиженияПоРегистрам(Ссылка) Тогда
Отказ = Истина;
Сообщить(“По данной номенклатуре уже были движения в регистрах! Изменения базовой единицы измерения невозможны!”);
Возврат;
КонецЕсли;
ОчиститьЕдиницыИзмеренияНоменклатуры(Ссылка);
КонецЕсли;
</code>
Сама функция «БылиДвиженияПоРегистрам» выглядит следующим образом:
<code>
Функция БылиДвиженияПоРегистрам(Номенклатура)
Запрос = Новый Запрос;
Запрос.Текст = ”
|ВЫБРАТЬ
| ОстаткиТоваров.Период
|ИЗ
| РегистрНакопления.ОстаткиТоваров КАК ОстаткиТоваров
|ГДЕ
| ОстаткиТоваров.Номенклатура = &Номенклатура
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| Покупки.Период
|ИЗ
| РегистрНакопления.Покупки КАК Покупки
|ГДЕ
| Покупки.Номенклатура = &Номенклатура
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| ЦеныНоменклатуры.Период
|ИЗ
| РегистрСведений.ЦеныНоменклатуры КАК ЦеныНоменклатуры
|ГДЕ
| ЦеныНоменклатуры.Номенклатура = &Номенклатура”;
Запрос.УстановитьПараметр(“Номенклатура”, Номенклатура);
Результат = Запрос.Выполнить();
Возврат НЕ Результат.Пустой();
КонецФункции
</code>
Задание выполнила, извините за опоздание.
1) Привязка менеджеров – РС.МенеджерыКонтрагентов(В пределах дня, независимый), измерение -Контрагент, ресурс-менеджер; 2) подстановка текМенеджера –
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Объект.Менеджер = УстановитьМенеджера();
КонецПроцедуры
&НаСервереБезКонтекста
Функция УстановитьМенеджера()
Возврат Справочники.Пользователи.НайтиПоРеквизиту(“ПользовательИБ”,ПользователиИнформационнойБазы.ТекущийПользователь().УникальныйИдентификатор);
КонецФункции
&НаКлиентеПроцедура ПриОткрытии(Отказ) Объект.Менеджер = УстановитьМенеджера();КонецПроцедуры
&НаСервереБезКонтекстаФункция УстановитьМенеджера() Возврат Справочники.Пользователи.НайтиПоРеквизиту(“ПользовательИБ”,ПользователиИнформационнойБазы.ТекущийПользователь().УникальныйИдентификатор);КонецФункции;
3) Проверка на первый контакт – запрос с отбором по контрагенту получает одну запись, и если не выборка.следующий() тогда запись; 4) созд. Перечисление.ТипыЦен и добавила ТипЦены в РС.Цены.. 5)Вариант пересчета – Константа.Пересчет(Перечисление 2 значения: КолВо и Цена); 6) РН.ОстаткиНоменклатуры(остатки) в БазЕд – в ОбработкеПроведения проверяю ЕдИзм на тип, если не базовая, то колво домножаю на коэффициент; 7) РН.Закупки(обороты) – изм. Контрагент,Номенклатура и ресурсы колво +стоимость; *) проверка баз.ед. через запрос к регистрам накопления; 9) вид документа предполагаю, что тип – стандартный реквизит это одно и тоже.
Задание Выполнено.
Созданы необходимые регистры сведений: МенеджерКонтрагентов, ЦеныОптовые, ЦеныРозничные. Проверка 1 контакта сделана через регистр.
Доработаны док-ты по учету ТМЦ.
Созданы регистры накопления:ОстаткиТоваров,ПоставкаТоваров.
Создан Журнал.
Задание выполнил. Немного с опозданием, вчерашний хоккей отвлек =)
Для хранения менеджеров создал периодический независимый регистр сведений “Менеджеры контрагентов”. Заполняется вручную из формы регистра, поскольку в задании не оговорено иное поведение.
Обработка проведения документа “Событие” с контролем первичности документа и заполнением менеджера контрагента.
Для хранения цен организовал периодический регистр сведений “Цены номенклатуры” с периодичностью “День”. Измерения – “Номенклатура” и “Тип цены”. “Типы цен” – новый справочник.
Доработал “юзабилити” документов согласно заданию. Пересчет строк при изменении реквизитов вынес в общий клиентский модуль.
Создал регистр накопления “Остатки товаров”, обеспечил его заполнение документом “Поступление товаров” при помощи конструктора движений. Также добавил оборотный регистр “Закупки” и обеспечил его заполнения в модуле проведения документа “Поступление товаров”.
Проверку на запрет изменения базовой единицы измерения организовал в модуле объекта справочника “Номенклатура” в процедуре “ПередЗаписью”.
Задание выполнил. Сложностей не возникло.
Привязку менеджеров к клиентам сделал через реквизит “ОсновнойМенеджер” в справочнике “Контрагенты”. Создал регистр сведений “МенеджерыИстория”, в который записывал все изменения менеджеров у контрагента, причем если измения происходят в один день, то последняя запись просто замещается. В документе “КонтактСКлиентом” создал реквизит “Менеджер” с автоматическим заполнением при запуске текущим пользователем. Проверку на первый контакт реализовал через регистр “МенеджерыИстория”, подсчитывал количество строк в результате:
<code>
Отбор=Новый Структура(“Контрагент”, Контрагент);
КоличествоСтрок=РегистрыСведений.КонтактыСКлиентами.СрезПоследних(Дата, Отбор).Количество();
</code>
Если количество строк в результате меньше единицы, устанавливал основного менеджера в справочнике и делал запись в регистр сведений “МенеджерыИстория”.
Создал справочник “ТипыЦен” и регистр сведений “ЦеныНоменклатуры” для хранения цен товаров в разрезе разных типов цен.
Во все документы ТМЦ добавил реквизит для выбора типов цен. Создал общий серверный модуль “ОбработкаТабличныхЧастей” где создал экспортную функцию “УстановкаЦен”, которая возвращает цену номенклатуры по заданному типу цен в табличной части документов. Пересчет по цене и количеству реализовал в каждом модуле отдельно в процедурах при изменении, чтобы в лишний раз не вызывать сервер. Создал константу ВариантПересчета(где храниться перечисление ВариантыПересчета). В общем модуле создал процедуру “ПересчитатьЦенуКоличество”, где в зависимости от константы идет пересчет цены или количества в текущей строке. Отображение итоговой суммы сделала через стандартные свойства отображения суммы табличной части. Установил проверку заполнения на все необходимые поля. В документе реализация сделал связь параметров для контактных лиц с контрагентами по владельцу.
Создал регистр накопления “ОстаткиТоваров”(вид регистра – Остатки) для хранения остатков товаров. Создал движения у документов закупки в этот регистр.
Создал регистр накоплений “Закупки”(вид регистра – Обороты) для хранения информации по закупкам у поставщиков. Для документа “АвансовыйОтчет” сделал дополнительное условие, чтобы при проведении в поле поставщик подставлялся контрагент с наименованием сотрудника(если такого нет, то чтобы он создавался в справочнике контрагенты в папке сотрудники).
Проверку изменения базовой единицы измерения реализовал через запрос к регистру “ОстаткиТоваров”. Если есть хоть одна запись, то выходит ошибка, наименование меняется к исходному и запись произвести нельзя.
Создал журнал “ДокументыЗакупки” в котором отразил всю необходимую информацию по документам закупки. Сумму документов закупки реализовал через дополнительный реквизит “СуммаДокумента” в каждом документе.
Задание выполнил.
Оговорюсь сразу, что во всех документах где возможно взаимодействие с Юр лицом или Физ. лицом создал реквизит “ОбращениеФизЛица”” с типом булево. Присваивается истина автоматически если выбранный контрагент – предопределенный элемент “Физ. лицо”. При этом при выборе контактного лица открывается форма выбора справочника “КонтактныеЛицаКонтрагентов” либо “КонтактныеЛица” (если физ. лицо).
1) Для связи менеджеров с клиентами создал периодический независимый регистр сведений. Периодичность = В пределах дня
Измерение – Контрагент, Ресурс – Менеджер
2) В документе “Событие”
Для подстановки менеджера по умолчанию в модуле формы прописал
<code>
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Объект.Ссылка.Пустая() И НЕ ЗначениеЗаполнено(Объект.Менеджер) Тогда
//Менеджер = глТекущийПользователь;
Объект.Менеджер = ОбщиеФункцииСервер.СинхронизацияПользователей(Неопределено);
КонецЕсли;
КонецПроцедуры
&НаСервереПроцедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) Если Объект.Ссылка.Пустая() И НЕ ЗначениеЗаполнено(Объект.Менеджер) Тогда //Менеджер = глТекущийПользователь; Объект.Менеджер = ОбщиеФункцииСервер.СинхронизацияПользователей(Неопределено); КонецЕсли; КонецПроцедуры
</code>
Проверку на первый контакт, как было сказано в задании, выполняю в модуле документа
<code>
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Клиент = ?(ОбращениеФизЛица, КонтактноеЛицо, Контрагент);
Отбор = Новый Структура(“Клиент”, Клиент);
Запись = РегистрыСведений.МененджерыКлиентов.ПолучитьПоследнее(, Отбор);
Если ЗначениеЗаполнено(Запись.Менеджер) Тогда
Возврат;
КонецЕсли;
МенеджерЗаписи = РегистрыСведений.МененджерыКлиентов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Активность = Истина;
МенеджерЗаписи.Период = Дата;
МенеджерЗаписи.Клиент = Клиент;
МенеджерЗаписи.Менеджер = Менеджер;
МенеджерЗаписи.Записать();
КонецПроцедуры
</code>
3) “Прайс листы” реализовал в виде справочника “ТипыЦен”. Для хранения цен добавил периодический регистр сведений “ЦеныНоменклатуры”.
Периодичность – В пределах дня
Измерения – ТипЦен, Номенклатура
Ресурс – Цена.
Добавил документ, который регистрирует изменение цен “УстановкаЦенНоменклатуры”.
Модуль документа “УстановкаЦенНоменклатуры”
<code>
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Движения.ЦеныНоменклатуры.Записывать = Истина;
Для Каждого ТекСтрока Из Товары Цикл
НовоеДвижение = Движения.ЦеныНоменклатуры.Добавить();
НовоеДвижение.Активность = Истина;
НовоеДвижение.Период = Дата;
НовоеДвижение.ТипЦен = ТипЦен;
НовоеДвижение.Номенклатура = ТекСтрока.Номенклатура;
НовоеДвижение.Цена = ТекСтрока.Цена;
НовоеДвижение.Ответственный = Ответственный;
КонецЦикла;
КонецПроцедуры
</code>
4) Во все документы по учету ТМЦ добавил реквизит “ТипЦен”.
Модуль формы документа “ПоступлениеТоваровУслуг”
<code>
&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент)
ТекДанные = Элементы.Товары.ТекущиеДанные;
СтруктураСтроки = ОбщиеФункцииКлиент.ПреобразоватьСтрокуВСтруктуру(ТекДанные, Элементы.Товары.ПодчиненныеЭлементы);
ПриИзмененииНоменклатуры(СтруктураСтроки);
ЗаполнитьЗначенияСвойств(ТекДанные, СтруктураСтроки);
ПересчитатьСтрокуТЧ(ТекДанные);
КонецПроцедуры
&НаСервере
Процедура ПриИзмененииНоменклатуры(СтрокаТабЧасти)
Если НЕ ЗначениеЗаполнено(СтрокаТабЧасти) Тогда
Возврат;
КонецЕсли;
СтрокаТабЧасти.ЕдиницаИзмерения = Справочники.ЕдиницыИзмеренияНоменклатуры.ПодобратьЕдиницуИзмеренияДляНоменклатурыПоКлассификатору(СтрокаТабЧасти.Номенклатура, СтрокаТабЧасти.Номенклатура.БазоваяЕдиница);
СтрокаТабЧасти.Коэффициент = СтрокаТабЧасти.ЕдиницаИзмерения.К;
СтрокаТабЧасти.Цена = ОбщиеФункцииСервер.ПолучитьЦенуНоменклатуры(СтрокаТабЧасти.Номенклатура, Объект.ТипЦен, ?(ЗначениеЗаполнено(Объект.Дата), Объект.Дата, ТекущаяДата()))*СтрокаТабЧасти.Коэффициент;
КонецПроцедуры
//ДЗ 8
&НаКлиенте
Процедура ТипЦенПриИзменении(Элемент)
Для Каждого ТекСтрока Из Объект.Товары Цикл
ТекСтрока.Цена = ОбщиеФункцииСервер.ПолучитьЦенуНоменклатуры(ТекСтрока.Номенклатура, Объект.ТипЦен, ?(ЗначениеЗаполнено(Объект.Дата), Объект.Дата, ТекущаяДата()))*ТекСтрока.Коэффициент;
ПересчитатьСтрокуТЧ(ТекСтрока);
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура КоличествоПриИзменении(Элемент)
ПересчитатьСтрокуТЧ(Элементы.Товары.ТекущиеДанные);
КонецПроцедуры
&НаКлиенте
Процедура ЦенаПриИзменении(Элемент)
ПересчитатьСтрокуТЧ(Элементы.Товары.ТекущиеДанные);
КонецПроцедуры
&НаКлиенте
Процедура СуммаПриИзменении(Элемент)
ТекДанные = Элементы.Товары.ТекущиеДанные;
СтруктураСтроки = ОбщиеФункцииКлиент.ПреобразоватьСтрокуВСтруктуру(ТекДанные, Элементы.Товары.ПодчиненныеЭлементы);
ЗаполнитьЗначенияСвойств(СтруктураСтроки, ТекДанные);
ПриИзмененииСуммыВтаблицеТовары(СтруктураСтроки);
ЗаполнитьЗначенияСвойств(ТекДанные, СтруктураСтроки);
КонецПроцедуры
&НаКлиенте
Процедура ПересчитатьСтрокуТЧ(СтрокаТабЧасти)
СтрокаТабЧасти.Сумма = СтрокаТабЧасти.Цена*СтрокаТабЧасти.Количество*СтрокаТабЧасти.Коэффициент;
КонецПроцедуры
&НаСервере
Процедура ПриИзмененииСуммыВтаблицеТовары(СтрокаТабЧасти)
Если НЕ ЗначениеЗаполнено(СтрокаТабЧасти) Тогда
Возврат;
КонецЕсли;
Если Константы.ПересчитыватьЦенуПриИзмененииСуммыВДокументах.Получить() Тогда
СтрокаТабЧасти.Цена = СтрокаТабЧасти.Сумма/СтрокаТабЧасти.Количество;
Иначе
СтрокаТабЧасти.Количество = СтрокаТабЧасти.Сумма/СтрокаТабЧасти.Цена;
КонецЕсли;
КонецПроцедуры
</code>
Сумму документа отобразил на форме, как было показано в одном из уроков, вытащив итоговую сумму по табличной части “Товары”.
В остальных документах код аналогичен.
5) Для хранения остатков создал регистр “ТоварыНаСкладах”.
Измерения – номенклатура, Склад (создал отдельный справочник и добавил реквизит в документы на всякий случай :0)), Качество.
Ресурс – Количество.
Регистраторы – Поступление товаров и услуг, Авансовый отчет.
Модуль документа “ПоступлениеТоваровУслуг”
<code>
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Движения.ТоварыНаСкладах.Записывать = Истина;
Движения.Закупки.Записывать = Истина;
Для Каждого ТекСтрока Из Товары Цикл
//ТоварыНаСкладах
НовоеДвижение = Движения.ТоварыНаСкладах.ДобавитьПриход();
НовоеДвижение.Активность = Истина;
НовоеДвижение.Период = Дата;
НовоеДвижение.Номенклатура = ТекСтрока.Номенклатура;
НовоеДвижение.Склад = Склад;
НовоеДвижение.Качество = ТекСтрока.Качество;
НовоеДвижение.Количество = ТекСтрока.Количество;
//Закупки
НовоеДвижение = Движения.Закупки.Добавить();
НовоеДвижение.Активность = Истина;
НовоеДвижение.Период = Дата;
НовоеДвижение.Контрагент = Контрагент;
НовоеДвижение.Номенклатура = ТекСтрока.Номенклатура;
НовоеДвижение.Количество = ТекСтрока.Количество;
НовоеДвижение.Стоимость = ТекСтрока.Сумма;
КонецЦикла;
КонецПроцедуры
</code>
В авансовом отчете аналогично.
6) Создал оборотный регистр накопления “Закупки”
Измерения – Контрагент(не обязательный), Номенклатура
Ресурс – Количество, Стоимость
7) Очень хочется спать поэтому запрет на изменение базовой единицы сделал просто
Модуль формы справочника “Номенклатура”
<code>
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ОтборПоВладельцу = Этаформа.ЕдиницыИзмерения.Отбор.Элементы.Добавить(Тип(“ЭлементОтбораКомпоновкиДанных”));
ОтборПоВладельцу.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(“Владелец”);
ОтборПоВладельцу.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ОтборПоВладельцу.ПравоеЗначение = Объект.Ссылка;
Элементы.БазоваяЕдиница.ТолькоПросмотр = НЕ ПроверитьВозможностьРедактированияБазовойЕдиницы(Объект.Ссылка);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПроверитьВозможностьРедактированияБазовойЕдиницы(Номенклатура)
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ ПЕРВЫЕ 1
| Закупки.Количество
|ИЗ
| РегистрНакопления.Закупки КАК Закупки
|ГДЕ
| Закупки.Номенклатура = &Номенклатура”;
Запрос.УстановитьПараметр(“Номенклатура”, Номенклатура);
Выборка = Запрос.Выполнить().Выбрать();
Возврат Выборка.Следующий();
КонецФункции
</code>
8) Журнал сделал. Одна Графа Контрагент/Подотчетное лицо, другая – Сумма документа.
Пришлось добавить реквизит в документы закупки и написать процедуру расчета, т.к. вытащенное на форму поле итогов по таблице Товары через ссылку при проверке отказывалось что либо показывать.
Вопросы:
1) В пункте 2 видна закомментированная строка с обращением к переменной “глТекущийПользователь”.
Для выполнения дз была взята ваша конфигурация с определением текущего пользователя. В модуле управляемого приложения глОбеды и глТекущий пользователь обе экспортные. глОбеды видит, пользователя нет. В чем причина?
2) В пункте 4 использую функцию
ОбщиеФункцииКлиент.ПреобразоватьСтрокуВСтруктуру
которая создает структуру с ключами = именам полей и соответственно значениями колонок. Чтобы затем эту структуру передать на сервер. Т.к. просто так текущие данные передать не удается.
Есть ли более правильное решение?
3) Можно ли в следующий раз писать просто “Задание выполнил”, если проблем не возникло? :0) Уж больно долго все это описывать.
1.
>глОбеды видит, пользователя нет. В чем причина?
Полагаю, что слово “видит” относится к контекстной подсказке. Но она также видит и глТекущийПользователь.
Другое дело, что синтакс-контроль этот момент не пропускает. Почему? Переменные модуля управляемого приложения – клиентские, а вы пытаетесь к ним обратиться в серверном методе. Такого система не допускает.
2. Ваше решение правильное.
3. Комментарий в два слова не приветствуется. Можно коротко описать ход решения, в 3-4х предложениях, без программного кода.
А также отдельно описать возникшие вопросы.
Спасибо.
Выполнил задание. С регистрами проблем не возникло. Обращался к регистрам где это нежно не используя запросы.
ДЗ 8
1. Были созданы регистры накопления ОстаткиТовара(регистр остатки) и Закупки( регистр обороты). Проведение документов по регистрам было создано с помощью конструктора движения с учетом того, что мы можем указывать единицу измерения отличную от базовой.
2.Для работы с прайсом был создан справочник ТипыЦен и регистрСведений «ЦеныНомеклатуры» Измерения: ТипЦен(Справочник), Номеклатура(справочник). Ресурсы: Цена
3.Автоматическая обработка Табличной части
Процедура ТоварНоменклатураПриИзменении(Элемент)
СтрокаТабличнойЧасти = Элементы.Товары.ТекущиеДанные;
СтруктураДанные = Новый Структура();
СтруктураДанные.Вставить("Номенклатура", СтрокаТабличнойЧасти.Номенклатура);
СтруктураДанные.Вставить("ДатаДок",Объект.Дата);
СтруктураДанные.Вставить("ТипЦен", Объект.ТипЦен);
СтруктураДанные = ОбработкаТабличныхЧастей.ПолучитьДанныеНоменклатураПриИзменении(СтруктураДанные);
СтрокаТабличнойЧасти.ЕдиницаИзмерения = СтруктураДанные.ЕдиницаИзмерения;
СтрокаТабличнойЧасти.Цена = СтруктураДанные.цена;
СтрокаТабличнойЧасти.Коэффициент=СтруктураДанные.Коэффициент;
СтрокаТабличнойЧасти.Сумма = 0;
КонецПроцедуры
&НаКлиенте
Процедура ТоварКоличествоПриИзменении(Элемент)
СтрокаТабличнойЧасти=элементы.Товары.ТекущиеДанные;
СтрокаТабличнойЧасти.сумма=ОбработкаТабличнойЧастиКлиент.РассчитатьСуммуТабличнойЧасти(СтрокаТабличнойЧасти.количество,СтрокаТабличнойЧасти.Цена);
КонецПроцедуры
&НаКлиенте
Процедура ТоварЦенаПриИзменении(Элемент)
СТЧ=элементы.Товары.ТекущиеДанные;
СТЧ.сумма=ОбработкаТабличнойЧастиКлиент.РассчитатьСуммуТабличнойЧасти(СТЧ.количество,СТЧ.Цена);
КонецПроцедуры
&НаКлиенте
Процедура ТоварСуммаПриИзменении(Элемент)
СТЧ=элементы.Товары.ТекущиеДанные;
Структура=Новый Структура("Цена,Количество,Сумма",СТЧ.цена,СТЧ.Количество,СТЧ.Сумма);
структура=ОбработкаТабличныхЧастей.РассчитатьЦенуКолвоТабличнойЧасти(Структура);
СТЧ.Количество=Структура.количество;
СТЧ.Цена=Структура.цена;
КонецПроцедуры
ОбщийМодуль: ОбработкаТабличныхЧастей
Отбор= Новый Структура("ТипЦен,Номеклатура",ТипЦен,номенклатура);
возврат РегистрыСведений.ЦеныНоменклатуры.ПолучитьПоследнее(Дата,Отбор).цена;
КонецФункции
функция ПолучитьДанныеНоменклатураПриИзменении(СтруктураДанные) экспорт
СтруктураДанные.Вставить("ЕдиницаИзмерения", ПолучитьЕдиницуИзмерения(СтруктураДанные.Номенклатура));
СтруктураДанные.Вставить("Коэффициент",1);
СтруктураДанные.Вставить("Цена", ПолучитьЦенуНомеклатуры(СтруктураДанные.Номенклатура,СтруктураДанные.ТипЦен,СтруктураДанные.ДатаДок));
возврат СтруктураДанные
КонецФункции
функция РассчитатьЦенуКолвоТабличнойЧасти(Структура) экспорт
если Константы.АлгоритмПересчетаСуммы=ПредопределенноеЗначение("Перечисление.ВариантыПерсчетаСуммы.Количество")тогда
если не структура.цена=0 тогда
структура.вставить("Количество",(структура.Сумма/структура.цена));
конецЕсли;
иначе
Если не структура.Количество=0 тогда
структура.вставить("цена",(структура.Сумма/структура.количество));
конецЕсли;
конецЕсли;
возврат Структура
конецФункции
4. Подбор КонтактногоЛица в документе Реализация
Процедура ПоставщикПриИзменении(Элемент)
объект.КонтактноеЛицо=КонтактноеЛицоПустаяСсылка();
КонецПроцедуры
&НаСервереБезКонтекста
Функция КонтактноеЛицоПустаяСсылка()
возврат Справочники.КонтактныеЛица.ПустаяСсылка()
КонецФункции
&НаКлиенте
Процедура КонтактноеЛицоНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
Структура=Новый Структура("Контрагент",Объект.Поставщик);
ФормаВыбора=ПолучитьФорму("Справочник.КонтактныеЛица.ФормаВыбора",Структура,Элемент);
ФормаВыбора.Открыть();
СтандартнаяОбработка=ложь;
КонецПроцедуры
В формевыбора КонтактныеЛица
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
если параметры.Свойство("контрагент") тогда
Если ЗначениеЗаполнено(Параметры.контрагент) Тогда
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КонтактныеЛица.Ссылка
|ИЗ
| Справочник.КонтактныеЛица КАК КонтактныеЛица
|ГДЕ
| КонтактныеЛица.Ссылка В
| (ВЫБРАТЬ
| КонтрактныеЛицаКонтрагентов.КонтактноеЛицо
| ИЗ
| Справочник.КонтрактныеЛицаКонтрагентов КАК КонтрактныеЛицаКонтрагентов
| ГДЕ
| КонтрактныеЛицаКонтрагентов.Владелец = &Владелец)";
Запрос.УстановитьПараметр("Владелец", Параметры.контрагент);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
отборКонтактныеЛица=список.Отбор;
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Отбор = список.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Отбор.Использование = Истина;
Отбор.ВидСравнения = ВидСравненияКомпоновкиДанных.равно;
Отбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Ссылка");
Отбор.ПравоеЗначение = ВыборкаДетальныеЗаписи.Ссылка;
КонецЦикла;
конецЕсли;
конецЕсли;
КонецПроцедуры
5. Запрет редактирования БазовойЕдиницы в справочнике номеклатура
Процедура БазоваяЕдиницаНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
если ЕстьЛиДвижения() тогда
сообщить("По данной позиции есть движения!");
СтандартнаяОбработка=0;
конецЕсли;
КонецПроцедуры
&НаСервере
Функция ЕстьЛиДвижения()
отбор=Новый Структура("Номенклатура",Объект.Ссылка);
ОстаткиТовара=РегистрыНакопления.ОстаткиТовара;
Оборот=ОстаткиТовара.Выбрать(,,Отбор);
возврат Оборот.Следующий();
конецФункции
Задание выполнила.
Для хранения менеджеров по контрагентам сделала РС “МенеджерыКлиентов”, периодический. Код модуля документа “Контакт”:
<code>
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
Флаг = Ложь;
Менеджер = ОбщиеФункцииСервер.СинхронизацияПользователей(Флаг);
КонецПроцедуры
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
ПоследнийМенеджер = РегистрыСведений.МенеджерыКлиентов.ПолучитьПоследнее(,Новый Структура(“Контрагент”,Контрагент)).Менеджер;
Если ПоследнийМенеджер.Пустая() Тогда
НаборЗаписей = РегистрыСведений.МенеджерыКлиентов.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Контрагент.Значение = Контрагент;
НаборЗаписей.Отбор.Контрагент.Использование = Истина;
НоваяСтрока = НаборЗаписей.Добавить();
НоваяСтрока.Период = Дата;
НоваяСтрока.Контрагент = Контрагент;
НоваяСтрока.Менеджер = Менеджер;
НаборЗаписей.Записать();
КонецЕсли;
КонецПроцедуры</code>
Далее создала справочник “Типы цен”, РС “Типы цен номенклатуры”, периодический.
В форме реализации выполняется пересчет:
<code>
&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ТД.ЕдиницаИзмерения = ЗаполнениеДокументовСервер.ЗаполнитьЕдИзмеренияНаСервере(ТД.Номенклатура);
Отбор = Новый Структура;
Отбор.Вставить(“ТипЦен”,Объект.ТипЦен);
Отбор.Вставить(“Номенклатура”,ТД.Номенклатура);
ТД.Цена = ЗаполнениеДокументовСервер.ПолучитьЦенуНоменклатуры(Объект.Дата, Отбор);
СтруктураСтроки = Новый Структура(“Сумма,Цена,Количество”,ТД.Сумма,ТД.Цена,ТД.Количество);
ЗаполнениеДокументовСервер.ПересчитатьСтроку(СтруктураСтроки);
ЗаполнитьЗначенияСвойств(ТД,СтруктураСтроки);
//ТД.Сумма = ПересчитатьСтроку(ТД.Количество,ТД.Цена);
КонецПроцедуры
&НаКлиенте
Процедура ТоварыСуммаПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
СтруктураСтроки = Новый Структура(“Сумма,Цена,Количество”,ТД.Сумма,ТД.Цена,ТД.Количество);
ЗаполнениеДокументовСервер.ПересчитатьСтроку(СтруктураСтроки,”ЦенаКоличество”);
ЗаполнитьЗначенияСвойств(ТД,СтруктураСтроки);
КонецПроцедуры
&НаКлиенте
Процедура ТоварыЦенаПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
СтруктураСтроки = Новый Структура(“Сумма,Цена,Количество”,ТД.Сумма,ТД.Цена,ТД.Количество);
ЗаполнениеДокументовСервер.ПересчитатьСтроку(СтруктураСтроки,”Сумма”);
ЗаполнитьЗначенияСвойств(ТД,СтруктураСтроки);
КонецПроцедуры
&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
СтруктураСтроки = Новый Структура(“Сумма,Цена,Количество”,ТД.Сумма,ТД.Цена,ТД.Количество);
ЗаполнениеДокументовСервер.ПересчитатьСтроку(СтруктураСтроки,”Сумма”);
ЗаполнитьЗначенияСвойств(ТД,СтруктураСтроки);
КонецПроцедуры
&НаКлиенте
Процедура ТипЦенПриИзменении(Элемент)
Режим = РежимДиалогаВопрос.ДаНет;
Ответ = Вопрос(“Перевыбран тип цен. Пересчитать таблицу товаров?”, Режим, 0);
Если Ответ = КодВозвратаДиалога.Нет Тогда
Возврат;
Иначе
ПересчитатьЦены();
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПересчитатьЦены() Экспорт
Для каждого СтрокаТЗ Из Объект.Товары Цикл
СтрокаТЗ.Цена = ЗаполнениеДокументовСервер.ПолучитьЦенуНоменклатуры(Объект.Дата,Новый Структура(“Номенклатура,ТипЦен”,СтрокаТЗ.Номенклатура,Объект.ТипЦен));
ЗаполнениеДокументовСервер.ПересчитатьСтроку(СтрокаТЗ);
КонецЦикла;
КонецПроцедуры // ПересчитатьСервер
</code>
процедуры общего модуля:
<code>Функция ПолучитьЦенуНоменклатуры(Дата, Отбор)Экспорт
Возврат РегистрыСведений.ЦеныНоменклатуры.ПолучитьПоследнее(Дата, Отбор).Цена;
КонецФункции // ПолучитьЦенуНоменклатуры(Дата, Отбор)()
Процедура ПересчитатьСтроку(ТД,Параметр = “Сумма”) Экспорт
Если Параметр = “Сумма” Тогда
ТД.Сумма = ТД.Количество*ТД.Цена;
ИначеЕсли Параметр = “ЦенаКоличество” Тогда
Пересчет = Константы.ПересчитыватьКоличествоАНеЦену.Получить();
ТД.Цена = ?(Пересчет, ТД.Цена, ?(ТД.Количество = 0,0,ТД.Сумма/ТД.Количество));
ТД.Количество = ?(Не Пересчет, ТД.Количество, ?(ТД.Цена = 0,0,ТД.Сумма/ТД.Цена));
КонецЕсли;
КонецПроцедуры // ПересчитатьСтроку()</code>
Итоговую сумму отобразила в подвале табличной части, проверку на заполнение реквизитов в тч делаю в модуле документа:
<code>
Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
ПроверяемыеРеквизиты.Добавить(“Товары.Номенклатура”);
ПроверяемыеРеквизиты.Добавить(“Товары.Количество”);
ПроверяемыеРеквизиты.Добавить(“Товары.ЕдиницаИзмерения”);
КонецПроцедуры
</code>
Регистры накопления “Остатки номенклатуры” и “Закупки” создала, первый регистр остатков, второй – оборотный.
Проверка в справочнике “Номенклатура”:
<code>Процедура ПередЗаписью(Отказ)
ЭтоНовый = ЭтоНовый();
Если Не БазоваяЕдиница = Ссылка.БазоваяЕдиница Тогда
// проверяем есть ли движения
Движения = РегистрыНакопления.ОстаткиТоваров.Выбрать(,,Новый Структура(“Номенклатура”,Ссылка));
Если Движения.Следующий() Тогда
Сообщить(“Номенклатура участвует в товародвижении. Базовую единицу изменять нельзя”);
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
</code>
Задание выполнил.
Отслеживание первого контакта с контрагентом и присвоения ему менеджера производится
в процедуре ОбработкаПроведения документа КонтактСКлиентом:
<code>
Отбор = Новый Структура(“Клиент”, Контрагент);
Если РегистрыСведений.МенеджерКлиентов.Получить(Отбор).Менеджер.Пустая() Тогда
Набор = РегистрыСведений.МенеджерКлиентов.СоздатьНаборЗаписей();
Набор.Отбор.Клиент.Установить(Контрагент);
Запись = Набор.Добавить();
Запись.Клиент = Контрагент;
Запись.Менеджер = Менеджер;
Набор.Записать();
КонецЕсли;
</code>
Автоматическая подстановка цен при выборе номенклатуры реализована с помощью вызова функции следующего содержания:
<code>
&НаСервереБезКонтекста
Функция ПолучитьЦену(Ссылка, ТипЦены, Дата)
Отбор = Новый Структура(“Номенклатура, ТипЦеныНоменклатуры”, Ссылка, ТипЦены) ;
Возврат РегистрыСведений.ЦеныТоваров.ПолучитьПоследнее(Дата, Отбор).Цена;
КонецФункции
</code>
из обработчика события ТоварыНоменклатураПриИзменении форм документов учета.
Проверка наличия движения в регистрах с целью запрета смены базовой единицы измерения
по данной номенклатуре размещена в модуле объекта справочника Номенклатура в обработчике
события ПередЗаписью. Для работы данного кода включил индексирование по измерению Номенклатура
во всех регистрах где оно присутствует.
</code>
СтарыйГУИД = БазоваяЕдиница.УникальныйИдентификатор();
НовыйГУИД = Ссылка.БазоваяЕдиница.УникальныйИдентификатор();
Если Не ЭтоНовый И СтарыйГУИД <> НовыйГУИД Тогда
Отбор = Новый Структура(“Номенклатура”,Ссылка);
Если РегистрыНакопления.ЗакупкиОтПоставщиков.Выбрать(,,Отбор).Следующий()
ИЛИ РегистрыНакопления.ОстаткиТоваров.Выбрать(,,Отбор).Следующий()
ИЛИ РегистрыСведений.ЦеныТоваров.Выбрать(,,Отбор).Следующий() тогда
Сообщить(“Существуют движения по регистрам. Смена Базовой Единицы Измерения запрещена.”);
Отказ = Истина;
КонецЕсли;
КонецЕсли;
</code>
Для автоматическрго заполнения реквизитов ВидДокумента и СуммаДокумента в модули объекта
документов закупки добавлен следующий код:
<code>
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
ВидДокумента = ЭтотОбъект.Метаданные().Синоним;
СуммаДокумента = Товары.Итог(“Сумма”);
КонецПроцедуры
</code>
Доработал процедуру ЗаполнитьПоКонтрагенту общего модуля для заполнения добавленных реквизитов в документах товародвижения.
Связка менеджеров и контрагентов реализована через независимый РС.МенеджерыКонтрагентов. Регистр заполняется вручную и при проведении документа Контакты. Создан независимый РС.ЦеныНоменклатуры. Реализованы авторасчеты суммы, цены, количества (в том числе исходя из значения константы). Созданы РН.ОстаткиНоменклатуры (остатки) и РН.Закупки (обороты). Движения документов в регистр производятся, количество пересчитывается к базовой единице. В документах добавлен реквизит Сумма – общая сумма документа.
Задание выполнил.
Создал регистры сведений МенеджерыКонтрагентов (Измер Контрагентб ресурс Менеджеры) и ПрайсыПоВидам (измер Номенклатураи видПрайса Ресурс цена)
В документе КонтактыСКлиентами реквизит Менеджер
Модуль документа
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
// Вставить содержимое обработчика.
Пользователь = ПользователиИнформационнойБазы.ТекущийПользователь();
Менеджер = Справочники.Пользователи.НайтиПоНаименованию(Пользователь);
КонецПроцедуры
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ ПЕРВЫЕ 1
| МенеджерКонтрагента.Менеджеры.Ссылка
|ИЗ
| РегистрСведений.МенеджерыКонтрагентов КАК МенеджерКонтрагента
|ГДЕ
| МенеджерКонтрагента.Контрагент = &Контрагент”;
Запрос.УстановитьПараметр(“Контрагент”, Контрагент);
Резуль=Запрос.Выполнить();
Выб=Резуль.Выбрать();
Если ( Резуль.Пустой()) Тогда
Запись=РегистрыСведений.МенеджерыКонтрагентов.СоздатьМенеджерЗаписи();
Запись.Период=Дата;
Запись.Контрагент=Контрагент;
Запись.Менеджеры=Менеджер;
Запись.Записать();
КонецЕсли;
КонецПроцедуры
2. Справочник ВидыЦен
Константы ВариантыПересчета типа Перечисления ВариантПересчета Цена и количество
Общие модуль сервера функции
Функция ПолучитьЦену(Товар, ТипЦен1) Экспорт
Отбор = Новый Структура(“Номенклатура, ВидПрайса”,Товар, ТипЦен1.ТипЦен );
Цена =РегистрыСведений.ПрайсыПоВидам.ПолучитьПоследнее( ТипЦен1.Дата, Отбор).Цена;
Возврат Цена;
КонецФункции // ПолучитьЦену()
Функция Пересчет(Цена, Сумма, Количество) Экспорт
Результат = Новый Структура;
Если Константы.ВариантПересчета.Получить()=Перечисления.ВариантПересчета.Количество Тогда
Количество = Сумма / Цена;
Иначе
Цена = Сумма / Количество;
КонецЕсли;
Результат.Вставить(“Цена”,Цена);
Результат.Вставить(“Сумма”,Сумма);
Результат.Вставить(“Количество”,Количество);
Возврат Результат;
КонецФункции // Пересчет()
Документ Пост товара и авансовый отчет добавил реквизит Суммадок
Модуль формы пост товара
&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ТД.ЕдиницаИзмерения = ПолучитьЕдиницуИзмерения(ТД.Номенклатура);
СтруктураЦены = Новый структура;
СтруктураЦены.Вставить(“Дата”,Объект.Дата);
СтруктураЦены.Вставить(“ТипЦен”,Объект.ТипЦен);
ТД.Цена = ОбщиеФункцииСервер.ПолучитьЦену(ТД.Номенклатура,СтруктураЦены);
ТД.Сумма = ТД.Цена*ТД.Количество;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьЕдиницуИзмерения(Товар)
//{{КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА
// Данный фрагмент построен конструктором.
// При повторном использовании конструктора, внесенные вручную изменения будут утеряны!!!
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| ЕдиницыИзмеренияНоменклатуры.Ссылка
|ИЗ
| Справочник.ЕдиницыИзмеренияНоменклатуры КАК ЕдиницыИзмеренияНоменклатуры
|ГДЕ
| ЕдиницыИзмеренияНоменклатуры.Владелец = &Товар
| И ЕдиницыИзмеренияНоменклатуры.ЕдиницаПоКлассификатору = &ЕдиницаПоКлассификатору
| И (НЕ ЕдиницыИзмеренияНоменклатуры.ПометкаУдаления)”;
Запрос.УстановитьПараметр(“ЕдиницаПоКлассификатору”, Товар.БазоваяЕдиница);
Запрос.УстановитьПараметр(“Товар”, Товар);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
Возврат ВыборкаДетальныеЗаписи.Ссылка;
Иначе
Возврат Справочники.ЕдиницыИзмеренияНоменклатуры.ПустаяСсылка();
КонецЕсли;
//}}КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА
КонецФункции // ПолучитьЕдиницуИзмерения()
&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ТД.Сумма = ТД.Цена*ТД.Количество;
КонецПроцедуры
&НаКлиенте
Процедура ТоварыЦенаПриИзменении(Элемент)
// Вставить содержимое обработчика.
ТД = Элементы.Товары.ТекущиеДанные;
ТД.Сумма = ТД.Цена*ТД.Количество;
КонецПроцедуры
&НаКлиенте
Процедура ТоварыСуммаПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ТД.Количество=ОбщиеФункцииСервер.Пересчет(ТД.Цена, ТД.Сумма, ТД.Количество).Количество;
Тд.Цена=ОбщиеФункцииСервер.Пересчет(ТД.Цена, ТД.Сумма, ТД.Количество).Цена;
КонецПроцедуры
модуль обьекта
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
Если ТипЗнч(ДанныеЗаполнения) = Тип(“СправочникСсылка.Контрагенты”) Тогда
// Заполнение шапки
ЗаполнениеДокументовСервер.ЗаполнитьПоКонтрагенту(ДанныеЗаполнения, ЭтотОбъект);
КонецЕсли;
КонецПроцедуры
Процедура ОбработкаПроведения(Отказ, Режим)
//{{__КОНСТРУКТОР_ДВИЖЕНИЙ_РЕГИСТРОВ
// Данный фрагмент построен конструктором.
// При повторном использовании конструктора, внесенные вручную изменения будут утеряны!!!
Движения.ОстаткиТоваров.Записывать = Истина;
Для Каждого ТекСтрокаТовары Из Товары Цикл
// регистр ОстаткиТоваров Приход
Движение = Движения.ОстаткиТоваров.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Номенклатура = ТекСтрокаТовары.Номенклатура;
Движение.Качество = ТекСтрокаТовары.Качество;
Движение.Количество = ТекСтрокаТовары.Количество*ТекСтрокаТовары.ЕдиницаИзмерения.К;
КонецЦикла;
Движения.Закупки.Записывать = Истина;
Для Каждого ТекСтрокаТовары Из Товары Цикл
// регистр Закупки
Движение = Движения.Закупки.Добавить();
Движение.Период = Дата;
Движение.Поставщик = Контрагент;
Движение.Товары = ТекСтрокаТовары.Номенклатура;
Движение.Количество = ТекСтрокаТовары.Количество;
Движение.Стоимость = ТекСтрокаТовары.Сумма;
КонецЦикла;
//}}__КОНСТРУКТОР_ДВИЖЕНИЙ_РЕГИСТРОВ
КонецПроцедуры
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
СуммаДок=Товары.Итог(“Сумма”);
КонецПроцедуры
Документ авансовый отчет
модуль формы
&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ТД.ЕдиницаИзмерения = ПолучитьЕдиницуИзмерения(ТД.Номенклатура);
СтруктураЦены = Новый структура;
СтруктураЦены.Вставить(“Дата”,Объект.Дата);
СтруктураЦены.Вставить(“ТипЦен”,Объект.ТипЦен);
ТД.Цена = ОбщиеФункцииСервер.ПолучитьЦену(ТД.Номенклатура,СтруктураЦены);
ТД.Сумма = ТД.Цена*ТД.Количество;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьЕдиницуИзмерения(Товар)
//{{КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА
// Данный фрагмент построен конструктором.
// При повторном использовании конструктора, внесенные вручную изменения будут утеряны!!!
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| ЕдиницыИзмеренияНоменклатуры.Ссылка
|ИЗ
| Справочник.ЕдиницыИзмеренияНоменклатуры КАК ЕдиницыИзмеренияНоменклатуры
|ГДЕ
| ЕдиницыИзмеренияНоменклатуры.Владелец = &Товар
| И ЕдиницыИзмеренияНоменклатуры.ЕдиницаПоКлассификатору = &ЕдиницаПоКлассификатору
| И (НЕ ЕдиницыИзмеренияНоменклатуры.ПометкаУдаления)”;
Запрос.УстановитьПараметр(“ЕдиницаПоКлассификатору”, Товар.БазоваяЕдиница);
Запрос.УстановитьПараметр(“Товар”, Товар);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
Возврат ВыборкаДетальныеЗаписи.Ссылка;
Иначе
Возврат Справочники.ЕдиницыИзмеренияНоменклатуры.ПустаяСсылка();
КонецЕсли;
//}}КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА
КонецФункции // ПолучитьЕдиницуИзмерения()
&НаКлиенте
Процедура ТоварыКачествоПриИзменении(Элемент)
КонецПроцедуры
&НаКлиенте
Процедура ТоварыЦенаПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ТД.Сумма = ТД.Цена*ТД.Количество;
КонецПроцедуры
&НаКлиенте
Процедура ТоварыСуммаПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ТД.Количество=ОбщиеФункцииСервер.Пересчет(ТД.Цена, ТД.Сумма, ТД.Количество).Количество;
Тд.Цена=ОбщиеФункцииСервер.Пересчет(ТД.Цена, ТД.Сумма, ТД.Количество).Цена;
КонецПроцедуры
&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ТД.Сумма = ТД.Цена*ТД.Количество;
КонецПроцедуры
модуль обьекта
Процедура ОбработкаПроведения(Отказ, Режим)
//{{__КОНСТРУКТОР_ДВИЖЕНИЙ_РЕГИСТРОВ
// Данный фрагмент построен конструктором.
// При повторном использовании конструктора, внесенные вручную изменения будут утеряны!!!
Движения.ОстаткиТоваров.Записывать = Истина;
Для Каждого ТекСтрокаТовары Из Товары Цикл
// регистр ОстаткиТоваров Приход
Движение = Движения.ОстаткиТоваров.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Номенклатура = ТекСтрокаТовары.Номенклатура;
Движение.Качество = ТекСтрокаТовары.Качество;
Движение.Количество = ТекСтрокаТовары.Количество*ТекСтрокаТовары.ЕдиницаИзмерения.К;
КонецЦикла;
Движения.Закупки.Записывать = Истина;
Для Каждого ТекСтрокаТовары Из Товары Цикл
// регистр Закупки
Движение = Движения.Закупки.Добавить();
Движение.Период = Дата;
Движение.Поставщик = Сотрудник;
Движение.Товары = ТекСтрокаТовары.Номенклатура;
Движение.Количество = ТекСтрокаТовары.Количество;
Движение.Стоимость = ТекСтрокаТовары.Сумма;
КонецЦикла;
//}}__КОНСТРУКТОР_ДВИЖЕНИЙ_РЕГИСТРОВ
КонецПроцедуры
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
СуммаДок=Товары.Итог(“Сумма”);
КонецПроцедуры
Справочник Номенклатура
модуль обьекта
Процедура ПередЗаписью(Отказ)
ЭтоНовый = ЭтоНовый();
Отбор=Новый Структура(“Товары”,СсыЗакупюлка);
Отбор1=Новый Структура(“Номенклатура”,Ссылка);
ОстТов=РегистрыНакопления.ОстаткиТоваров.Выбрать(,,Отбор1);
Закуп=РегистрыНакопления.Закупки.Выбрать(,,Отбор);
Если ОстТов.Следующий() Или Закуп.Следующий() тогда
сообщить(“Есть движения.Менять единицу нельзя”);
Отказ=Истина;
КонецЕсли;
КонецПроцедуры
Журнал документа
Документы закупки
графы поставщик и сумма
данные Авансотчет и Поступление товара
Задание выполнил.
1. Привязку менеджеров компании сделал через регистр сведений “МенеджерыПредприятия” (в пределах дня, независимый)
2.Документ “КонтактСКлиентом” проводится (фиксирует событие) и делает запись, при выполнении условия задачи, в независимый регистр сведений МенеджерыПредприятия, для чего использовал обработчик события модуля документа ПередЗаписью(). Во всяком случае, так я понял задание.
3.Для хранения цен на товары создал регистр сведений “ЦеныНоменклатуры” (в пределах дня,независимый)
4.Далее добавил функционал в работе с документами ТМЦ, создал регистр накопления(остатки) “ОстаткиТоваров”, регистр накопления(обороты) “ЗакупкиТоваров”.
5.Проверку на запрет изменения реквизита номеклатуры “БазоваяЕдиницаИзмерения” реализовал в обработчике события “НачалоВыбора” поля формы и запроса к регистрам.Можно было бы еще применить и метод глобального контекста “НайтиПоСсылкам()”.
P.s. Задание интересное и полезное.Многое осмысливаешь пока находишь ответ.Очень эффективно, сравнивать Ваше решение,с тем что сделал сам, чтобы понять, где ошибался, а где можно было сделать проще и оптимальнее.
Задание выполнил, проблем не возникло.
Привязку менеджеров контрагентов выполнил при помощи переодического регистра сведений с периодичностью день, измерение контрагент, ресурс менеджер.
в документ “событие” добавил реквизит менеджер,
в процедуре ОбработкаЗаполнения модуля объекта заполнение текущим пользователем из параметров сеанса, при проведении запросом проверяю привязку контрагента к менеджеру, если запрос возвращает пустой результат запроса, добавляю записи. Проверки заполнения реквизитов выполнены выставлением свойств реквизитов объектов “Проверка заполнение” в “Выдавать ошибку”.
В документах поступления использовал об работчики событий ПриИзменении, добавлен реквизит СуммаДокумента. Реквизит “контактное лицо” связал с реквизитом “Контрагент” при помощи свойства реквизита “связи параметров выбора” Отбор.Владелец(Контрагент)
При проведении Товары перересчитываются к базовым единицам.
Данные о закупках хранятся в регистре накопления с видом регистра обороты.
Контроль изменения базовой единицы номенклатуры реализовал при помощи функции “НайтиПоСсылкам”
Привязку менеджеров компании к клиентам сделал через регистр сведений «МенеджерыКлиентов». (Измерение – «Клиент», ресурс – «Менеджер»). Периодичность в пределах дня, независимый. Заполняется документом «КонтактСКлиентом», при этом проверка первого контакта проводится в модуле объекта перед записью:
<code>
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Отбор = Новый Структура(“Клиент”, Клиент);
Набор = РегистрыСведений.МенеджерыКлиентов.ПолучитьПоследнее(,Отбор).Менеджер;
Если Набор.Пустая() Тогда
ЗаписьМенеджера = РегистрыСведений.МенеджерыКлиентов.СоздатьМенеджерЗаписи();
ЗаписьМенеджера.Клиент = Клиент;
ЗаписьМенеджера.Менеджер = Менеджер;
ЗаписьМенеджера.Период = Дата;
ЗаписьМенеджера.Записать();
КонецЕсли;
КонецПроцедуры
</code>
Выборка контактных лиц, указанного в документе контрагента у меня ещё в прошлом задании была реализована, как впрочем и пересчёт суммы по цене и количеству (вернее, в моей реализации, цена в табличной части документов не доступна для изменения интерактивно, пересчёт производится при изменении/выборе номенклатуры), а так же отображение итоговой суммы документа.
Хранение цен на товары реализовал через регистр сведений «ЦеныНоменклатуры». Периодичность в пределах дня, независимый. Ведение нескольких прайс-листов обеспечивается несколькими реквизитами типа Число (ПрайсЛист_1 — ПрайсЛист_4). Для выбора пользователем в документах закупки и отгрузки прайс-листа соответствующему реквизиту назначил тип «ПеречислениеСсылка.ПрайсЛисты». В самом перечислении – соответствующее количество элементов с синонимами, в которых расписано — розничный/мелкооптовый и т.д. При выборе номенклатуры в документах по учёту ТМЦ, происходит анализ индекса перечисления ПрайсЛисты и через Case выбирается соответствующая цена.
<code>
&НаКлиенте
Процедура ПоступлениеНоменклатураПриИзменении(Элемент)
ТекДанные = Элементы.Поступление.ТекущиеДанные;
ТекДанные.ЕденицыИзмерения = ПолучитьЕдиницуИзмерения(ТекДанные.Номенклатура);
ТекущийПрайс = Объект.ПрайсЛист;
ТекДанные.Цена = ЗагрузитьЦенуСервер(Объект.Дата, ТекДанные.Номенклатура, ТекущийПрайс);
ТекДанные.Сумма = ОбщиеФункцииКлиент.ПолучитьСумму(ТекДанные.Количество, ТекДанные.Цена);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ЗагрузитьЦенуСервер(Дата, Номенклатура, Прайс)
НомерПрайса = Перечисления.ПрайсЛисты.Индекс(Прайс)+1;
Отбор = Новый Структура(“Номенклатура”, Номенклатура);
Набор = РегистрыСведений.ЦеныНоменклатуры.ПолучитьПоследнее(Дата,Отбор);
Если НомерПрайса = 1 Тогда
Возврат Набор.ПрайсЛист_1;
ИначеЕсли НомерПрайса = 2 Тогда
Возврат Набор.ПрайсЛист_2;
ИначеЕсли НомерПрайса = 3 Тогда
Возврат Набор.ПрайсЛист_3;
ИначеЕсли НомерПрайса = 4 Тогда
Возврат Набор.ПрайсЛист_4;
КонецЕсли;
КонецФункции
</code>
Далее создал константу «ПересчитыватьПриИзмененииСуммы» с типом данных «ПеречислениеСсылка.ЦенаКоличество» и соответсвующее перечисление с двумя значениями. При изменении суммы вызывается функция из ОбщийМодульСервера, которая возвращает структуру, значения из которой потом загружаются в соответствующие ячейки строки.
Листинг процедуры модуля формы:
<code>
&НаКлиенте
Процедура ПоступлениеСуммаПриИзменении(Элемент)
ТекДанные = Элементы.Поступление.ТекущиеДанные;
ЦенаКоличество = ОбщиеФункцииСервер.ПересчетПриИзмененииСуммы(ТекДанные.Сумма, ТекДанные.Цена, ТекДанные.Количество);
ТекДанные.Цена = ЦенаКоличество.Цена;
ТекДанные.Количество = ЦенаКоличество.Количество;
КонецПроцедуры
</code>
Листинг функции из ОбщийМодульСервера:
<code>
Функция ПересчетПриИзмененииСуммы(Сумма, Цена, Количество) Экспорт
Пересчет = Строка(Константы.ПересчитыватьПриИзмененииСуммы.Получить());
ЦенаКоличество = Новый Структура(“Цена”, Цена);
ЦенаКоличество.Вставить(“Количество”, Количество);
Если Пересчет = “Количество” Тогда
ЦенаКоличество.Количество = Окр(Сумма/Цена, 2);
ИначеЕсли Пересчет = “Цена” Тогда
ЦенаКоличество.Цена = Окр(Сумма/Количество, 2);
Иначе
Сообщить(“Правило пересчёта не установлено”);
КонецЕсли;
Возврат ЦенаКоличество;
КонецФункции
</code>
Для хранения остатков создал регистр накопления «ОстаткиТоваров», ресурсы «Номенклатура» и «Качество», измерение «Остатки». Регистраторы — ПоступлениеТоваров и АвансовыйОтчет на приход, сразу сделал и проведение РеализацииТоваров на расход. При проведении сравниваются базовая еденица измерения номенклатуры и еденица измерения в табличной части, при необходимости производится перерасчёт в базовые еденицы.
Листинг модуля объекта документа РеализацияТоваров:
<code>
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Движения.ОстаткиТоваров.Записывать = Истина;
Для Каждого ТекСтрокаПоступление Из Реализация Цикл
Движение = Движения.ОстаткиТоваров.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
Движение.Период = Дата;
Движение.Номенклатура = ТекСтрокаПоступление.Номенклатура;
Движение.Качество = ТекСтрокаПоступление.Брак;
БазоваяЕденица = ТекСтрокаПоступление.Номенклатура.БазоваяЕденица;
Если БазоваяЕденица = ТекСтрокаПоступление.ЕденицыИзмерения Тогда
Движение.Остатки = ТекСтрокаПоступление.Количество;
Иначе
Коэфф = ТекСтрокаПоступление.ЕденицыИзмерения.К;
Количество = ТекСтрокаПоступление.Количество*Коэфф;
Движение.Остатки = Количество;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
</code>
Для хранения данных о закупках от поставщиков создал регистр накопления «ЗакупкиОтПоставщиков» типа Обороты. Измерения «Номеклатура» и «Контрагент», ресурсы «Количество» и «Стоимость». В документе ПоступлениеТоваров дополнил обработку проведения следующим кодом в том же цикле:
<code>
//ЗакупкиОтПоставщиков
Движение = Движения.ЗакупкиОтПоставщиков.Добавить();
Движение.Период = Дата;
Движение.Номенклатура = ТекСтрокаПоступление.Номенклатура;
Движение.Контрагент = Контрагент;
Движение.Количество = ТекСтрокаПоступление.Количество;
Движение.Стоимость = ТекСтрокаПоступление.Сумма;
</code>
Проверку, запрещающую изменять базовую единицу измерения, провожу перед записью элемента справочника. Проверяю, есть ли записи с данной номенклатурой следующим образом:
<code>
Процедура ПередЗаписью(Отказ)
ЭтоНовый = ЭтоНовый();
Отбор = Новый Структура(“Номенклатура”, Ссылка);
ЗаписиВРегистре = РегистрыНакопления.ОстаткиТоваров.Обороты(,,Отбор).Количество();
Если ЗаписиВРегистре > 0 Тогда
Сообщить(“Изменение базовой еденицы измерения запрещено!”);
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
</code>
Журнал документов «Документы закупки» создал как в уроке.
Вопросы по заданию: данные о закупках от поставщиков — поступления по Авансовым отчётам учитывать не надо? Я так понимаю это уже будут поступления от подотчётных лиц (сотрудников организации).
Насколько целесообразно (или это просто в учебных целях) применение Прайсов в документах поступления? Просто за одну дату возможна поставка одной номенклатуры от разных поставщиков (цены, скорее всего, будут разные). Опять же продажа получается по этой же цене, где тогда выгода?
И ещё, наверное, пожелание. Хотелось бы что-то типа единого набора исходных данных для решения и проверки задач.
>данные о закупках от поставщиков — поступления по Авансовым отчётам учитывать не надо?
Поступления Авансовым отчетом тоже закупки, поэтому в общем случае их учитывать надо.
Например, с пустым значением контрагента в регистре.
>Насколько целесообразно (или это просто в учебных целях) применение Прайсов в документах поступления?
Все зависит от решаемой задачи. В типовых цена закупки привязана еще и к поставщику.
>Опять же продажа получается по этой же цене, где тогда выгода
Продажа осуществляется по другому типу цен. Разница и есть выгода.
>Хотелось бы что-то типа единого набора исходных данных для решения и проверки задач.
Все-таки может быть несколько различных и в тоже время правильных решений. Поэтому наборы данных подготовить затруднительно.
Регистр сведений МенеджерыКлиентов периодический, периодичность в пределах секунды, режим записи независимый. Измерение Контрагент типа
СправочникСсылка.Контрагенты (ведущее, запрет незаполненных значений). Ресурс Менеджер типа СправочникСсылка.Пользователи.
Поведение документа КонтактСКлиентом, обусловленное условиями задачи, реализовано в модуле объекта
<code>
Перем ЭтоНовый;
Процедура ОбработкаЗаполнения(ДанныеЗаполнения, СтандартнаяОбработка)
Менеджер = ОбщиеФункцииСервер.СинхронизацияПользователей();
КонецПроцедуры
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
ЭтоНовый = ЭтоНовый();
КонецПроцедуры
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Отбор = Новый Структура(“Контрагент”, Контрагент);
Если РегистрыСведений.МенеджерыКлиентов.ПолучитьПоследнее(Дата, Отбор).Менеджер.Пустая() Тогда
МенеджерЗаписи = РегистрыСведений.МенеджерыКлиентов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Период = Дата;
МенеджерЗаписи.Контрагент = Контрагент;
МенеджерЗаписи.Менеджер = Менеджер;
МенеджерЗаписи.Записать();
КонецЕсли;
КонецПроцедуры
</code>
Для работы с ценами номенклатуры создан регистр сведений ЦеныНоменклатуры с независимым режимом записи и периодичностью в пределах дня. Измерения Номенклатура типа СправочникСсылка.Номенклатура и ТипЦены типа СправочникСсылка.ТипыЦен – оба измерения ведущие с запретом незаполненных значений. Числовой ресурс Цена. Считается, что хранится цена базовой единицы измерения номенклатуры.
В документах закупки и отгрузки создан реквизит ТипЦен типа СправочникСсылка.ТипыЦен, в котором пользователь выбирает прайс, для заполнения цен текущего документа. Функция, возвращающая цену номенклатуры, размещается в общем модуле ЗаполнениеДокументовСервер, компилируемом на сервере с возможностью вызова сервера.
<code>
Функция ПолучитьЦену(Дата, Номенклатура, ТипЦен, ЕдиницаИзмерения) Экспорт
Отбор = Новый Структура();
Отбор.Вставить(“Номенклатура”, Номенклатура);
Отбор.Вставить(“ТипЦены”, ТипЦен);
Возврат РегистрыСведений.ЦеныНоменклатуры.ПолучитьПоследнее(Дата, Отбор).Цена * ЕдиницаИзмерения.К;
КонецФункции // ПолучитьЦену()
</code>
Во все документы закупки и отгрузки добавлен реквизит СуммаДокумента, значение которого определяется в процессе записи документов в их модулях:
<code>
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
СуммаДокумента = Товары.Итог(“Сумма”);
КонецПроцедуры
</code>
Для его отображения на формах документов добавлен соответствующий элемент вида поле надписи.
Требуемое интерактивное поведение документов закупки и отгрузки обеспечивается процедурами и функциями модулей основных форм документов. Вследствие одинаковой структуры табличных частей документов эти модули полностью идентичны:
<code>
&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ТД.ЕдиницаИзмерения = ПолучитьЕдиницуИзмерения(ТД.Номенклатура);
ТД.Цена = ЗаполнениеДокументовСервер.ПолучитьЦену(Объект.Дата, ТД.Номенклатура, Объект.ТипЦен, ТД.ЕдиницаИзмерения);
ПересчитатьСумму(ТД);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьЕдиницуИзмерения(Товар)
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| ЕдиницыИзмеренияНоменклатуры.Ссылка
|ИЗ
| Справочник.ЕдиницыИзмеренияНоменклатуры КАК ЕдиницыИзмеренияНоменклатуры
|ГДЕ
| ЕдиницыИзмеренияНоменклатуры.Владелец = &Товар
| И ЕдиницыИзмеренияНоменклатуры.ЕдиницаПоКлассификатору = &ЕдиницаПоКлассификатору
| И (НЕ ЕдиницыИзмеренияНоменклатуры.ПометкаУдаления)”;
Запрос.УстановитьПараметр(“ЕдиницаПоКлассификатору”, Товар.БазоваяЕдиница);
Запрос.УстановитьПараметр(“Товар”, Товар);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
Возврат ВыборкаДетальныеЗаписи.Ссылка;
Иначе
Возврат Справочники.ЕдиницыИзмеренияНоменклатуры.ПустаяСсылка();
КонецЕсли;
КонецФункции // ПолучитьЕдиницуИзмерения()
&НаКлиенте
Процедура ПересчитатьСумму(ТД)
ТД.Сумма = ТД.Цена*ТД.Количество;
КонецПроцедуры // ПересчитатьСумму()
&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ПересчитатьСумму(ТД);
КонецПроцедуры
&НаКлиенте
Процедура ТоварыЦенаПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ПересчитатьСумму(ТД);
КонецПроцедуры
&НаКлиенте
Процедура ТоварыСуммаПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
Если ТД.Количество = 0 Или ТД.Цена = 0 Тогда
ПересчитатьСумму(ТД);
Возврат;
КонецЕсли;
ЗаполнениеДокументовСервер.ПересчитатьЦенуИлиКоличество(ТД.Сумма, ТД.Цена, ТД.Количество);
КонецПроцедуры
</code>
Процедура ПересчитатьЦенуИлиКоличество размещается в общем модуле ЗаполнениеДокументовСервер, компилируемом на сервере с возможностью вызова сервера.
<code>
Процедура ПересчитатьЦенуИлиКоличество(Сумма, Цена, Количество) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| Константы.ПриИзмененииСуммы
|ИЗ
| Константы КАК Константы”;
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
Если ВыборкаДетальныеЗаписи.ПриИзмененииСуммы = Перечисления.ВариантыПересчетаПриИзмененииСуммы.ПересчитатьКоличество Тогда
Количество = Сумма / Цена;
ИначеЕсли ВыборкаДетальныеЗаписи.ПриИзмененииСуммы = Перечисления.ВариантыПересчетаПриИзмененииСуммы.ПересчитатьЦену Тогда
Цена = Сумма / Количество;
Иначе
Сумма = Цена * Количество;
КонецЕсли;
КонецЕсли;
КонецПроцедуры // ПересчитатьЦенуИлиКоличество()
</code>
Константа ПриИзмененииСуммы типа ПеречислениеСсылка.ВариантыПересчетаПриИзмененииСуммы (значения ПересчитатьЦену и ПересчитатьКоличество)
Остатки товаров хранятся в регистре накопления вида остатки ОстаткиТоваров. Измерения Номенклатура и Качество, ресурс Количество.
Для хранения данных о закупках от поставщиков создан регистр накопления Закупки вида обороты с измерениями Контрагент и Номенклатура и ресурсами Количество и Стоимость. При проведении документов закупки осуществляется запись движений в эти регистры. Документ ПоступлениеТоваров:
<code>
Процедура ОбработкаПроведения(Отказ, Режим)
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| ПоступлениеТоваровТовары.Номенклатура,
| ПоступлениеТоваровТовары.Качество,
| ПоступлениеТоваровТовары.ЕдиницаИзмерения.К КАК КоэффициентЕИ,
| СУММА(ПоступлениеТоваровТовары.Количество) КАК Количество,
| СУММА(ПоступлениеТоваровТовары.Сумма) КАК Сумма
|ИЗ
| Документ.ПоступлениеТоваров.Товары КАК ПоступлениеТоваровТовары
|ГДЕ
| ПоступлениеТоваровТовары.Ссылка = &Ссылка
| И ПоступлениеТоваровТовары.Номенклатура.ВидНоменклатуры = &ВидНоменклатуры
|
|СГРУППИРОВАТЬ ПО
| ПоступлениеТоваровТовары.Номенклатура,
| ПоступлениеТоваровТовары.Качество,
| ПоступлениеТоваровТовары.ЕдиницаИзмерения.К”;
Запрос.УстановитьПараметр(“ВидНоменклатуры”, Перечисления.ВидыНоменклатуры.Товар);
Запрос.УстановитьПараметр(“Ссылка”, Ссылка);
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Отказ = Истина;
КонецЕсли;
Если Отказ Тогда
Возврат;
КонецЕсли;
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Движения.ОстаткиТоваров.Записывать = Истина;
Движения.Закупки.Записывать = Истина;
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
//регистр накопления ОстаткиТоваров
Движение = Движения.ОстаткиТоваров.ДобавитьПриход();
Движение.Период = Дата;
Движение.Номенклатура = ВыборкаДетальныеЗаписи.Номенклатура;
Движение.Качество = ВыборкаДетальныеЗаписи.Качество;
Движение.Количество = ВыборкаДетальныеЗаписи.Количество * ВыборкаДетальныеЗаписи.КоэффициентЕИ;
//регистр накопления Закупки
Движение = Движения.Закупки.Добавить();
Движение.Период = Дата;
Движение.Контрагент = Контрагент;
Движение.Номенклатура = ВыборкаДетальныеЗаписи.Номенклатура;
Движение.Количество = ВыборкаДетальныеЗаписи.Количество * ВыборкаДетальныеЗаписи.КоэффициентЕИ;
Движение.Стоимость = ВыборкаДетальныеЗаписи.Сумма;
Движение.ВидЗакупки = Перечисления.ВидыЗакупок.ОтПоставщика;
КонецЦикла;
КонецПроцедуры
</code>
Для документа АвансовыйОтчет аналогично, но в регистре Закупки оставляем незаполненным измерение Контрагент.
В обоих регистрах установлено свойство Запрет незаполненных значений для измерения Номенклатура.
Проверку, запрещающую изменять базовую единицу измерения для номенклатуры, если по ней уже есть движения в регистрах, реализуем в модуле объекта справочника Номенклатура:
<code>
Процедура ПередЗаписью(Отказ)
ЭтоНовый = ЭтоНовый();
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| Номенклатура.БазоваяЕдиница
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка = &Ссылка”;
Запрос.УстановитьПараметр(“Ссылка”, Ссылка);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Если БазоваяЕдиница <> ВыборкаДетальныеЗаписи.БазоваяЕдиница Тогда
Если ЕстьДвиженияВРегистрах() Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = “Нельзя изменять базовую единицу измерения, так как по этой номенклатуре уже есть движения в регистрах”;
Сообщение.Поле = “БазоваяЕдиница”;
Сообщение.УстановитьДанные(ЭтотОбъект);
Сообщение.Сообщить();
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция ЕстьДвиженияВРегистрах()
Отбор = Новый Структура(“Номенклатура”, Ссылка);
Выборка = РегистрыСведений.ЦеныНоменклатуры.Выбрать(,,Отбор);
Если Выборка.Следующий() Тогда
Возврат Истина;
КонецЕсли;
Выборка = РегистрыНакопления.Закупки.Выбрать(,,Отбор);
Если Выборка.Следующий() Тогда
Возврат Истина;
КонецЕсли;
Выборка = РегистрыНакопления.ОстаткиТоваров.Выбрать(,,Отбор);
Если Выборка.Следующий() Тогда
Возврат Истина;
КонецЕсли;
Возврат Ложь;
КонецФункции // ЕстьДвиженияВРегистрах()
</code>
Для того, чтобы работал метод менеджера регистра накопления Выбрать(), признак индексирования измерения Номенклатура регистров Закупки и ОстаткиТоваров установлен в значение “Индексировать”.
создала регистр сведений КлиентМенеджер измерение Клиент, ресурс Менеджер. в документе КонтактСКлиентом модуль объекта процедура обработка заполнения если это новый тогда из общего модуля получить текущего пользователя и присвоить его реквизиту Менеджер.
Обработка проведения запросом получаем данные из регистра сведений КлиентМенеджер, если запрос пустой тогда создаем запись в регистре через менеджер записи.
Регистр сведений ЦеныНоменклатуры измерение Номенклатура, ВидЦены( справочник ссылка тип цен) ресурс цена в пределах дня. В документах общие функции сервер ПолучитьЦену(ТД.Номенклатура,Объект.ВидЦены,Объект.Д
ата) Цена получается из регистра сведений метод ПолучитьПоследнее()
Количество и Цена при изменении общие функции клиент перессчитать сумму(ТД). Сумма при изменении общие функции клиент клиент перессчет строки (ТД) в ней вызываем сервер для получения константы и возвращаем ее значение. в зависимости от значения меняется либо количество либо цена.
регистр накопления остатки Товары измерение номенклатура ,качество ресурс количество регистраторы поступление и авансовый отчет.
Регистр накопления обороты Закупки измерения контрагент, номенклатура, ресурсы количество и стоимость. регистраторы поступление и авансовый отчет.
В модуле формы элемента справочника запросом получаем информацию о движениях по данной номенклатуре, если они есть изменить базовую единицу нельзя.
Создала журнал документов ДокументыЗакупки с дополнительными графами контрагент сумма документа.
Задание выполнено.
Привязку менеджеров осуществил через реквизит Менеджер у справочника Контрагенты. Добавил еще табл. часть Менеджеры к справочнику Контрагенты, если менеджеров будет несколько. Подстановку Менеджера в документ выполнил в процедуре ПриСозданииНа Сервере модуля формы документа КонтактСКлиентом. При проведении проверяется заполнение реквизита Менеджер у Контрагента. Добавил регистр сведений ЦеныНоменклатуры с измерениями ТипЦен (добавил в конфигурацию справочник ТипЦен) , Номенклатура и ресурсами Цена, ЕдИзм. Добавил реквизиты ТипЦен и СуммаДокумента в документы по учету ТМЦ. В формы этих документов добавил реквизит формы СуммаВсего.
Для пересчета суммы добавил общий модуль ОбщиеФункцииКлиентСервер (клиент,сервер) и разместил в нем процедуру:
<code>
Процедура ПересчитатьСуммуДокумента(Объект,Форма) Экспорт
Форма.СуммаВсего = Объект.Товары.Итог(“Сумма”);
КонецПроцедуры
</code>
Модуль формы Поступления ТМЦ:
<code>
&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ТД.ЕдиницаИзмерения = ПолучитьЕдиницуИзмерения(ТД.Номенклатура);
СтруктураЦены = Новый структура;
СтруктураЦены.Вставить(“Дата”,Объект.Дата);
СтруктураЦены.Вставить(“ТипЦен”,Объект.ТипЦен);
ТД.Цена = ПолучитьЦенуНоменклатуры(ТД.Номенклатура,СтруктураЦены);
ТД.Сумма = ТД.Цена*ТД.Количество;
ОбщиеФункцииКлиентСервер.ПересчитатьСуммуДокумента(Объект,ЭтаФорма);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьЕдиницуИзмерения(Товар)
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| ЕдиницыИзмеренияНоменклатуры.Ссылка
|ИЗ
| Справочник.ЕдиницыИзмеренияНоменклатуры КАК ЕдиницыИзмеренияНоменклатуры
|ГДЕ
| ЕдиницыИзмеренияНоменклатуры.Владелец = &Товар
| И ЕдиницыИзмеренияНоменклатуры.ЕдиницаПоКлассификатору = &ЕдиницаПоКлассификатору
| И (НЕ ЕдиницыИзмеренияНоменклатуры.ПометкаУдаления)”;
Запрос.УстановитьПараметр(“ЕдиницаПоКлассификатору”, Товар.БазоваяЕдиница);
Запрос.УстановитьПараметр(“Товар”, Товар);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
Возврат ВыборкаДетальныеЗаписи.Ссылка;
Иначе
Возврат Справочники.ЕдиницыИзмеренияНоменклатуры.ПустаяСсылка();
КонецЕсли;
КонецФункции
&НаСервереБезКонтекста
Функция ПолучитьЦенуНоменклатуры(Товар,СтруктураЦены)
Запрос = новый Запрос;
Запрос.Текст = “ВЫБРАТЬ
| ЦеныНоменлатурыСрезПоследних.Цена КАК Цена
|ИЗ
| РегистрСведений.ЦеныНоменлатуры.СрезПоследних(
| &ДатаДок,
| Номенклатура = &Номенклатура
| И ТипЦен = &ТипЦен) КАК ЦеныНоменлатурыСрезПоследних”;
Запрос.УстановитьПараметр(“Номенклатура”,Товар);
Запрос.УстановитьПараметр(“ДатаДок”,СтруктураЦены.Дата);
Запрос.УстановитьПараметр(“ТипЦен”,СтруктураЦены.ТипЦен);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
Возврат ВыборкаДетальныеЗаписи.Цена;
иначе
Возврат 0;
КонецЕсли;
КонецФункции
&НаКлиенте
Процедура ТоварыСуммаПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ВариантПересчета = ОбщиеФункцииСервер.ВернутьВариантПересчета();
Если ВариантПересчета = 1 Тогда
ТД.Количество = ТД.Сумма/?(ТД.Цена=0,1,ТД.Цена);
иначе
ТД.Цена = ТД.Сумма/?(ТД.Количество=0,1,ТД.Количество);
КонецЕсли;
ОбщиеФункцииКлиентСервер.ПересчитатьСуммуДокумента(Объект,ЭтаФорма);
КонецПроцедуры
&НаКлиенте
Процедура ТоварыПриОкончанииРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования)
ОбщиеФункцииКлиентСервер.ПересчитатьСуммуДокумента(Объект,ЭтаФорма);
КонецПроцедуры
&НаКлиенте
Процедура ТоварыПослеУдаления(Элемент)
ОбщиеФункцииКлиентСервер.ПересчитатьСуммуДокумента(Объект,ЭтаФорма);
КонецПроцедуры
&НаСервере
Процедура ПриЧтенииНаСервере(ТекущийОбъект)
ЭтаФорма.СуммаВсего = ТекущийОбъект.СуммаДокумента;
КонецПроцедуры
</code>
В модуле документа Поступление ТМЦ добавил процедуру ПередЗаписью() в которой устанавливается реквизит СуммаДокумента.
Добавил регистр остатков ОстаткиНоменклатуры с измерениями Номенклатура,Качество и ресурсом Количество . Добавил регистр оборотов ЗакупкиТовара с измерениями Поставщик, Номенклатура и ресурсами Количество,Сумма.
Проведение по регистрам сделал с помощью конструктора и изменил расчет с поправкой на коэффициент ЕдИзм.
Запрет изменения базовой единицы выполнил в модуле формы элемента справрчника Номенлатура :
<code>
&НаСервереБезКонтекста
Функция ПроверитьБазовую(Объект)
Запр = новый Запрос;
Запр.УстановитьПараметр(“Номенклатура”,Объект.ссылка);
ТипНоменклатура = Тип(“СправочникСсылка.Номенклатура”);
Запр.Текст = “”;
Для Каждого РегистрНакопления Из Метаданные.РегистрыНакопления Цикл
Для Каждого РеквизитРегистра из РегистрНакопления.Измерения Цикл
Если РеквизитРегистра.Тип.СодержитТип(ТипНоменклатура) Тогда
Если Запр.текст <> “” Тогда
Запр.текст = Запр.Текст+ “ОБЪЕДИНИТЬ ВСЕ”;
КонецЕсли;
Запр.текст = Запр.Текст+ ”
|ВЫБРАТЬ ПЕРВЫЕ 1
| 1 КАК Результат
|ИЗ
| РегистрНакопления.”+РегистрНакопления.Имя+ ” КАК Рег
|ГДЕ
| Рег.”+ РеквизитРегистра.Имя+ ” = &Номенклатура
|” ;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Возврат НЕ Запр.Выполнить().Пустой();
КонецФункции
&НаКлиенте
Процедура БазоваяЕдиницаНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
Если ПроверитьБазовую(Объект.Ссылка) Тогда
сообщить(“Есть движения.Менять единицу нельзя”);
СтандартнаяОбработка =ложь;
КонецЕсли;
КонецПроцедуры
</code>
Добавил журнал документов ДокументыЗакупки с графами Контрагент и СуммаДокумента
Приучил себя таскать из дерева объектов метаданных реквизиты в код (что бы не ошибаться в именах), ожидал ежели перетащу спр. ВидыЦен в измерение Регистра сведений, система поставит тип СправочникСсылка.ВидыЦен, а вот нет Строка. Видать не дорос еще машинный интеллект до такого волшебства.
Да, пока такого платформа не умеет, даже в 8.2.14.
Подобное пожелание у разработчиков уже записано.
Добавил реквизит МенеджерКонтрагента в спр. Контрагенты, вывел на ФормуЭлемента.
Добавил реквизит Менеджер в док. Событие (КонтактСКлиентом) определил свойство Проверка заполнения, для реквизита КонтактноеЛицоКонтрагента определил свойство Связи параметров выбора. В Модуле объекта определил процедуру ОработкаЗаполнения и подставил текущего пользователя в реквизит Менеджер, в проц. ОбработкаПроведения проверил запросом наличие док. Событие от Контрагента
<code> |ГДЕ
| Событие.Контрагент = &Контрагент
| И Событие.Ссылка <> &Ссылка”;</code>
И если Результат.Пустой() Записал Менеджера в реквизит справочника.
Создал спр. ВидыЦен, рег. Сведений ЦеныНоменклатуры: измерения Номенклатура, ВидЦен, ресурсы Цена, ЕдиницаИзмерения
В документы добавил новый реквизит ВидЦен, за искл. Дока Событие. В ОбщийМодуль РаботаСДиалогамиСервер добавил процедуру ПолучитьЦенуНоменклатурыПоВидуЦен, внутри запрос
<code> “ВЫБРАТЬ
| ЦеныНоменклатурыСрезПоследних.Цена КАК Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
| &ДатаОбработки,
| Номенклатура = &Номенклатура
| И ВидЦен = &ВидЦен) КАК ЦеныНоменклатурыСрезПоследних”;</code>
Которую и вызываю из МодуляФормы документов при обработке событий ТЧ «Товары». Все пересчеты сделал в прошлом ДЗ, добавил только Константу ПересчетКоличестваИлиЦены, значение которой и анализирую, естественно получаю значение константы в модуле свойство Сервер. Итоги показал в подвале ТЧ «Товары».
Создал регистры Запасы, Закупки. Измерение Поставщик у рег. Закупки составной тип.
Движения док. поступлений создал конструктором, ранее прозорливо добавил в ТЧ доков реквизит Коэффициент и обработал заполнение при изм. ЕдиницыИзмерения, так что
<code>Движение.Количество = ТекСтрокаТовары.Количество*ТекСтрокаТовары.Коэффициент;</code>
Оптимизировал код конструктора – сделал один цикл. Включил просмотр движений в УФ доков.
Проверку базовой ед. реализовал в Модуле ФормыЭлемента проц. ПриСозданииНаСервере: выбрал запросом из рег. ЗапасыОбороты, если НЕ Результат.Пустой() ->
<code>Элементы.БазоваяЕдиница.Доступность = Ложь;</ode>
Создал журнал «ДокументыЗакупки», рег. Документы: АвансовыйОтчет и ПриходнаяНакладная, для графы Сумма, создал реквизит СуммаДокумента у документов и присвоил значение
<code>СуммаДокумента = Товары.Итог(“Сумма”);</code>
В МО проц. ПередЗаписью(). Все отладил. Все ок.
Задание выполнил. Трудновато с передачей данных формы на сервер и обратно, но добился работоспособности кода.
1.Независимый регистр сведений “МенеджерыКонтрагентов”, период “День” с измерением “Контрагент” и ресурсом “Менеджер”.
2.В модуле объекта документа “КонтактСКлиентом” в обработчике “ОбработкаЗаполнения” для нового заполняю менеджера текущим пользователем.
В “ОбработкаПроведения” обращаюсь к общеу серверному модулю к экп. ф-ии “ЭтоПервыйКонтакт(Ссылка)”. Если возвращ. значение истинное, с помощью класса “РегистрСведенийМенеджерЗаписи”
записываю менеджера на дату документа.
В функции “ЭтоПервыйКонтакт(Ссылка)” делаю запрос (“ВЫБРАТЬ ПЕРВЫЕ 1”) к проведенным документам “КонтактСКлиентом” не равным передаваемой ссылке. “Возврат Результат.Пустой()”
3.Справочник “ТипыЦен”. Независимый периодический(день) рег. сведений “ЦеныНоменклатуры” с изм. “Номенклатура”,”ТипЦены” и ресурсом “Цена”.
В документах рекв. шапки “ТипЦен”.
В формах док. в обработчиках “ПриИзменении” данных тыб. части, вызываю клиентскую процедуру:
<code>&НаКлиенте
Процедура ОбработкаТЧКлиент(ИмяЭлемента)
ТД = Элементы.Товары.ТекущиеДанные;
СтруктураПараметров = Новый Структура;
СтруктураПараметров.Вставить(“Объект”, Объект);
СтруктураПараметров.Вставить(“Номенклатура”, ТД.Номенклатура);
СтруктураПараметров.Вставить(“Цена”, ТД.Цена);
СтруктураПараметров.Вставить(“ЕдиницаИзмерения”, ТД.ЕдиницаИзмерения);
СтруктураПараметров.Вставить(“Количество”, ТД.Количество);
СтруктураПараметров.Вставить(“Сумма”, ТД.Сумма);
ОбщиеФункцииСервер.ОбработкаТабличнойЧасти(СтруктураПараметров, ИмяЭлемента);
Если ИмяЭлемента = “ТоварыНоменклатура” Тогда
ТД.Цена = СтруктураПараметров.Цена;
ТД.ЕдиницаИзмерения = СтруктураПараметров.ЕдиницаИзмерения;
КонецЕсли;
Если ИмяЭлемента = “ТоварыЦена” ИЛИ ИмяЭлемента = “ТоварыКоличество” ИЛИ ИмяЭлемента=”ТоварыНоменклатура” Тогда
ТД.Сумма = СтруктураПараметров.Сумма;
ИначеЕсли ИмяЭлемента = “ТоварыСумма” Тогда
ТД.Количество = СтруктураПараметров.Количество;
ТД.Цена = СтруктураПараметров.Цена;
КонецЕсли;
КонецПроцедуры</code>
Общйй серверный модуль делает заполнения и пересчет за один вызов:
<code>Процедура ОбработкаТабличнойЧасти(Параметры, ИмяЭлемента) Экспорт
Если ИмяЭлемента = “ТоварыНоменклатура” Тогда
Объект = Параметры.Объект;
Номенклатура = Параметры.Номенклатура;
ТипЦен = Объект.ТипЦен;
Если Не ТипЦен.Пустая() Тогда
Если Объект.Ссылка.Пустая() Тогда
ПериодЦен = Объект.Дата;
Иначе
ПериодЦен = Объект.Ссылка.МоментВремени();
КонецЕсли;
Параметры.Цена = ОбщиеФункцииСервер.ПолучитьЦенуНоменклатуры(Номенклатура, ТипЦен, ПериодЦен);
КонецЕсли;
Параметры.ЕдиницаИзмерения = ПолучитьЕдиницуИзмерения(Номенклатура);
КонецЕсли;
//Пересчет
Если ИмяЭлемента=”ТоварыЦена” ИЛИ ИмяЭлемента=”ТоварыКоличество” ИЛИ ИмяЭлемента=”ТоварыНоменклатура” Тогда
Параметры.Сумма = Параметры.Цена*Параметры.Количество;
ИначеЕсли ИмяЭлемента = “ТоварыСумма” Тогда
Режим = Константы.РежимПересчетаПриИзмененииСуммы.Получить();
Если Режим = Перечисления.РежимыПересчетаПриИзмененииСуммы.ПересчитыватьКоличество Тогда
Параметры.Количество = ?(Параметры.Цена=0, Параметры.Количество, Параметры.Сумма/Параметры.Цена);
ИначеЕсли Режим = Перечисления.РежимыПересчетаПриИзмененииСуммы.ПересчитыватьЦену Тогда
Параметры.Цена = ?(Параметры.Количество=0, Параметры.Цена, Параметры.Сумма/Параметры.Количество);
КонецЕсли;
КонецЕсли;
КонецПроцедуры</code>
4.Регистр накопления (остатки) “ОстаткиТоваров” с измерениями “Номенклатура”, “Качество” и ресурсом “Количество”.
При проведении, если единица изм. не базовая – перевожу количество с учетом коэф. ед. изм.
Регистр накопления (обороты) “Закупки” с измерениями “Поставщик”(составной тип), “Номенклатура”, и ресурсами “Количество”, “Сумма”.
При проведении, если единица изм. не базовая – перевожу количество с учетом коэф. ед. изм.
Измерения индексирую дополнительно.
При проведении документов использую один цикл по строкам.
5. В модуле объекта “ПередЗаписью” спр. “Номенклатура”
<code>
Процедура ПередЗаписью(Отказ)
ЭтоНовый = ЭтоНовый();
Если НЕ ЭтоНовый И (Ссылка.БазоваяЕдиница<>БазоваяЕдиница) И ОбщиеФункцииСервер.ЕстьДвиженияПоРегистрам(Ссылка) Тогда
Отказ = Истина;
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = “Запрещено менять базовую единицу измерения!”+Символы.ПС+”По номенклатуре “+Ссылка+” уже есть записи в регистрах!”;
Сообщение.Сообщить();
КонецЕсли;
КонецПроцедуры</code>
В общем модуле (ОбщиеФункцииСервер.ЕстьДвиженияПоРегистрам(Ссылка)) делаю запрос к регистрам накопления “ОстаткиТоваров” и “Закупки” – объединением таблиц с отбором по номенклатуре. Выбираю первые.
Если результат пустой – возврат “истина”.
6. В журнале “ДокументыЗакупки” добавил графы “Поставщик” – контрагент/сотрудник и “Сумма”, куда вывожу реквизит шапки документов “СуммаДокумента”, расчитываемый перед их записью.
Задание выполнила
Созданы 2 регистра сведений – независимый основной менеджер контрагента и контакты с контрагентами, где регистратор – документ “Контакт с клиентом”
http://fotoifolder.ru/view_full_size/9k17uuuejz7j
http://fotoifolder.ru/view_full_size/07dp2yxpbqhp
http://fotoifolder.ru/view_full_size/s3dgd4ka07y2
У справочника контрагенты добавил реквизит Менеджер тип СправочникСсылка.Пользователи.
Историю менеджеров по контрагенту храню в регистре сведений МенеджерыКлиентов
Модуль объекта спр контрагенты
<code>
Процедура ПередЗаписью(Отказ)
Отбор=Новый Структура(“Клиент”,Ссылка);
Посл=РегистрыСведений.МенеджерыКлиентов.ПолучитьПоследнее(,Отбор);
Если Посл.Менеджер<>Менеджер Тогда
МенКл=РегистрыСведений.МенеджерыКлиентов.СоздатьМенеджерЗаписи();
МенКл.Клиент=Ссылка;
МенКл.Менеджер=Менеджер;
МенКл.Период=ТекущаяДата();
МенКл.Записать();
КонецЕсли;
КонецПроцедуры
Процедура ПередЗаписью(Отказ) Отбор=Новый Структура(“Клиент”,Ссылка); Посл=РегистрыСведений.МенеджерыКлиентов.ПолучитьПоследнее(,Отбор); Если Посл.Менеджер<>Менеджер Тогда МенКл=РегистрыСведений.МенеджерыКлиентов.СоздатьМенеджерЗаписи(); МенКл.Клиент=Ссылка; МенКл.Менеджер=Менеджер; МенКл.Период=ТекущаяДата(); МенКл.Записать(); КонецЕсли;КонецПроцедуры
</code>
Документ КонтактСКлиентом МодульФормы
<code>
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если Объект.Ссылка.Пустая() тогда
Объект.Менеджер=глТекущийПользователь;
КонецЕсли;
//Вставить содержимое обработчика
КонецПроцедуры
</code>
МодульОбъекта
<code>
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| КонтактСКлиентом.Ссылка
|ИЗ
| Документ.КонтактСКлиентом КАК КонтактСКлиентом
|ГДЕ
| КонтактСКлиентом.Контрагент = &Контрагент
| И КонтактСКлиентом.МоментВремени <> &МоментВремени”;
Запрос.УстановитьПараметр(“МоментВремени”, Ссылка.МоментВремени());
Запрос.УстановитьПараметр(“Контрагент”, Контрагент);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Если Не ВыборкаДетальныеЗаписи.Следующий() Тогда
КонтрСсылка=Справочники.Контрагенты.НайтиПоНаименованию(Контрагент);
Контр=КонтрСсылка.ПолучитьОбъект();
Контр.Менеджер=Менеджер;
Контр.записать();
// Вставить обработку выборки ВыборкаДетальныеЗаписи
КонецЕсли;
</code>
Создаем регистр сведений цены с измерениями
Номенклатура,Прайс и ресурсом Цена
<code>
&НаКлиенте
Процедура ТоварыНоменклатураПриИзменении(Элемент)
ТД = Элементы.Товары.ТекущиеДанные;
ТД.ЕдиницаИзмерения = ПолучитьЕдиницуИзмерения(ТД.Номенклатура);
Если Не Объект.Прайс.Пустая() Тогда
ЦенаПоПрайсу=ПолучитьЦенуНаСервере(ТД.Номенклатура,Объект.Прайс,Объект.Дата);
ТД.цена=ЦенаПоПрайсу.Цена;
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьЦенуНаСервере(Товар,Прайс,Дата)
Отбор=Новый Структура;
Отбор.Вставить(“Номенклатура”,Товар);
Отбор.Вставить(“Прайс”,Прайс);
Цена=РегистрыСведений.Цены.ПолучитьПоследнее(Дата,Отбор);
Возврат Цена;
КонецФункции // ПолучитьЦенуНаСервере()
&НаСервереБезКонтекста
Функция ПолучитьЕдиницуИзмерения(Товар)
//{{КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА
// Данный фрагмент построен конструктором.
// При повторном использовании конструктора, внесенные вручную изменения будут утеряны!!!
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| ЕдиницыИзмеренияНоменклатуры.Ссылка
|ИЗ
| Справочник.ЕдиницыИзмеренияНоменклатуры КАК ЕдиницыИзмеренияНоменклатуры
|ГДЕ
| ЕдиницыИзмеренияНоменклатуры.Владелец = &Товар
| И ЕдиницыИзмеренияНоменклатуры.ЕдиницаПоКлассификатору = &ЕдиницаПоКлассификатору
| И (НЕ ЕдиницыИзмеренияНоменклатуры.ПометкаУдаления)”;
Запрос.УстановитьПараметр(“ЕдиницаПоКлассификатору”, Товар.БазоваяЕдиница);
Запрос.УстановитьПараметр(“Товар”, Товар);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
Возврат ВыборкаДетальныеЗаписи.Ссылка;
Иначе
Возврат Справочники.ЕдиницыИзмеренияНоменклатуры.ПустаяСсылка();
КонецЕсли;
//}}КОНСТРУКТОР_ЗАПРОСА_С_ОБРАБОТКОЙ_РЕЗУЛЬТАТА
КонецФункции // ПолучитьЕдиницуИзмерения()
&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
ТД=Элементы.Товары.текущиеДанные;
ТД.Сумма=ОбщиеФункцииКлиент.ПересчетСуммы(Тд.Цена,Тд.Количество);
// Вставить содержимое обработчика.
КонецПроцедуры
&НаКлиенте
Процедура ТоварыЦенаПриИзменении(Элемент)
ТД=Элементы.Товары.текущиеДанные;
ТД.Сумма=ОбщиеФункцииКлиент.ПересчетСуммы(Тд.Цена,Тд.Количество);
КонецПроцедуры
&НаКлиенте
Процедура ТоварыСуммаПриИзменении(Элемент)
ТД=Элементы.Товары.текущиеДанные;
ОбщиеФункцииСервер.ПересчетКоличестваИЦены(ТД.Количество,ТД.Цена,ТД.Сумма);
КонецПроцедуры
</code>
ОбщиеФункцииСервер
<code>
Функция ПересчетКоличестваИЦены(Количество,Цена,сумма) Экспорт
Если Константы.ПересчетКоличестваИЦены.Получить() тогда
Цена=Сумма/Количество;
Иначе Количество=Сумма/Цена;
КонецЕсли;
КонецФункции
</code>
Создаем два регистра накопления остатки товаров измерения товар,степеньбрака ресурс количество и закупки измерения товары поставщик и ресурсы количество стоимость
Документ ПоступлениеТоваров модуль объекта
<code>
Процедура ОбработкаПроведения(Отказ, Режим)
Движения.ОстаткиТоваров.Записывать = Истина;
Для Каждого ТекСтрокаТовары Из Товары Цикл
Движение = Движения.ОстаткиТоваров.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Товар = ТекСтрокаТовары.Номенклатура;
Движение.СтепеньБрака = ТекСтрокаТовары.Качество;
Движение.Количество = ТекСтрокаТовары.Количество;
КонецЦикла;
Движения.Закупки.Записывать = Истина;
Для Каждого ТекСтрокаТовары Из Товары Цикл
Движение = Движения.Закупки.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Товар = ТекСтрокаТовары.Номенклатура;
Движение.Поставщик = Контрагент;
Движение.Количество = ТекСтрокаТовары.Количество;
Движение.Стоимость = ТекСтрокаТовары.Сумма;
КонецЦикла;
КонецПроцедуры
</code>
Далее Справочник Номенклатура МодульФормы
<code>
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ОтказБЕ=ПроверкаСервер(Объект.Ссылка);
Если ОтказБЕ Тогда
Элементы.БазоваяЕдиница.ТолькоПросмотр=истина;
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПроверкаСервер(Ссылка)
Отбор=Новый Структура(“Товар”,Ссылка);
ОстТов=РегистрыНакопления.ОстаткиТоваров.Выбрать(,,Отбор);
Закуп=РегистрыНакопления.Закупки.Выбрать(,,Отбор);
Если ОстТов.Следующий() Или Закуп.Следующий() Тогда
Возврат Истина
Иначе Возврат Ложь;
КонецЕсли;
КонецФункции // ПередЗаписьюСервер()
</code>
Создал журнал ДокументыЗакупки с первыми двумя колонками трудностей не возникло, Сумму реализовал через дополнительный реквизит ИтогСумма как в лекции.
У меня вопрос в форме журнала есть реквизит
Список.Ссылка.Товары.ИтогСумма. Для чего он применяется или просто в платформе прописано выводить суммы для числовых реквизитов
Задание выполнил.
Создал РегистрСведений «Менеджеры», без подчинения регистратору
Создал справочник «ТипыЦен»
В документе «Контакт» сделал заполнение регистра «Менеджеры» в случае первого контакта с контрагентов. Первый контакт проверял по наличию документа «Контакт» с этим контрагентом, т.к. в регистр могли занести данные вручную для других целей.
Создал РегистрСведений «ЦеныНоменклатуры», без подчинения регистратору. Сначала создал непериодический – при обращении за ценами пришлось поломать голову над непонятной ошибкой, но потом догадался…
Создал РегистрНакопления «ОстаткиНоменклатуры», «ЗакупкиНоменклатуры»
Проверку на изменение базовой единицы измерения сделал в обработке события при начале выбора
Выполнил.
Ввел справочник ТипыЦен с предопределенными значениями Закупочная и Розничная (которые автоматически устанавливаются для новых документов Поступления и Реализации соответственно)
Ввел регистры СВЕДЕНИЙ:
КонтрагентыПоМенеджерам (Изм = Контрагент, Рес = Менеджер, можно было добавить Реквизит = КонтактноеЛицо). Независимый, Периодический (с точностью до секунды)
ЦеныНоменклатуры (Изм = Номенклатура, ТипЦены, Рес = Цена). Подчинил регистратору “АктПереоценки”, которым изменяю цены номенклатуры по выбранному типу цен. Акт переоценки можно ввести на основании справочника ТипыЦен и документа ПоступлениеТоваров.
Анализ менеджеров у контрагента вынес в модуль менеджера регистра КонтрагентыПоМенеджерам:
Функция ЕстьМенеджерУКонтрагента(Контр, НаДату = “”) Экспорт
Отбор = Новый Структура(“Контрагент”,Контр ) ;
Если ЗначениеЗаполнено(НаДату) Тогда
ВГ = Новый Граница ( КонецДня(НаДату),ВидГраницы.Включая);
Структура = ПолучитьПоследнее( ВГ, Отбор);
Иначе
Структура = ПолучитьПоследнее( , Отбор);
КонецЕсли;
Возврат Структура.Менеджер;
КонецФункции
Получение цены по номенклатуре и типу цены также вынес в модуль менеджера соответствующего регистра. Пока использовал объектную структуру и ПолучитьПоследнее…
В документах АктПереоценки, ПоступлениеТоваров, РеализацияТоваров создал реквизит ТипЦены.
По видео-урокам мастер-группы с целью множественного подбора создал в справочнике Номенклатуры произвольную форму ДляПодбора с дополнительными ревизитами ТипЦены, НаДату для обеспечения вывода цены выбираемой номенклатуры. Кнопку Подбор вставил во все документы, работающие с номенклатурой.
Обеспечил ПЕРЕСЧЕТ цен (пока не оптимальным образом) при изменении в этих документах реквизитов Дата и ТипЦены.
Создал регистры НАКОПЛЕНИЙ:
ОстаткиТоваров (Изм = Номенклатура,Состояние,Рес=Количество). Вид = Остатки;
Закупки (Изм = Поставщик – составной тип Контрагенты и Сотрудники, Номенклатура, Рес = Количество, Стоимость). Вид = Обороты
При проведении документа ПоступлениеТоваров проверяю товар на вид номенклатуры = Услуга.
Пересчитываю количество в базовые единицы (предварительно в табличные части документов ввел реквизит Коэффициент, зависимый от единицы измерения номенклатуры)
Для вывода в журнале документов ИтоговойСуммы завел в шапке Поступления одноименный реквизит = Товары.Итог(“Сумма”) – в модуле объекта ПередЗаписью()
В списки документов ввел кнопку “Движения документа” по регистрам (как по видео-урокам) с предварительным выбором вида регистра.
Возможность смены базовой единицы (а также вида номенклатуры!) проверяю в модуле объекта ПередЗаписью()
Первоначальные (исходные) значения единицы и вида номенклатуры до записи можно взять из реквизита Ссылка:
//проверим, что можно менять базовую единицу измерения и вид номенклатуры у записанных элементов
Если НЕ ЭтоНовый() Тогда //существует ссылка на еще пока не записанный элемент (исходный вид)
СтарБазЕд = Ссылка.БазоваяЕдИзм;
СтарВидНом = Ссылка.ВидНоменклатуры;
Если (СтарБазЕд <> БазоваяЕдИзм)ИЛИ(СтарВидНом <> ВидНоменклатуры) Тогда //поменяли базовую ед. или вид номенклатуры – а можно??
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ ПЕРВЫЕ 1
| ОстаткиТоваровОбороты.Номенклатура
|ИЗ
| РегистрНакопления.ОстаткиТоваров.Обороты КАК ОстаткиТоваровОбороты
|ГДЕ
| ОстаткиТоваровОбороты.Номенклатура.Ссылка = &Ссылка
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ ПЕРВЫЕ 1
| ЗакупкиОбороты.Номенклатура
|ИЗ
| РегистрНакопления.Закупки.Обороты КАК ЗакупкиОбороты
|ГДЕ
| ЗакупкиОбороты.Номенклатура.Ссылка = &Ссылка”;
Запрос.УстановитьПараметр(“Ссылка”, Ссылка);
………………………………………
“Привязку менеджеров” реализовал с помощью регистра сведений “МенеджерыКлиентов”, с помощью интерфейса можно поменять менеджера. Документ “КонтактСКлиентом” Код на проверку<code>
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
АнализКонтагента(Контрагент,Менеджер);
КонецПроцедуры
Процедура АнализКонтагента(Контрагент,Менеджер)
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| МенеджерыКлиентов.Контрагент
|ИЗ
| РегистрСведений.МенеджерыКлиентов КАК МенеджерыКлиентов
|ГДЕ
| МенеджерыКлиентов.Контрагент = &Контрагент”;
Запрос.УстановитьПараметр(“Контрагент”, Контрагент);
//Запрос.УстановитьПараметр(“Менеджер”, Менеджер);
Если Запрос.Выполнить().Пустой() Тогда
МенеджерСвед = РегистрыСведений.МенеджерыКлиентов.СоздатьМенеджерЗаписи();
МенеджерСвед.Контрагент = Контрагент;
МенеджерСвед.Менеджер = Менеджер;
МенеджерСвед.Записать();
КонецЕсли;
КонецПроцедуры
Процедура ОбработкаПроведения(Отказ, РежимПроведения) АнализКонтагента(Контрагент,Менеджер);КонецПроцедуры
Процедура АнализКонтагента(Контрагент,Менеджер) Запрос = Новый Запрос; Запрос.Текст = “ВЫБРАТЬ | МенеджерыКлиентов.Контрагент |ИЗ | РегистрСведений.МенеджерыКлиентов КАК МенеджерыКлиентов |ГДЕ | МенеджерыКлиентов.Контрагент = &Контрагент”;
Запрос.УстановитьПараметр(“Контрагент”, Контрагент); //Запрос.УстановитьПараметр(“Менеджер”, Менеджер);
Если Запрос.Выполнить().Пустой() Тогда МенеджерСвед = РегистрыСведений.МенеджерыКлиентов.СоздатьМенеджерЗаписи(); МенеджерСвед.Контрагент = Контрагент; МенеджерСвед.Менеджер = Менеджер; МенеджерСвед.Записать(); КонецЕсли; КонецПроцедуры</code>
Хранение цен реализовано отдельным справочником, который испльзуется в документах ТМЦ. Пример “ПоступлениеТоваров“. Приведу код модуля формы документа получения цен при выборе номенклатуры и соответствующего общего модуля. Модуль формы документа<code>&НаКлиенте
Процедура ТоварыКоличествоПриИзменении(Элемент)
ПересчетСуммы();
КонецПроцедуры
&НаКлиенте
Процедура ТоварыЦенаПриИзменении(Элемент)
ПересчетСуммы();
КонецПроцедуры
&НаКлиенте
Процедура ПересчетСуммы()
ТД = Элементы.Товары.ТекущиеДанные;
ТД.Сумма = ТД.Количество*ТД.Цена;
КонецПроцедуры // ПересчетСуммы()
&НаКлиенте
Процедура ТоварыНомеклатураПриИзменении(Элемент)
Элементы.Товары.ТекущиеДанные.ЕдиницаИзмерения = ОбработкаНоменклатуры.УказатьЕдиницуИзмерения(Элементы.Товары.ТекущиеДанные.Номенклатура);
Элементы.Товары.ТекущиеДанные.Цена = ОбработкаНоменклатуры.ПодставитьЦену(Элементы.Товары.ТекущиеДанные.Номенклатура, Объект.Дата, Объект.Прайс);
ПересчетСуммы();
КонецПроцедуры
&НаКлиенте
Процедура ТоварыСуммаПриИзменении(Элемент)
Если ПроверкаКонстСервер() Тогда
Элементы.Товары.ТекущиеДанные.Количество = Окр(Элементы.Товары.ТекущиеДанные.Сумма/Элементы.Товары.ТекущиеДанные.Цена,2);
Иначе
Элементы.Товары.ТекущиеДанные.Цена = Окр(Элементы.Товары.ТекущиеДанные.Сумма/Элементы.Товары.ТекущиеДанные.Количество,2);
КонецЕсли;
КонецПроцедуры
&НаСервере
Функция ПроверкаКонстСервер()
Возврат ЗначениеЗаполнено(Константы.ПересчитатьКоличество);
КонецФункции// ПроверкаКонстСервер()
</code>
Общий модуль “ОбработкаНоменклатуры”<code>&НаСервере
Функция УказатьЕдиницуИзмерения(ВыбранноеЗначение) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| ЕдиницыИзмерения.Ссылка
|ИЗ
| Справочник.ЕдиницыИзмерения КАК ЕдиницыИзмерения
|ГДЕ
| ЕдиницыИзмерения.Владелец = &Владелец
| И ЕдиницыИзмерения.Коэффициент = 1”;
Запрос.УстановитьПараметр(“Владелец”, ВыбранноеЗначение);
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Возврат ВыборкаДетальныеЗаписи.Ссылка;
КонецЦикла;
КонецФункции// УказатьЕд()
&НаСервере
Функция ПодставитьЦену(ВыбранноеЗначение, Дата, Прайс) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| ЦеныНоменклатурыСрезПоследних.Цена
|ИЗ
| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Дата, Номенклатура = &ПарамНоменклатура) КАК ЦеныНоменклатурыСрезПоследних
|ГДЕ
| ЦеныНоменклатурыСрезПоследних.ТипЦен = &Прайс”;
Запрос.УстановитьПараметр(“Дата”, Дата);
Запрос.УстановитьПараметр(“ПарамНоменклатура”, ВыбранноеЗначение);
Запрос.УстановитьПараметр(“Прайс”, Прайс);
Если Запрос.Выполнить().Пустой() Тогда
Возврат 0;
Иначе
Выборка = Запрос.Выполнить().Выбрать();
Выборка.Следующий();
Возврат Выборка.Цена;
КонецЕсли;
КонецФункции // ПодставитьЦену()
&НаСервере
Функция Обработка_ЕИ(Ссылка) Экспорт
Запрос = Новый Запрос();
Запрос.УстановитьПараметр(“Номенклатура”, Ссылка);
Запрос.Текст = “”;
Для Каждого РегистрНакопления Из Метаданные.РегистрыНакопления Цикл
Если Запрос.Текст <> “” Тогда
Запрос.Текст = Запрос.Текст + ”
|ОБЪЕДИНИТЬ ВСЕ
|”;
КонецЕсли;
Запрос.Текст = Запрос.Текст + ”
|ВЫБРАТЬ
|”+РегистрНакопления.Имя+”.Номенклатура
|ИЗ
| РегистрНакопления.”+РегистрНакопления.Имя+” КАК “+РегистрНакопления.Имя+”
|”;
КонецЦикла;
СуществуютСерии = НЕ Запрос.Выполнить().Пустой();
Возврат СуществуютСерии;
КонецФункции // Обработка_ЕИ()</code>
Создал регистр накопления для хранения остатков(вид регистра – остатки). Создал регистр накопления для хранения информации по закупкам(вид регистра-обороты). Фото
Обработка проведения док-та “Поступление товаров”:<code>Процедура ОбработкаПроведения(Отказ, Режим)
Движения.ОстаткиТоваров.Записывать = Истина;
Для Каждого ТекСтрокаТовары Из Товары Цикл
Движение = Движения.ОстаткиТоваров.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Номенклатура = ТекСтрокаТовары.Номенклатура;
Движение.Качество = ТекСтрокаТовары.Качество;
Движение.Количество = ТекСтрокаТовары.Количество*ТекСтрокаТовары.ЕдиницаИзмерения.Коэффициент;
КонецЦикла;
Движения.Закупки.ВыполнитьДвижения(Контрагент,Товары);
КонецПроцедуры
</code>
Модуль регистра “Закупки”:
<code>Процедура ВыполнитьДвижения(Поставщик,Товары) Экспорт
Для каждого Строка Из Товары Цикл
НаборЗаписей = Добавить();
НаборЗаписей.Период = Отбор.Регистратор.Значение.Дата;
НаборЗаписей.Номенклатура = Строка.Номенклатура;
НаборЗаписей.Контрагент = Поставщик;
НаборЗаписей.Количество = Строка.Количество*Строка.ЕдиницаИзмерения.Коэффициент;
НаборЗаписей.Стоимость = Строка.Сумма;
КонецЦикла;
Записать();
КонецПроцедуры
</code>
Журнал документов “Документы закупки”
Проверка изменения ЕИ
<code>Процедура ОбработкаПроверкиЗаполнения(Отказ, ПроверяемыеРеквизиты)
ТипНоменк = ПроверяемыеРеквизиты.Найти(“ЕдиницаИзмерения”);
Если ЭтотОбъект.ВидНоменклатуры = Перечисления.ВидНоменклатуры.Услуга И НЕ ЭтотОбъект.ЭтоГруппа Тогда
ПроверяемыеРеквизиты.Удалить(ТипНоменк);
КонецЕсли;
Если Не ЭтоНовый() И НЕ ЭтоГруппа И Ссылка.ЕдиницаИзмерения <> ЕдиницаИзмерения Тогда
Если ОбработкаНоменклатуры.Обработка_ЕИ(ЭтотОбъект.Ссылка) Тогда
Сообщить(“Данная номенклатура используется в движениях регистра.”);
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры</code>
<code>&НаСервере
Функция Обработка_ЕИ(Ссылка) Экспорт
Запрос = Новый Запрос();
Запрос.УстановитьПараметр(“Номенклатура”, Ссылка);
Запрос.Текст = “”;
Для Каждого РегистрНакопления Из Метаданные.РегистрыНакопления Цикл
Если Запрос.Текст <> “” Тогда
Запрос.Текст = Запрос.Текст + ”
|ОБЪЕДИНИТЬ ВСЕ
|”;
КонецЕсли;
Запрос.Текст = Запрос.Текст + ”
|ВЫБРАТЬ
|”+РегистрНакопления.Имя+”.Номенклатура
|ИЗ
| РегистрНакопления.”+РегистрНакопления.Имя+” КАК “+РегистрНакопления.Имя+”
|”;
КонецЦикла;
СуществуютСерии = НЕ Запрос.Выполнить().Пустой();
Возврат СуществуютСерии;
КонецФункции // Обработка_ЕИ()
</code>
Задание выполнил
Задание выполнил
http://www.imagepost.ru/images/d/z8/dz8_screen.png
Готово.
Интересным показался такой момент: так как у меня контактные лица хранились в табличной части справочника Контрагенты, то отбор при открытии формы выбора контактного лица я делала, получая запросом список ссылок контактных лиц и передавая затем его в параметр открываемой формы. Не думала, что программа распознает список в качестве значения Структуры “Ссылка” правильно, но все сработало, вид сравнения установился “В списке”.
И все-таки контактных лиц правильнее хранить в подчиненном справочнике.
В вашем случае, можно безболезненно удалить контактное лицо из табличной части, даже если оно выбрано в документе для данного контрагента.
То есть может возникнуть ситуация, когда в документе для контрагента выбрано не его контактное лицо.
Переделала контактные лица. И кстати, ошиблась, было два кода в разных документах, проводила один, глядела на другой. Сработал этот код:
<code> ФормаВыбора = ПолучитьФорму(“Справочник.КонтактныеЛица.ФормаВыбора”,,Элемент);
Отбор = ФормаВыбора.Список.Отбор.Элементы.Добавить(тип(“ЭлементОтбораКомпоновкиДанных”));
Отбор.ЛевоеЗначение = Новый ПолеКомпоновкиДанных(“Ссылка”);
Отбор.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
Отбор.ПравоеЗначение = СписокКл;
Отбор.Использование = Истина;
ФормаВыбора.Открыть();
</code>
а передача списка значений в параметр не работает (.
У меня отбор работает и со списком значений, и с массивом.
Вот пример кода:
Список.Добавить(ПредопределенноеЗначение("Справочник.Номенклатура.Раз"));
Список.Добавить(ПредопределенноеЗначение("Справочник.Номенклатура.Два"));
Отбор = Новый Структура("Ссылка", Список);
ПараметрыФормы = Новый Структура("Отбор", Отбор);
ОткрытьФорму("Справочник.Номенклатура.ФормаСписка", ПараметрыФормы);