Продвинутый курс. Занятие №1
Первое занятие по 0-му блоку продвинутого курса.
Необходимо изучить следующие главы 0-го курса.
Глава 1. Запуск информационных баз.
Глава 2. Автоматическая установка платформы.
Глава 3. Архитектура системы.
Глава 4. Клиент-серверный вариант работы ИБ.
Глава 5. Журнал регистрации.
— залогиньтесь.
Если не активировали токен — посмотрите видео-инструкцию (видео N5)
Если вы залогинены, у Вас активирован токен доступа, но вы все равно видите эту запись —
напишите нам на e-mail поддержки.
Сначала попытался сделать логирование при помощи регистрации события _$Data$_.Update. Но для табличной части документа сделать это не удалось. Сделал подписку на событие ПередЗаписью для документов поступления и реализации. В обработчике подписки на событие получаю метаданные источника и прохожу циклом по все табличным частям источника. Проверяю на существование реквизитов Номенклатура и Цена табличной части. Сравниваю при помощи запроса новое и старое значение цены. Информацию об изменениях цен записываю в журнал регистрации при помощи процедуры ЗаписьЖурналаРегистрации.
Создал отчет по истории изменения цен. При этом использовал процедуру ВыгрузитьЖурналРегистрации.
Задание выполнил.
Пытался сделать через событие _$Access$_.Access. Но как ни странно привязаться к табличной части документа не получилось) К тому же подумал, что нужно логировать любое изменение цены, даже без последующей записи.
После просмотра решения преподавателя, все встало на свои места.
Отчет выполнил на СКД
Задание выполнил. Запись в журнал регистрации делаю в процедуре общего модуля, который вызываю “Перед записью” документа. Перед записью проверяю, есть ли дубли строк с разной ценой, если есть, то отказываюсь записывать. Старую цену нахожу поиском строки по номенклатуре в таб.части Объект.Ссылка.Товары. Информацию об изменении цены записываю в комментарий. С получением данных из ЖР и формированием отчета проблем не возникло.
Создала подписку на событие. Источники: ДокументОбъект.РеализацияТоваровИУслуг, ДокументОбъект.ПоступлениеТоваровИУслуг. Событие: ПередЗаписью. В обработчике след. код:
<code>
Если Источник.Проведен И Источник.Модифицированность() Тогда
Запрос = Новый Запрос;
Запрос.Текст = “ВЫБРАТЬ
| ТЗ.Номенклатура,
| ТЗ.Цена
|ПОМЕСТИТЬ ВТ_Новый
|ИЗ
| &ТЗ КАК ТЗ
|;
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ДокументТип.Номенклатура,
| ДокументТип.Цена
|ПОМЕСТИТЬ ВТ_Старый
|ИЗ
| Документ.”
+ Источник.Метаданные().Имя + “.Товары КАК ДокументТип
|ГДЕ
| ДокументТип.Ссылка = &Ссылка
|;
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ЕСТЬNULL(ВТ_Старый.Номенклатура, ВТ_Новый.Номенклатура) КАК Номенклатура,
| ЕСТЬNULL(ВТ_Старый.Цена, 0) КАК СтараяЦена,
| ЕСТЬNULL(ВТ_Новый.Цена, 0) КАК НоваяЦена
|ИЗ
| ВТ_Старый КАК ВТ_Старый
| ПОЛНОЕ СОЕДИНЕНИЕ ВТ_Новый КАК ВТ_Новый
| ПО ВТ_Старый.Номенклатура = ВТ_Новый.Номенклатура
|ГДЕ
| ЕСТЬNULL(ВТ_Старый.Цена, 0) <> ЕСТЬNULL(ВТ_Новый.Цена, 0)”;
Запрос.УстановитьПараметр(“ТЗ”, Источник.Товары);
Запрос.УстановитьПараметр(“Ссылка”, Источник.Ссылка);
СтрокаКомм = “”;
ТЗРезультат = Запрос.Выполнить().Выгрузить();
Для каждого СтрокаРезультата Из ТЗРезультат Цикл
УН = Строка(СтрокаРезультата.Номенклатура.УникальныйИдентификатор());
СтрокаКомм = СтрокаКомм + УН + “///” + Строка(СтрокаРезультата.СтараяЦена) + “///” + Строка(СтрокаРезультата.НоваяЦена) + “///”;
КонецЦикла;
ЗаписьЖурналаРегистрации(“Новые.Изменение цены в проведенном документе”, УровеньЖурналаРегистрации.Информация, Источник.Метаданные(), Источник.Ссылка, СтрокаКомм);
КонецЕсли;
</code>
Т.е. данные об изменение цен и номенклатуре виде строки (строка GUID номенклатуры /// старая цена /// новая цена///) записываются в комментарии. Предполагается, что номенклатура встречается в табличной части один раз. Тут еще надо бы разрезать комментарий, что бы все данные помещались, для упрощения не делается.
Отчет. Получается таблица значений из журнала регистрации (имяпользователя, данные (ссылка на измененный документ), дата, комментарий), комментарий разрезается, данные преобразуются в строку. Информация выводится в простой макет, с группировкой по имени пользователя.
Первую часть задания по логированию изменений цены выполнил вместе с потоком. Контроль изменений осуществляю в событии перед записью, результат изменений получаю в виде таблицы значений, которую затем сериализую при помощи ЗначениеВСтрокуВнутр и делаю запись в ЖР.
Отчет хотел сделать с использованием СКД, однако ничего не получилось. Не помогла и работа с имеющейся литературой. С эталонным решением я ознакомился, однако повторить его на своих данных не удалось, а вручную создавать макет и заполнять табличный документ не хотелось. И вот теперь, изучив тему первого блока по запросам, я разобрался с механизмом передачи таблицы значений в запрос в качестве параметра. Поэтому с небольшими затруднениями, но все же смог повторить подход по формированию отчета при помощи конструктора запроса и вывод результата в табличный документ.
Считываю данные из ЖР с фильтром по периоду и событию. Заполняю таблицу значений необходимыми данными и передаю ее в качестве параметра в запрос. Затем сохраняю результат во временную таблицу и далее во втором запросе пакета добавляю итоговую секцию по пользователю.
Логирование сделал через подписку на событие для поступления и реализации перед записью:
<code>
Процедура ПроверкаИзмененияЦенПередЗаписьюПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
Если Не Источник.Ссылка.Проведен Тогда Возврат; КонецЕсли;
СтТовары = Источник.Ссылка.Товары;
Для Каждого Стр Из Источник.Товары Цикл
СтСтр = СтТовары.Найти(Стр.Номенклатура);
Если СтСтр <> Неопределено И Стр.Цена <> СтСтр.Цена Тогда
ЗаписьЖурналаРегистрации(“ИзменениеЦены”,,Источник.Метаданные(),Источник.Ссылка,
“” + Стр.Номенклатура + ” Старая цена: ” + СтСтр.Цена + ” Новая цена: ” + Стр.Цена);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
</code>
отчет сделал очень просто
<code>
&НаКлиенте
Процедура Сформировать(Команда)
СформироватьНаСервере();
КонецПроцедуры
&НаСервере
Процедура СформироватьНаСервере()
ТЗ = Новый ТаблицаЗначений;
ВыгрузитьЖурналРегистрации(ТЗ,Новый Структура(“Событие”, “ИзменениеЦены”));
Тз.Сортировать(“ИмяПользователя”);
Объект = ДанныеФормыВЗначение(Отчет,Тип(“ОтчетОбъект.ОтчетПоСобытиямИзмененияЦен”));
Макет = Объект.ПолучитьМакет(“Макет”);
ТабДок.Очистить();
ТабДок.Вывести(Макет.ПолучитьОбласть(“Шапка”));
Для Каждого Стр Из ТЗ цикл
ОбластьСтрока = Макет.ПолучитьОбласть(“Строка”);
ОбластьСтрока.Параметры.Автор = Стр.ИмяПользователя;
ОбластьСтрока.Параметры.Событие = Стр.Комментарий;
ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;
КонецПроцедуры // СформироватьНаСервере()
</code>
Задание выполнила. Запись в журнал регистрации производила используя подписку на событие “Перед записью” . Даные о ценах записывала в комментарий. Отчет формировала используя СКД. Источник данных – объект таблица значений.
Задание №1 выполнил
Задание выполнено.
Пытался записывать события просмотра журнала регистрации
ПриСозданииНаСервере модуля формы и ПриЗаписи модуля объекта с помощью
УстановитьИспользованиеСобытияЖурналаРегистрации(<ИмяСобытия>, <Использование>)
Хотел загрузить в поле Данные информацию по цене. Но из табличной части цена не хочет писаться.
// Документ
ПоляДоступа = Новый Массив;
ПоляДоступа.Добавить(“Номенклатура”);
ПоляРегистрации = Новый Массив;
ПоляРегистрации.Добавить(“Цена”);
Доступ = Новый ОписаниеИспользованияСобытияДоступЖурналаРегистрации;
Доступ.Объект = “Документы.ПоступлениеТоваровИУслуг.Товары”; //Не срабатывает
Доступ.ПоляРегистрации = ПоляРегистрации;
Доступ.ПоляДоступа = ПоляДоступа;
ОписанияДоступ.Добавить(Доступ);
Возможно, в принципе внести информацию в поле Данные из табличной части документа?
Ознакомьтесь с решением данного задания.
ДЗ выполнил.
ДЗ сделал
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если Ссылка.Проведен И РежимЗаписи = РежимЗаписиДокумента.Проведение Тогда
ИсходнаяТЧ = Ссылка.Товары;
Для Каждого ТекСтрокаТовары Из Товары Цикл
ИсходнаяСтрокаТовары = ИсходнаяТЧ.Найти(ТекСтрокаТовары.НомерСтроки, “НомерСтроки”);
СтарЦена = ИсходнаяСтрокаТовары.Цена;
НовЦена = ТекСтрокаТовары.Цена;
Если СтарЦена <> НовЦена Тогда
ЗаписьЖурналаРегистрации(“Данные.Изменение цены”,,,Ссылка, “Изменена цена у Номенклатуры ” + ТекСтрокаТовары.Номенклатура
+ ” с ” + СтарЦена + ” на ” + НовЦена);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Отчет сделал обычный (без СКД) – вывожу таблицу значений (выгрузку ЖР) в табличный документ по аналогии с формированием печатных форм
Евгений, а можно я здесь вопрос спрошу.
1. При разделении журнала регистрации (ЖР) например по годам, каждый код будет создаваться новый файл для хранения журнала. А если мне надо будет получить информацию, скажем, за три года, то при обращении из 1С к ЖР система сама “склеит” эти файлы, или покажет данные только за текущий год?
А когда старые данные уже будут не нужны – то можно просто удалить файлы ЖР? Например, можно просто так (без последсвий) удалить файл ЖР за 2008 год?
2. И еще один вопросик. Файлы ЖР хранятся в каталоге …/srvinfo/reg_1541/<IDБазы>/…
Например есть базы Sklad и Zarplata. А как понять какой у них ID? т.е. какая папка в каталоге reg_1541 соответсвует какой базе?
Очепятка:
При разделении журнала регистрации (ЖР) например по годам, каждый код будет создаваться новый файл
При разделении журнала регистрации (ЖР) например по годам, каждый год будет создаваться новый файл
>при обращении из 1С к ЖР система сама «склеит» эти файлы
Да, это так.
>Например, можно просто так (без последсвий) удалить файл ЖР за 2008 год?
Я бы не советовал так делать.
Лучше сокращать журнал средствами конфигуратора.
спасибо!
ID базы вы можете посмотреть в ibases.v8i.
Находится примерно по такому пути:
C:\Users\UserName\Application Data\1C\1CEStart
Задание выполнил. Регистрация событий затруднений не вызвало. А вот с СКД пришлось разбираться.
Регистрация события изменения цен выполняется в процедуре “ПередЗаписью”
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
Если Проведен Тогда
МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВременныхТаблиц;
Запрос.Текст =
“ВЫБРАТЬ
| ПоступлениеТоваровИУслугТовары.Номенклатура,
| ПоступлениеТоваровИУслугТовары.Цена КАК СтараяЦена
|ПОМЕСТИТЬ ТоварыБаза
|ИЗ
| Документ.ПоступлениеТоваровИУслуг.Товары КАК ПоступлениеТоваровИУслугТовары
|ГДЕ
| ПоступлениеТоваровИУслугТовары.Ссылка = &Ссылка”;
Запрос.УстановитьПараметр(“Ссылка”, Ссылка);
Запрос.Выполнить();
Запрос.Текст =
“ВЫБРАТЬ
| ТЧТовары.Номенклатура,
| ТЧТовары.Цена КАК НоваяЦена
|ПОМЕСТИТЬ ТоварыДок
| ИЗ &ТЧТовары КАК ТЧТовары”;
Запрос.УстановитьПараметр(“ТЧТовары”, Товары);
Запрос.Выполнить();
Запрос.Текст =
“ВЫБРАТЬ
| ТоварыДок.Номенклатура,
| ТоварыБаза.СтараяЦена,
| ТоварыДок.НоваяЦена
|ИЗ
| ТоварыДок КАК ТоварыДок
| Левое СОЕДИНЕНИЕ ТоварыБаза КАК ТоварыБаза
| ПО ТоварыДок.Номенклатура = ТоварыБаза.Номенклатура
|ГДЕ
| ТоварыБаза.СтараяЦена <> ТоварыДок.НоваяЦена” ;
Результат = Запрос.Выполнить();
МенеджерВременныхТаблиц.Закрыть();
Если НЕ Результат.Пустой() Тогда
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
Комментарий = “” + Выборка.Номенклатура + “. Старая цена – ” + Выборка.СтараяЦена + “. Новая цена – ” + Выборка.НоваяЦена;
ЗаписьЖурналаРегистрации(“Цена.Изменение”, УровеньЖурналаРегистрации.Предупреждение,,, Комментарий);
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
В СКД используется внешний набор данных – таблица значений. Заполнение отчета происходит программно в модуле объекта отчета:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ТаблицаСобытий = Новый ТаблицаЗначений;
Фильтр = Новый Структура;
Фильтр.Вставить(“Событие”, “Цена.Изменение”);
Колонки = “Дата, ИмяПользователя, Комментарий”;
ВыгрузитьЖурналРегистрации(ТаблицаСобытий, Фильтр, Колонки);
ВнешнийНД = Новый Структура;
ВнешнийНД.Вставить(“ТаблицаСобытий”, ТаблицаСобытий);
СКД = ПолучитьМакет(“ОсновнаяСхемаКомпоновкиДанных”);
Настройки = СКД.НастройкиПоУмолчанию;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СКД, Настройки);
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, ВнешнийНД);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);
ДокументРезультат.Показать();
КонецПроцедуры
Задание выполнено.
Запись в журнал регистрации формировал подпиской на событие с видом “ПередЗаписью”.
В отчете использовал запрос с временной таблицей, в которую помещал ТЗ. ТЗ же получал из метода ВыгрузитьЖР()
Логирую Изменение цены в документах проведённых(неважно запишется документ или нет, логируем все изменения цены/любое телодвижение пользователя с ценой/) на событии при изменении цены в документах саму процедуру записи вынес в отдельный модуль.
Отчёт формируется на основе СКД по вынруженной информации из Журнала Регистрации с фильтром по своему событию и пользователем, если по нему нужен фильтр в Отчете.
Поскольку в процессе редактирования документа изменение цены может происходить неоднократно, фиксировать факт изменения нужно в событии “ПередЗаписью”, когда можно получить старое и новое значение поля. Для универсальности можно использовать подписку на событие “ПередЗаписью” для всех объектов “Документ”, с обращением к метаданным.
Процедура ПередЗаписьюДокументаИзменениеЦены(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
Если НЕ Отказ И Источник.Проведен Тогда
СтарыйДокумент=Источник.Ссылка;
//Наименование реквизитов для номенклатуры и цены
РеквизитЦена=”Цена”;
РеквизитНоменклатура=”Номенклатура”;
МетаданныеДокумента=Источник.Метаданные();
Если МетаданныеДокумента.ТабличныеЧасти.Количество() >0 тогда
Для каждого ТЧ из МетаданныеДокумента.ТабличныеЧасти цикл
Если ТЧ.Реквизиты.Найти(РеквизитЦена)<>неопределено тогда //Есть ли у документа реквизит Цена в ТЧ
ТЧДокумента=Источник[ТЧ.Имя];//Получаем ТЧ документа
ТЧСтарогоДокумента=СтарыйДокумент[ТЧ.Имя];
Для каждого Строка из ТЧДокумента цикл
ИндексСтроки=ТЧДокумента.Индекс(Строка);
Номенклатура=Строка[РеквизитНоменклатура];
НоваяЦена=Строка[РеквизитЦена];
СтараяЦена=ТЧСтарогоДокумента[ИндексСтроки][РеквизитЦена];
Если НоваяЦена<>СтараяЦена тогда
ЗаписьЖурналаРегистрации(“Изменение цены”, УровеньЖурналаРегистрации.Предупреждение, МетаданныеДокумента, Источник.Ссылка,
“В строке ” + (ИндексСтроки + 1)+ ” табличной части “””+ ТЧ.Имя +””” изменена цена на Номенклатуру “”” + Номенклатура.Наименование +”””:”
+ Символы.ВК + “- старое значение: ” + Строка(СтараяЦена) + Символы.ВК + “- новое значение: ” + Строка(НоваяЦена));
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
В данном случае не учитывается возможность добавления/удаления строк и изменение порядка строк пользователем.
Данные для отчета получаем в таблицу значений с помощью функции:
Функция ВыгрузкаЖурналаРегистрации() Экспорт
ИзменениеЦен = Новый ТаблицаЗначений;
Фильтр=Новый Структура(“Событие”, “Изменение цены”);
ВыгрузитьЖурналРегистрации(ИзменениеЦен, Фильтр, “Дата,Комментарий,Данные,ИмяПользователя”, , ) ;
Возврат ИзменениеЦен;
КонецФункции
Данные выводим в табличный документ с группировкой по пользователю. При использовании простого отчета с выводом в табличный документ, таблицу значений предварительно сортируем.
Не удалось сделать до конца отчет на СКД. Здесь используем набор данных – объект, где таблица значений будет внешним набором данных. Однако формирование отчета сделала с помощью новой команды формы. Можно ли отключить или переопределить стандартную команду формы “Сформировать”?
>Можно ли отключить или переопределить стандартную команду формы «Сформировать»?
Самый лучший вариант – использовать событие ПриКомпоновкеРезультата модуля объекта.
Задание выполнил.
Так как требуется по заданию выполнять поверку не в одном определенном документе, а может в нескоьлких, то я решил сделать новую подписку на события. Объекты указал документы, а событие указал ПередЗаписью. Создал в общем модуле процедуру, которая и регистрирует изменения цены пользователем в журнале регистраций. Коротко поясню. Перед записью проверяем документ на то, что он был проведен и он модифицирован, далее проверяем все его таб. части на наличие реквизита Номенклатура и цена, так как документ может и не содержать таб. частей. Если есть и цена отличается от того, что было в проведенном ранее документе, то регистрирую это изменение. Внизу приведен код:
<cod>
Процедура ИзменениеЦеныПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
Ссылка = Источник.Ссылка;
Если Ссылка.Проведен И Источник.Модифицированность() Тогда
МетаданныеДокумента = Ссылка.Метаданные();
Для Каждого ТабЧасть Из МетаданныеДокумента.ТабличныеЧасти Цикл
Если ТабЧасть.Реквизиты.Найти(“Номенклатура”)=Неопределено ИЛИ ТабЧасть.Реквизиты.Найти(“Цена”)=Неопределено Тогда
Продолжить;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст = “ВЫБРАТЬ
| * Поместить ТЗ
|ИЗ
| &Данные КАК МоиДанные”;
Запрос.УстановитьПараметр(“Данные”, Источник[ТабЧасть.Имя].Выгрузить(, “Номенклатура, Цена”));
Запрос.Выполнить();
Запрос1 = Новый Запрос;
Запрос1.МенеджерВременныхТаблиц = Запрос.МенеджерВременныхТаблиц;
Запрос1.Текст = “ВЫБРАТЬ
| ПоступлениеТоваровИУслугТовары.Ссылка КАК Документ,
| ТЗ.Номенклатура,
| ТЗ.Цена,
| ПоступлениеТоваровИУслугТовары.Цена КАК ЦенаСтарая
|ИЗ
| ТЗ КАК ТЗ
| ВНУТРЕННЕЕ СОЕДИНЕНИЕ &Документ КАК ПоступлениеТоваровИУслугТовары
| ПО ТЗ.Номенклатура = ПоступлениеТоваровИУслугТовары.Номенклатура
|ГДЕ
| ПоступлениеТоваровИУслугТовары.Ссылка = &Ссылка
| И ТЗ.Цена <> ПоступлениеТоваровИУслугТовары.Цена”;
СтрокаЗамены = “Документ.” + МетаданныеДокумента.Имя + “.” + ТабЧасть.Имя;
Запрос1.Текст = СтрЗаменить(Запрос1.Текст, “&Документ”, СтрокаЗамены);
Запрос1.УстановитьПараметр(“Ссылка”, Ссылка);
Результат = Запрос1.Выполнить().Выгрузить();
Данные = ЗначениеВСтрокуВнутр(Результат);
ЗаписьЖурналаРегистрации(“Изменение цены”, УровеньЖурналаРегистрации.Информация,
Метаданные.Документы.ПоступлениеТоваровИУслуг, Ссылка, Данные, РежимТранзакцииЗаписиЖурналаРегистрации.Транзакционная);
КонецЦикла;
КонецЕсли;
КонецПроцедуры
</cod>
Кстати, ЗначениеВСтрокуВнутр я позаимствовал тут в комментарии у коллеги, спасибо большое, а то не знал как выпутаться и содержать данные в журнале.
Вторая часть у меня не важная, не успевал доработать по срокам, но приведу пример кода отчета на СКД.
<cod>
&НаКлиенте
Процедура ВыполнитьОтчет(Команда)
ВыполнитьНаСервере();
КонецПроцедуры
&НаСервере
Процедура ВыполнитьНаСервере()
Таблица = Новый ТаблицаЗначений;
ВыгрузитьЖурналРегистрации(Таблица, Новый Структура(“Событие”, “Изменение цены”), “Дата,ИмяПользователя,Комментарий”);
ТаблицаДанных = Новый ТаблицаЗначений;
ТаблицаДанных.Колонки.Добавить(“Дата”);
ТаблицаДанных.Колонки.Добавить(“Пользователь”);
ТаблицаДанных.Колонки.Добавить(“Документ”);
ТаблицаДанных.Колонки.Добавить(“Номенклатура”);
ТаблицаДанных.Колонки.Добавить(“Цена”);
ТаблицаДанных.Колонки.Добавить(“ЦенаСтарая”);
Для Каждого Строка Из Таблица Цикл
Попытка
ТабЗН = ЗначениеИзСтрокиВнутр(Строка.Комментарий);
Исключение
Продолжить;
КонецПопытки;
Для Каждого СтрокаТабЗН Из ТабЗН Цикл
НоваяСтрока = ТаблицаДанных.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, Строка);
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТабЗН);
НоваяСтрока.Пользователь = Строка.ИмяПОльзователя;
КонецЦикла;
КонецЦикла;
ОтчетОбъект = ДанныеФормыВЗначение(Отчет, Тип(“ОтчетОбъект.Отчет1”));
СхемаКомпоновкиДанных = ОтчетОбъект.ПолучитьМакет(“ОсновнаяСхемаКомпоновкиДанных”);
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Отчет.КомпоновщикНастроек.Настройки);
ВнешнийНаборДанных = Новый Структура;
ВнешнийНаборДанных.Вставить(“ТаблицаДанных”, ТаблицаДанных);
ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, ВнешнийНаборДанных);
Результат.Очистить();
ДокументРезультат = Результат;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных);
КонецПроцедуры
</cod>
Отчет работает, но без фильтров и отборов.
Задание выполнил.
Так как требуется по заданию выполнять поверку не в одном определенном документе, а может в нескоьлких, то я решил сделать новую подписку на события. Объекты указал документы, а событие указал ПередЗаписью. Создал в общем модуле процедуру, которая и регистрирует изменения цены пользователем в журнале регистраций. Коротко поясню. Перед записью проверяем документ на то, что он был проведен и он модифицирован, далее проверяем все его таб. части на наличие реквизита Номенклатура и цена, так как документ может и не содержать таб. частей. Если есть и цена отличается от того, что было в проведенном ранее документе, то регистрирую это изменение. Внизу приведен код:
<cod>
Процедура ИзменениеЦеныПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт Ссылка = Источник.Ссылка; Если Ссылка.Проведен И Источник.Модифицированность() Тогда МетаданныеДокумента = Ссылка.Метаданные(); Для Каждого ТабЧасть Из МетаданныеДокумента.ТабличныеЧасти Цикл Если ТабЧасть.Реквизиты.Найти(“Номенклатура”)=Неопределено ИЛИ ТабЧасть.Реквизиты.Найти(“Цена”)=Неопределено Тогда Продолжить; КонецЕсли; Запрос = Новый Запрос; Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц; Запрос.Текст = “ВЫБРАТЬ | * Поместить ТЗ |ИЗ | &Данные КАК МоиДанные”; Запрос.УстановитьПараметр(“Данные”, Источник[ТабЧасть.Имя].Выгрузить(, “Номенклатура, Цена”)); Запрос.Выполнить(); Запрос1 = Новый Запрос; Запрос1.МенеджерВременныхТаблиц = Запрос.МенеджерВременныхТаблиц; Запрос1.Текст = “ВЫБРАТЬ | ПоступлениеТоваровИУслугТовары.Ссылка КАК Документ, | ТЗ.Номенклатура, | ТЗ.Цена, | ПоступлениеТоваровИУслугТовары.Цена КАК ЦенаСтарая |ИЗ | ТЗ КАК ТЗ | ВНУТРЕННЕЕ СОЕДИНЕНИЕ &Документ КАК ПоступлениеТоваровИУслугТовары | ПО ТЗ.Номенклатура = ПоступлениеТоваровИУслугТовары.Номенклатура |ГДЕ | ПоступлениеТоваровИУслугТовары.Ссылка = &Ссылка | И ТЗ.Цена <> ПоступлениеТоваровИУслугТовары.Цена”; СтрокаЗамены = “Документ.” + МетаданныеДокумента.Имя + “.” + ТабЧасть.Имя; Запрос1.Текст = СтрЗаменить(Запрос1.Текст, “&Документ”, СтрокаЗамены); Запрос1.УстановитьПараметр(“Ссылка”, Ссылка); Результат = Запрос1.Выполнить().Выгрузить(); Данные = ЗначениеВСтрокуВнутр(Результат); ЗаписьЖурналаРегистрации(“Изменение цены”, УровеньЖурналаРегистрации.Информация, Метаданные.Документы.ПоступлениеТоваровИУслуг, Ссылка, Данные, РежимТранзакцииЗаписиЖурналаРегистрации.Транзакционная);
КонецЦикла; КонецЕсли;
КонецПроцедуры
</cod>
Кстати, ЗначениеВСтрокуВнутр я позаимствовал тут в комментарии у коллеги, спасибо большое, а то не знал как выпутаться и содержать данные в журнале.
Вторая часть у меня не важная, не успевал доработать по срокам, но приведу пример кода отчета на СКД.
<cod>
&НаКлиенте
Процедура ВыполнитьОтчет(Команда) ВыполнитьНаСервере();
КонецПроцедуры
&НаСервере
Процедура ВыполнитьНаСервере() Таблица = Новый ТаблицаЗначений; ВыгрузитьЖурналРегистрации(Таблица, Новый Структура(“Событие”, “Изменение цены”), “Дата,ИмяПользователя,Комментарий”); ТаблицаДанных = Новый ТаблицаЗначений; ТаблицаДанных.Колонки.Добавить(“Дата”); ТаблицаДанных.Колонки.Добавить(“Пользователь”); ТаблицаДанных.Колонки.Добавить(“Документ”); ТаблицаДанных.Колонки.Добавить(“Номенклатура”); ТаблицаДанных.Колонки.Добавить(“Цена”); ТаблицаДанных.Колонки.Добавить(“ЦенаСтарая”); Для Каждого Строка Из Таблица Цикл Попытка ТабЗН = ЗначениеИзСтрокиВнутр(Строка.Комментарий); Исключение Продолжить; КонецПопытки; Для Каждого СтрокаТабЗН Из ТабЗН Цикл НоваяСтрока = ТаблицаДанных.Добавить(); ЗаполнитьЗначенияСвойств(НоваяСтрока, Строка); ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТабЗН); НоваяСтрока.Пользователь = Строка.ИмяПОльзователя; КонецЦикла; КонецЦикла; ОтчетОбъект = ДанныеФормыВЗначение(Отчет, Тип(“ОтчетОбъект.Отчет1”)); СхемаКомпоновкиДанных = ОтчетОбъект.ПолучитьМакет(“ОсновнаяСхемаКомпоновкиДанных”); КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных; МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Отчет.КомпоновщикНастроек.Настройки); ВнешнийНаборДанных = Новый Структура; ВнешнийНаборДанных.Вставить(“ТаблицаДанных”, ТаблицаДанных); ПроцессорКомпоновкиДанных = Новый ПроцессорКомпоновкиДанных; ПроцессорКомпоновкиДанных.Инициализировать(МакетКомпоновки, ВнешнийНаборДанных); Результат.Очистить(); ДокументРезультат = Результат; ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент; ПроцессорВывода.УстановитьДокумент(ДокументРезультат); ПроцессорВывода.Вывести(ПроцессорКомпоновкиДанных); КонецПроцедуры
</cod>
Отчет работает, но без фильтров и отборов.
Задание выполнено.
Для универсальности создал Подписку на событие ПередЗаписью с Источником ДокументОбъект. В общем модуле в обработчике этого события в случае если режим – проведение, Источник проведен и у док-та есть табчасти с реквизитами Номенклатура, Цена делаю проверку. Ну и ЗаписьЖуранлаРегистрации в случае отличия цены номенклатуры Ссылки от Источника.
С отчетом проблем не возникло. ВыгрузитьЖурналРегистрации с соответствующим фильтром по событию.
Домашнее задание выполнено. Изменение цены отслеживается в событии
“ПередЗаписью” для документов поступления и реализации.
Осуществляется чтение табличной части из БД с помощью запроса,
после чего данные из БД сравниваются с данными, введеными
пользователем. Если в какой-либо строке цена была изменена и
документ при этом был проведен, то добавляется запись в журнал
регистрации с указанием текущего документа, ссылки на
номенклатуру, новой и старой цены. Отчет был создан без
использования СКД, путем получения таблицы значений с помощью
процедуры “ВыгрузитьЖурналРегистрации”.
Домашнее задание выполнено. Изменение цены отслеживается в событии
“ПередЗаписью” для документов поступления и реализации.
Осуществляется чтение табличной части из БД с помощью запроса,
после чего данные из БД сравниваются с данными, введеными
пользователем. Если в какой-либо строке цена была изменена и
документ при этом был проведен, то добавляется запись в журнал
регистрации с указанием текущего документа, ссылки на
номенклатуру, новой и старой цены. Отчет был создан без
использования СКД, путем получения таблицы значений с помощью
процедуры “ВыгрузитьЖурналРегистрации”.
Задание выполнено.
В общем модуле реализована процедура,
осуществляющая запись в журнал регистрации
событий изменения цены в документах поступления
и реализации товаров. Процедура вызывается в событии “ПередЗаписью”
для возможности выявления старой и новой цены номенклатуры.
Запись информации в журнал регистрации осуществляется
с помощью функции “ЗаписьЖурналаРегистрации”.
Отчет по событиям изменения цены реализован с помощью СКД.
Таблица значений, полученная с помощью функции
“ВыгрузитьЖурналРегистрации” с фильтром по необходимым событиям,
используется в качестве источника данных СКД.
Задание выполнил.
Не без проблем, но всё решил.
Задание выполнила. Изменение цены фиксирую в журнал через ЗаписьЖурналаРегистрации,где данные это структура
СтруктураДанных = Новый Структура(“Документ, Номенклатура, СтараяЦена, НоваяЦена”, Док, Номенклатура, СтараяЦена, Цена).
ЗаписьЖурналаРегистрации(“ИзменениеЦены”, , Док.Метаданные(), ЗначениеВСтрокуВнутр(СтруктураДанных), “Изменение цены”).
Для получения старой цены читаю объект из базы и ищу нужный товар.
Для отчета выгружаю данные из журнала регистрации по фильтру события в таблицу значений, потом преобразовываю структуру данных в каждой строке, извлекая нужное и на выходе получаю таблицу вида (Пользователь, Документ, Номенклатура, СтараяЦена, НоваяЦена), по ней строю отчет через табличный документ(как в СКД передать таблицу в виде источника данных не разобралась). Считаю метод решения явно не самый оптимальный по производительности :)
>как в СКД передать таблицу в виде источника данных не разобралась
Это мы будем делать во втором блоке.
При скачивании одним файлом 0 блока, обрывается закачка. Пишет что ошибка. При длине 1.2 Гб качается 1Гб и рвется. Посмотрите пожалуйста. Спасибо. Качал и с работы и с дома, разными браузерами. Результат одинаков.
Проверим.
У Вас еще нет физической поставки?
Есть, но хотелось бы последний вариант.
В физической поставке последний вариант.
Задание выполнено, но не таким образом как мне хотелось бы. Изначально я планировал делать одну запись в журнале регистрации на каждый документ, где в параметре “Данные” указывать всю информацию о товарах и ценах. Но поле “Данные” почему-то все время имеет тип “Неопределено”. Я пробовал передавать туда структуру, таблицу значений, массив, список значений – результат одинаковый. Только если передать ссылку или примитивный тип данных, то оно заполняется.
Поэтому сделал так – на каждое изменение цены делается отдельная запись ЖР, причем в данные идет ссылка на документ, а в комментарии текстом пишу какой товар был изменен и значения цен до и после изменения.
Сам факт изменения цен и формирование записи ЖР определяется в обработчике “ПередЗаписью” при помощи запроса с использованием временной таблицы.
Отчет по изменениям также сделан без применения СКД, как ее тут использовать не совсем понятно.
Т.о. задание полностью выполнено, но жду правильного решения. :-)
Задание выполнено. Сложностей не возникло, т.к. в главе 5 все подробно расписано
Где можно скачать эту конфигурацию?
В меню сайта открываете «Продвинутый курс – Материалы курса», находите нулевой блок.
Конфигурацию скачиваете там же..
Добрый день!
Где можно посмотреть актуальную версию уроков нулевого блока? а также файл со слайдами и базой, с примерами этого блока?
В меню сайта открываете “Продвинутый курс – Материалы курса”, находите нулевой блок.
Конфигурацию скачиваете там же.
Так и делал, но доступа не было к этим материалам!)
сейчас все ок, спасибо!)
ок!
Здравствуйте.
Представьте план-график прохождения курса, как для базового делали. Очень удобно.
Добрый день!
Готово, скачайте новую версию “Просмотр курсов”.
PS. План-график продвинутого курса находится в конфигурации “Просмотр курсов”.