Продвинутый курс. Домашнее задание №12
Эта запись посвящена второму потоку продвинутого курса по программированию.
Для выполнения рекомендуется изучить следующие главы 2-го блока.
Глава 3. Агрегаты
Глава 4. Запросы к регистрам
Глава 5. Блокировка данных
Глава 6. Последовательности
Глава 7. Складской учет
— залогиньтесь.
Если не активировали токен — посмотрите видео-инструкцию (видео N5)
Если вы залогинены, у Вас активирован токен доступа, но вы все равно видите эту запись —
напишите нам на e-mail поддержки.
Задание выполнил. Нечасто в практической работе применю блокировку данных, так что здесь пришлось подумать.
Задание выполнил.
Добавил в конфигурацию документ Заказ и регистр накопления ЗарезервированныйТовар вида Остатки с измерениями Номенклатура, Заказ (тип ДокументСсылка.Заказ) и ресурсом Количество. Режим блокировки управляемый. Регистраторами нового регистра являются документы Заказ и РеализацияТоваровИУслуг. В табличную чать Товары документа РеализацияТоваровИУслуг добавлен реквизит Заказ (тип ДокументСсылка.Заказ). У документа Заказ свойство «Удаление движений» принимает значение «Удалять автоматически при отмене проведения», а свойство «Запись движений при проведении» – «Записывать выбранные».
При проведении, документ Заказ создает «приходные» движения в регистре ЗарезервированныйТовар, а документ РеализацияТоваровИУслуг – «расходные». При этом остаток по номенклатуре в регистре ЗарезервированныйТовар не может превышать остатка по этой же номенклатуре в регистре ОстаткиТоваров. Для блокировки регистра ЗарезервированныйТовар при проведении документов, используется свойство БлокироватьДляИзменения набора записей регистра накопления (присваивается значение Истина).
Текст модуля объекта документа Заказ:
<code>
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
НаборДвижений = Движения.ЗарезервированныйТовар;
НаборДвижений.БлокироватьДляИзменения = Истина;
НаборДвижений.Очистить();
Для каждого ТекСтрока Из Товары Цикл
НоваяЗапись = НаборДвижений.Добавить();
НоваяЗапись.ВидДвижения = ВидДвиженияНакопления.Приход;
НоваяЗапись.Период = ЭтотОбъект.Дата;
НоваяЗапись.Номенклатура = ТекСтрока.Номенклатура;
НоваяЗапись.Заказ = ЭтотОбъект.Ссылка;
НоваяЗапись.Количество = ТекСтрока.Количество;
КонецЦикла;
НаборДвижений.Записать();
Запрос = Новый Запрос;
Запрос.Текст =
“ВЫБРАТЬ
| ЗаказТовары.Номенклатура,
| СУММА(ЗаказТовары.Количество) КАК Количество,
| МИНИМУМ(ЗаказТовары.НомерСтроки) КАК НомерСтроки
|ПОМЕСТИТЬ Товар
|ИЗ
| Документ.Заказ.Товары КАК ЗаказТовары
|ГДЕ
| ЗаказТовары.Ссылка = &Ссылка
|
|СГРУППИРОВАТЬ ПО
| ЗаказТовары.Номенклатура
|
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Товар.Номенклатура,
| Товар.НомерСтроки,
| ЕСТЬNULL(ОстаткиТоваровОстатки.КоличествоОстаток, 0) – ЕСТЬNULL(ЗарезервированныйТоварОстатки.КоличествоОстаток, 0) КАК СвободныйОстаток
|ИЗ
| Товар КАК Товар
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ЗарезервированныйТовар.Остатки(
| ,
| Номенклатура В
| (ВЫБРАТЬ
| Товар.Номенклатура
| ИЗ
| Товар КАК Товар)) КАК ЗарезервированныйТоварОстатки
| ПО Товар.Номенклатура = ЗарезервированныйТоварОстатки.Номенклатура
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиТоваров.Остатки(
| ,
| Номенклатура В
| (ВЫБРАТЬ
| Товар.Номенклатура
| ИЗ
| Товар КАК Товар)) КАК ОстаткиТоваровОстатки
| ПО Товар.Номенклатура = ОстаткиТоваровОстатки.Номенклатура
|ГДЕ
| ЕСТЬNULL(ОстаткиТоваровОстатки.КоличествоОстаток, 0) – ЕСТЬNULL(ЗарезервированныйТоварОстатки.КоличествоОстаток, 0) < 0”;
Запрос.УстановитьПараметр(“Ссылка”, Ссылка);
Результат = Запрос.Выполнить();
Если НЕ Результат.Пустой() Тогда
Отказ = Истина;
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = “Не хватает свободного остатка по номенклатуре ” + ВыборкаДетальныеЗаписи.Номенклатура + ” в количестве ” + (-ВыборкаДетальныеЗаписи.СвободныйОстаток);
Сообщение.Поле = “Товары[” + (ВыборкаДетальныеЗаписи.НомерСтроки – 1) + “].Количество”;
Сообщение.УстановитьДанные(ЭтотОбъект);
Сообщение.Сообщить();
КонецЦикла;
КонецЕсли;
КонецПроцедуры
</code>
При проведении документа РеализацияТоваровИУслуг сначала выполняются движения по регистру ЗарезервированныйТовар (при этом контролируются остатки по номенклатуре в разрезе заказов), затем по регистру ОстаткиТоваров (при этом контролируется «свободный», не зарезервированный остаток).
Были созданы подписки на события ПодпискаНаСобытиеПередЗаписьюРегистраЗарезервированныйТовар и ПодпискаНаСобытиеПриЗаписиРегистраЗарезервированныйТовар, обработчик подписки ПодпискаНаСобытиеПриЗаписьюРегистраОстатки был модифицирован с учетом требования контроля «свободного »остатка. Текст обработчиков созданных подписок:
<code>
Процедура ПодпискаНаСобытиеПередЗаписьюРегистраЗарезервированныйТоварПередЗаписью(Источник, Отказ, Замещение) Экспорт
Перем МенеджерВТ, ЭтоНовый;
ДопСвойства = Источник.ДополнительныеСвойства;
ВыполнятьКонтрольОстатков = Истина;
ДопСвойства.Свойство(“ВыполнятьКонтрольОстатков”, ВыполнятьКонтрольОстатков);
Если ВыполнятьКонтрольОстатков = Истина Тогда
Если НЕ ДопСвойства.Свойство(“МенеджерВТ”, МенеджерВТ) Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = “Не определен менеджер временных таблиц. Проведение докумнета невозможно!”;
Сообщение.Сообщить();
Отказ = Истина;
Возврат;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
ДопСвойства.Свойство(“ЭтоНовый”, ЭтоНовый);
Если ЭтоНовый = Истина Тогда
Запрос.Текст =
“ВЫБРАТЬ
| 1 КАК Номенклатура,
| 2 КАК Заказ,
| 3 КАК Количество
|ПОМЕСТИТЬ ПрошлоеСостояниеДокументаРезервы
|ГДЕ
| 1 = 2”;
Иначе
Запрос.Текст =
“ВЫБРАТЬ
| Резервы.Номенклатура,
| Резервы.Заказ,
| Резервы.Количество
|ПОМЕСТИТЬ ПрошлоеСостояниеДокументаРезервы
|ИЗ
| РегистрНакопления.ЗарезервированныйТовар КАК Резервы
|ГДЕ
| Резервы.Регистратор = &Регистратор
| И Резервы.Заказ <> ЗНАЧЕНИЕ(Документ.Заказ.ПустаяСсылка)
| И Резервы.Заказ ЕСТЬ НЕ NULL “;
Запрос.УстановитьПараметр(“Регистратор”, Источник.Отбор.Регистратор.Значение);
КонецЕсли;
Запрос.Выполнить();
КонецЕсли;
КонецПроцедуры
Процедура ПодпискаНаСобытиеПриЗаписиРегистраЗарезервированныйТоварПриЗаписи(Источник, Отказ, Замещение) Экспорт
ДопСвойства = Источник.ДополнительныеСвойства;
ВыполнятьКонтрольОстатков = Ложь;
ДопСвойства.Свойство(“ВыполнятьКонтрольОстатков”, ВыполнятьКонтрольОстатков);
Если ВыполнятьКонтрольОстатков = Истина Тогда
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = ДопСвойства.МенеджерВТ;
Запрос.Текст =
“ВЫБРАТЬ
| ЗарезервированныйТовар.Номенклатура,
| ЗарезервированныйТовар.Заказ,
| ЗарезервированныйТовар.Количество
|ПОМЕСТИТЬ ТекущееСостояниеДокумента
|ИЗ
| РегистрНакопления.ЗарезервированныйТовар КАК ЗарезервированныйТовар
|ГДЕ
| ЗарезервированныйТовар.Регистратор = &Регистратор
| И ЗарезервированныйТовар.Заказ <> ЗНАЧЕНИЕ(Документ.Заказ.ПустаяСсылка)
| И ЗарезервированныйТовар.Заказ ЕСТЬ НЕ NULL
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ТекущееСостояниеДокумента.Номенклатура,
| ТекущееСостояниеДокумента.Заказ
|ПОМЕСТИТЬ ИзмененияДокумента
|ИЗ
| ТекущееСостояниеДокумента КАК ТекущееСостояниеДокумента
| ЛЕВОЕ СОЕДИНЕНИЕ ПрошлоеСостояниеДокументаРезервы КАК ПрошлоеСостояниеДокумента
| ПО ТекущееСостояниеДокумента.Номенклатура = ПрошлоеСостояниеДокумента.Номенклатура
| И ТекущееСостояниеДокумента.Заказ = ПрошлоеСостояниеДокумента.Заказ
|ГДЕ
| ТекущееСостояниеДокумента.Количество <> ЕСТЬNULL(ПрошлоеСостояниеДокумента.Количество, 0)
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ЗарезервированныйТоварОстатки.Номенклатура,
| ЗарезервированныйТоварОстатки.Заказ,
| ЗарезервированныйТоварОстатки.КоличествоОстаток,
| МИНИМУМ(ДокументыТовары.НомерСтроки) КАК НомерСтроки
|ИЗ
| РегистрНакопления.ЗарезервированныйТовар.Остатки(
| &МоментВремени,
| Номенклатура В
| (ВЫБРАТЬ
| ИзмененияДокумента.Номенклатура
| ИЗ
| ИзмененияДокумента КАК ИзмененияДокумента)
| И
| Заказ В
| (ВЫБРАТЬ
| ИзмененияДокумента.Заказ
| ИЗ
| ИзмененияДокумента КАК ИзмененияДокумента)
| ) КАК ЗарезервированныйТоварОстатки
| ЛЕВОЕ СОЕДИНЕНИЕ ДокументТоварыПараметр КАК ДокументыТовары
| ПО ЗарезервированныйТоварОстатки.Номенклатура = ДокументыТовары.Номенклатура
| И ЗарезервированныйТоварОстатки.Заказ = ДокументыТовары.Заказ
|ГДЕ
| ЗарезервированныйТоварОстатки.КоличествоОстаток < 0
|
|СГРУППИРОВАТЬ ПО
| ЗарезервированныйТоварОстатки.Номенклатура,
| ЗарезервированныйТоварОстатки.КоличествоОстаток,
| ЗарезервированныйТоварОстатки.Заказ
|;
|////////////////////////////////////////////////////////////////////////////////
|УНИЧТОЖИТЬ ТекущееСостояниеДокумента
|;
|
|////////////////////////////////////////////////////////////////////////////////
|УНИЧТОЖИТЬ ИзмененияДокумента”;
Регистратор = Источник.Отбор.Регистратор.Значение;
Запрос.Текст = СтрЗаменить(Запрос.Текст, “ДокументТоварыПараметр”, “Документ.”+Регистратор.Метаданные().Имя+”.Товары”);
Запрос.УстановитьПараметр(“Регистратор”, Регистратор);
Запрос.УстановитьПараметр(“МоментВремени”, Новый Граница(Регистратор.МоментВремени(), ВидГраницы.Включая));
РезультатЗапроса = Запрос.Выполнить();
Если НЕ РезультатЗапроса.Пустой() Тогда
Отказ = Истина;
ВыборкаНехватка = Запрос.Выполнить().Выбрать();
Пока ВыборкаНехватка.Следующий() Цикл
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = “Нехватка номенклатуры “+ВыборкаНехватка.Номенклатура + ” по заказу” + ВыборкаНехватка.Заказ +” в количестве “+(-ВыборкаНехватка.КоличествоОстаток);
Сообщение.Поле = “Товары[“+(ВыборкаНехватка.НомерСтроки-1)+”].Количество”;
Сообщение.УстановитьДанные(ДопСвойства.ДокументОбъект);
Сообщение.Сообщить();
КонецЦикла;
КонецЕсли;
ДопСвойства.МенеджерВТ.Закрыть();
КонецЕсли;
КонецПроцедуры
</code>
Задание выполнил. Создал регистр “ЗаказыПокупателей” (Измерения- номенклатура, документ “Заказ”). При проведении документа “Заказ” списываем номенклатуру с “Остатки” и ставим на “ЗаказыПокупателей”. Контроль остатоков по регистру “ЗаказыПокупателей” (расход по которому делает “РеализацияТоваровУслуг”) анналогичный контролю “Остатки” (только еще учитывается дополнительное измерение “Заказ”).
1.Взагрузил ИБ предыдущей задачи. Сделал регистр “Заказы покупателей”(измерения: номенклатура, номер заказа; ресурс кол-во) и документ “Заказ покупателя” . При проведении документа “Заказ покупателя” производится списание данных с регитсра “Остатки” и зачисление на регистр “Заказы покупателей”. В процедуру проведения установил контролль остаков по новой методе (перед фиксацией транзакции).
2.Т.к. один документ может использовать несколько заказов в табличную часть “Товары” документа “Реализация Товаров и Услуг” добавил реквизит “НомерЗаказ”.
3.В модуле документа “Реализация товаров и услуг” модифицировал списание т.о. что строки с указаным заказом списываются из регистра “Заказы покупателей”, а без указания заказа из рагитсра “Остатки”. Сдедлал 2 новых подписки (“ПередЗаписью” и “ПриЗаписи”) на регистр “Заказы покупателей”. Аналогичные подписки по регистру “Остатки” модифицировал т.о. что-бы они работали толлько по номенклатуре без указания заказа.
Потренироваться в тестировании блокировок удаётся только умозрительно т.к. дома 1с только файловая.
В план-графике названия глав 3-7 блока 2 не соответствуют тому как они указаны в учебной конф. и в заголовке этой стринички.
Будем исправлять план-график.
ДЗ Выполнено.
Добавил новый документ ЗаказПокупателя и регистр накопления РезервыТоваров (регистраторы Заказ и Реализация). Модифицировал обработку заполнения Реализации по Заказу.
В качестве допущения принял, что заказ покупателя списывает товар из регистра ОстаткиТоваров и делает приход по регистру РезервыТоваров.
Модифицировал подписки на события из прошлого ДЗ. Вместо параметра ТоварыДляКонтроля сделал два: ТоварыДляКонтроляОстатков и ТоварыДляКонтроляРезервов.
Соответственно при проведении Заказа проверяю только остатки, при проведении Реализации и остатки и резервы в зависимости от переданных параметров.
Т.к. мы используем новую технологию проведения – сначала запись, потом чтение – то для реализации корректной работы во многопользовательской среде можем использовать новое свойство набора записей регистров накопления – БлокироватьДляИзменения, для автоматического наложения блокировок в транзакции проведения.
Задание выполнено.
Создал документ ЗаказПокупателя с табличной частью Товары.
Создал РН остатков ТоварыВРезерве, измерения – Номенклатура, Заказ. Ресурс – Количество. Указал регистраторы для этого регистра. Документ ЗаказПокупателя выполняет приход по РН ТоварыВРезерве.
В табличную часть документа РеализацияТоваровИУслуг добавил реквизит Заказ (ссылка на документ ЗаказПокупателя). Модифицировал контроль остатков сделанный в ДЗ№ 11. Внес измерения в обработку проведения документа РеализацияТоваровИУслуг, где расход по РН ОстаткиТоваров формируется по строке с незаполненным реквизитом Заказ, а расход по РН ТоварыВРезерве по строке с заполненным реквизитом Заказ. Контроль отрицательных остатков реализовал в подписке на событие ОбработкаПроведения() для документа РеализацияТоваровИУслуг. Для этого контроль пришлось разбить на два этапа, собирая на первом этапе количество товара в резерве по РН ТоварыВРезерве, для того, чтобы затем определить свободный остаток по РН Остатки с учетом зарезервированного.
Т.к. проверка остатков выполняется после записи движений, то для того, чтобы обеспечить корректную работу в клиент-серверном режиме, накладывал блокировку при записи движения с установкой свойства БлокироватьДляИзменения, а потом уже проверял остатки. Насколько я понял из видео-уроков это свойство обеспечивает блокировку в регистре по тем комбинациям измерений, которые записываются в наборе записей. И если нужно заблокировать именно те комбинации, по которым записываются записи, то лучше использовать это свойство (вместо объекта БлокировкаДанных). Т.к. не нужно формировать состав блокировки, то свойство БлокироватьДляИзменения сокращает код и уменьшает количество действий платформы.
Задание сделал.
Создал документ ЗаказПокупателя со структурой документа реализации и включил его в подписки ПередЗаписью и ПриПроведении, созданные в прошлом задании. В табличную часть реализации добавил реквизит ЗаказПокупателя. Создал РН РезервыТоваров вида остатки с измерениями Номенклатура, Заказ и ресурсом Количество. Указал соотв.регистраторы для регистров РезервыТоваров и Остатки. Скорректировал процедуру контроля остатков из подписки при проведении.
Для документа реализации для строк с заполненным заказом делается движение по регистру РезервыТоваров, иначе – по регистру Остатки. Далее проверяю объединенным запросом по двум регистрам наличие отрицательных остатков.
Для документа ЗаказПокупателя делаются расходные движения по регистру Остатки и приходные – по регистру РезервыТоваров, далее
запросом по регистру Остатки производится контроль остатков.
Для корректной работы нескольких пользователей одновременно устанавливал перед записью движений вида расход свойство набора записей БлокироватьДляИзменения в истину.
Общая схема решения будет следующей. Документ «Заказ покупателя» будет делать движения приход по регистру накопления «Резервы товаров». В документе реализация контроль будет реализован в два этапа. На первом этапе анализируются строки табличной части «Товары» в которых заполнен реквизит «Заказ покупателя». При этом сначала делаются движения по расходу в регистре накопления «Резервы товаров», а затем осуществляется контроль отрицательных остатков, т.е. контроль реализуется по новой схеме. На втором этапе анализу подвергаются строки табличной части с пустым реквизитом «Заказ покупателя», контроль осуществляется по наличию свободного остатка, который вычисляется как разница между общим количестве на остатке и количество зарезервированного товара. В этом случае контроль остаток осуществляется по старой классической схеме, поскольку нехватка свободного количества не означает отрицательного остатка по регистру «Остатки товаров».
Данную схему я и реализовал, создал документ «Заказ покупателя» с табличной частью «Товары», регистр накопления «Резервы товаров» с измерениями «Заказ покупателя» и «Номенклатура» и одним ресурсом «Количество». В документ «Реализация» добавил в табличную часть «Товары» реквизит «Заказ покупателя». Внес необходимые изменения в модуль проведения документа «Реализация», контроль остатков по регистру «Резервы товаров», реализовал в подписке на события «При записи», источником для которого являлся этот регистр. Контроль свободного остатка осуществлял в процедуре «Обработка проведения».
Для корректной работы конфигурации в клиент-серверном варианте, реализовал управление блокировками, для этого пришлось разрывать тексты запросов, после считывания данных и накладывать блокировки до проверки остатков. Это проделал с помощью менеджера временных таблиц.
А что за глава “Глава 3. Особенные свойства регистров” ? В списке такой нет. Третья глава называется “Агрегаты”
Спасибо за информацию, исправлено.