Тренинг по подготовке к аттестации.
Разбор задач 09, 10

Публикуем решения задач 9 “Интернет-магазин” и 10 “Пени”.

Предлагаю обсудить и покритиковать в комментариях мое решение ;)

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

Если не активировали токен — посмотрите видео-инструкцию (видео N5)

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

комментариев 10 на “Тренинг по подготовке к аттестации.
Разбор задач 09, 10”

  1. 1. Расскажите пожалуйста, почему РС СостояниеСчета периодический?
    Считтаю что можно было бы обойтись обычным.

    2. В структура РН ЗадолженностьПоОплате
    Вы добавили измерение Контрагент, хотел бы проконсультироваться
    по этому поводу, т.к. довольно часто такая ситуация возникает на практике.

    Плюсы и минусы Вы описали, объём базы или скорость запросов, но вот
    что ещё меня немного тревожит, может это параноя. :)
    При такой структуре регистра может сложиться следующая ситуация:
    Измерение Контрагент — Вася, Измерение Счет — Счет № 3.
    А реквизит Контрагент в Счете № 3 — Петя.

    Всегда ведь есть документ Корректировка регистра, или Операция.
    Насколько “весомы” мои опасения?
    Может дополнительная проверка в модуле регистра не так уж страшна. :)

    3. Разве пени “капитализируется”? Мне кажется пени начисляется только
    на сумму основного долга, без накопившихся процентов.
    Для решения, как вариант, в регистр ЗадолженностьПоОплате можно
    добавить ещё один ресурс, СуммаПени. И при поступлении денег
    погашать в первую очередь пени. Правда отчеты бы сложней пришлось
    формировать.

    Подскажите правильный вариант.

    • Простите за опечатки. Трудно набирать когда ваш волшебный плеер играет,
      экран не прорисовывается. :) 

      • А я и без плеера иногда умею здорово опечатываться :)

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

  2. Отправила отчеты по этой задаче на pavel@Spec8.ru
    Хотелось бы посмотреть правильное решение :)

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

  3. Денис Попов 30.04.2012 в 13:22

    Доработка Оперативного/НеОперативного проведения + Блокировки.
     Документ «РегистрацияЗаказаКлиента».
    Движения.СвободныеОстатки.БлокироватьДляИзменения = Истина;

    Если Режим = РежимПроведенияДокумента.Оперативный Тогда
       МоментИтогов = ‘00010101’;
    Иначе
       МоментИтогов = Новый Граница(МоментВремени(),ВидГраницы.Включая);
    КонецЕсли;
    Запрос.УстановитьПараметр(“МоментИтогов”,МоментИтогов);
     Документ «ВыдачаЗаказов».
    Запрос на получение данных разбил на два Запроса с подключением МенеджераВременныхТаблиц.
    В первый Запрос добавлено поле Склад (ТочкаВыдачи) через параметр.
    По результатам этого запроса устанавливается блокировка на Регистры ОстатковТоваров и СтоимостиТоваров.
    Во второй Запрос добавлен параметр «МоментИтогов» для реализации Оперативного/НеОперативного проведения. 
    Движения.ОстаткиТоваров.Очистить();
    Движения.СтоимостьТоваров.Очистить();
     Если РежимПроведения = РежимПроведенияДокумента.Оперативный Тогда
       Движения.ОстаткиТоваров.Записать();
       Движения.СтоимостьТоваров.Записать();
       МоментИтогов = ‘00010101’;
    Иначе
       МоментИтогов = Новый Граница(МоментВремени(), ВидГраницы.Исключая);
    КонецЕсли;
    Запрос.УстановитьПараметр(“МоментИтогов”, МоментИтогов);
    БлокировкаДанных = Новый БлокировкаДанных;
    ЭлементБлокировки = БлокировкаДанных.Добавить(“РегистрНакопления.ОстаткиТоваров”);
    ЭлементБлокировки.ИсточникДанных = ДанныеДляБлокировки;
    ЭлементБлокировки.ИспользоватьИзИсточникаДанных(“Склад”, “Склад”);
    ЭлементБлокировки.ИспользоватьИзИсточникаДанных(“Номенклатура”, “Номенклатура”);
    ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
    ЭлементБлокировки = БлокировкаДанных.Добавить(“РегистрНакопления.СтоимостьТоваров”);
    ЭлементБлокировки.ИсточникДанных = ДанныеДляБлокировки;
    ЭлементБлокировки.ИспользоватьИзИсточникаДанных(“Номенклатура”, “Номенклатура”);
    ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
    БлокировкаДанных.Заблокировать();
     Создание Отчетов
    С отчетами по Остаткам и по Продажам проблем не возникло.
    А вот с отчетом по Заказам в пути было не просто.
    Реализовал следующим образом:
    Никаких изменений в структуру регистров вносить не стал.
    В справочник Номенклатуры добавил два реквизита: Вес и Объем.
    Список заказов в пути получаю из СрезаПоследних регистра сведений.
    Присоединяю к нему данные табличной части Товары документа Заказов и сохраняю во временную таблицу.
    Затем во временную таблицу получаю данные по остаткам и стоимости товаров.
    В следующем запросе соединяю данные первой и второй временных таблиц и рассчитываю себестоимость.

  4. Денис Попов 30.04.2012 в 11:53

    Спасибо, Павел, за решение.
    Есть несколько вопросов.

    1. О выдаче товаров.
    Нет проверки на наличие данного заказа именно в этой точке выдачи. 
    В таком случае товар может спокойно уйти в минус на одном складе и остаться в плюсе на другом.

    2. Перемещение.
    На мой взгляд более верным будет формировать движения о Приеме товаров в событии ОбработкаПроведения, а не командой… в этом случае не будет проблем с многочисленным нажатием на эту кнопку, а также не будет проблем при простом перепроведении документа (в вашем случае движения по приему будут затерты).
    Можно добавить дополнительный реквизит “ДатаПриемаВТочкеВыдачи”. По этой дате и формировать движения о приеме. Если дата пуста – значит приема еще не было.

    3.  В общем.
    Не попали ли мы при таком решении (смущает частое получение данных не из Регистров, а из таблицы Документов) под ошибку: “Получение расчетных данных не из регистра…”: цена 3 балла?

    В любом случае вы потратили на эту задачу (если прибавить время на создание отчетов и включение блокировок) около 90 минут. Весьма похвально! 

    • 1. Согласен.
      2. Согласен. Но я не хотел регистрировать изменение самого документа.
      3. Неудачная задача, каюсь еще раз. Я ориентировался на ввод данных в документах на основании. Задача в более расширенном варианте функционирует в одном из реальных магазинов, но контроль заказов и остатков товаров почти полностью лежит на менеджерах, единственный момент это резервирование и контроль резервов автоматизирован. Но к сертификации это конечно не имеет отношения.

  5. Manase940N 28.04.2012 в 13:48

    День добрый! Решил описать блокировки и оперативное проведение документов для эталонного решения задания №9, чтобы получить доступ к бонусу :).
    В документе РегистрацияЗаказаКлиента модуль процедуры ОбработкаПроведения будет таким:
    <code>
     
    Процедура ОбработкаПроведения(Отказ, Режим)
                   
                    Движения.СвободныеОстатки.БлокироватьДляИзменения = Истина;
                   
                    Запрос = Новый Запрос;
                    Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
                    Запрос.Текст = “ВЫБРАТЬ
                                   |              РегистрацияЗаказаКлиентаСписокТоваров.Номенклатура КАК Номенклатура,
                                   |              СУММА(РегистрацияЗаказаКлиентаСписокТоваров.Количество) КАК Количество,
                                   |              СУММА(РегистрацияЗаказаКлиентаСписокТоваров.СуммаПродажи) КАК СуммаПродажи
                                   |ПОМЕСТИТЬ ДокТЧ
                                   |ИЗ
                                   |              Документ.РегистрацияЗаказаКлиента.СписокТоваров КАК РегистрацияЗаказаКлиентаСписокТоваров
                                   |ГДЕ
                                   |              РегистрацияЗаказаКлиентаСписокТоваров.Ссылка = &Ссылка
                                   |
                                   |СГРУППИРОВАТЬ ПО
                                   |              РегистрацияЗаказаКлиентаСписокТоваров.Номенклатура
                                   |
                                   |ИНДЕКСИРОВАТЬ ПО
                                   |              Номенклатура
                                   |;
                                   |
                                   |////////////////////////////////////////////////////////////////////////////////
                                   |ВЫБРАТЬ
                                   |              ДокТЧ.Номенклатура,
                                   |              ДокТЧ.Количество
                                   |ИЗ
                                   |              ДокТЧ КАК ДокТЧ”;
                    Запрос.УстановитьПараметр(“Ссылка”, Ссылка);
                    РезультатЗапроса = Запрос.Выполнить();
                   
                    Выборка = РезультатЗапроса.Выбрать();
                   
                    Движения.СвободныеОстатки.Записывать = Истина;
                    Пока Выборка.Следующий() Цикл
                                   Движение = Движения.СвободныеОстатки.Добавить();
                                   Движение.ВидДвижения = ВидДвиженияНакопления.Расход;
                                   Движение.Период = Дата;
                                   Движение.Номенклатура = Выборка.Номенклатура;
                                   Движение.Количество = Выборка.Количество;
                    КонецЦикла;
                   
                    Движения.Записать();
                   
        Запрос.Текст = “ВЫБРАТЬ
                       |          СвободныеОстаткиОстатки.Номенклатура.Представление,
                       |          СвободныеОстаткиОстатки.КоличествоОстаток
                       |ИЗ
                       |          РегистрНакопления.СвободныеОстатки.Остатки(
                       |                                         &МоментИтогов,
                       |                                         Номенклатура В
                       |                                                         (ВЫБРАТЬ
                       |                                                                         ДокТЧ.Номенклатура
                       |                                                         ИЗ
                       |                                                                         ДокТЧ КАК ДокТЧ)) КАК СвободныеОстаткиОстатки
                       |ГДЕ
                       |          СвободныеОстаткиОстатки.КоличествоОстаток < 0”;
     
                    Если Режим = РежимПроведенияДокумента.Оперативный Тогда
                                   МоментИтогов = Дата(‘00010101’);
                    Иначе
                                   МоментИтогов = Новый Граница(МоментВремени(), ВидГраницы.Включая);
                    КонецЕсли;
                    Запрос.УстановитьПараметр(“МоментИтогов”, МоментИтогов);
                   
                    РезультатЗапроса = Запрос.Выполнить();
                   
                    Если НЕ РезультатЗапроса.Пустой() Тогда
                                   Отказ = Истина;
                                  
                                   Выборка = РезультатЗапроса.Выбрать();
                                   Пока Выборка.Следующий() Цикл
                                                   Сообщение = Новый СообщениеПользователю;
                                                   Сообщение.Текст = “Товар: ” + Выборка.НоменклатураПредставление + “, нехватает: ” +
                                                                   (-Выборка.КоличествоОстаток);
                                                   Сообщение.Сообщить();                         
                                   КонецЦикла;
                    КонецЕсли;
                   
                   
                    Движения.СостояниеЗаказов.Записывать = Истина;
                   
                    Движение = Движения.СостояниеЗаказов.Добавить();
                    Движение.Период = Дата;
                    Движение.Заказ = Ссылка;
                    Движение.Состояние = Перечисления.СостоянияЗаказов.Новый;
                   
    КонецПроцедуры
    </code>
    В документе ВыдачаТоваров модуль процедуры ОбработкаПроведения будет таким:
    <code>
     
    Процедура ОбработкаПроведения(Отказ, РежимПроведения)
                   
                    Запрос = Новый Запрос;
                    Запрос.Текст = “ВЫБРАТЬ
                                   |              РегистрацияЗаказаКлиентаСписокТоваров.Номенклатура,
                                   |              СУММА(РегистрацияЗаказаКлиентаСписокТоваров.Количество) КАК Количество,
                                   |              СУММА(РегистрацияЗаказаКлиентаСписокТоваров.СуммаПродажи) КАК СуммаПродажи,
                                   |              ВыдачаЗаказовЗаказы.Заказ
                                   |ПОМЕСТИТЬ ОтгружаемыеТовары
                                   |ИЗ
                                   |              Документ.ВыдачаЗаказов.Заказы КАК ВыдачаЗаказовЗаказы
                                   |                              ЛЕВОЕ СОЕДИНЕНИЕ Документ.РегистрацияЗаказаКлиента.СписокТоваров КАК РегистрацияЗаказаКлиентаСписокТоваров
                                   |                              ПО ВыдачаЗаказовЗаказы.Заказ = РегистрацияЗаказаКлиентаСписокТоваров.Ссылка
                                   |ГДЕ
                                   |              ВыдачаЗаказовЗаказы.Ссылка = &Ссылка
                                   |
                                   |СГРУППИРОВАТЬ ПО
                                   |              РегистрацияЗаказаКлиентаСписокТоваров.Номенклатура,
                                   |              ВыдачаЗаказовЗаказы.Заказ
                                   |;
                                   |
                                   |////////////////////////////////////////////////////////////////////////////////
                                   |ВЫБРАТЬ
                                   |              ОтгружаемыеТовары.Номенклатура,
                                   |              ОтгружаемыеТовары.Количество,
                                   |              ОтгружаемыеТовары.СуммаПродажи КАК СуммаПродажи,
                                   |              ОстаткиТоваровОстатки.КоличествоОстаток,
                                   |              СтоимостьТоваровОстатки.СтоимостьОстаток,
                                   |              ОтгружаемыеТовары.Заказ КАК Заказ
                                   |ИЗ
                                   |              ОтгружаемыеТовары КАК ОтгружаемыеТовары
                                   |                              ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиТоваров.Остатки(
                                   |                                                             &МоментИтогов,
                                   |                                                             Номенклатура В
                                   |                                                                             (ВЫБРАТЬ
                                   |                                                                                            ОтгружаемыеТовары.Номенклатура
                                   |                                                                             ИЗ
                                   |                                                                                            ОтгружаемыеТовары КАК ОтгружаемыеТовары)) КАК ОстаткиТоваровОстатки
                                   |                              ПО ОтгружаемыеТовары.Номенклатура = ОстаткиТоваровОстатки.Номенклатура
                                   |                              ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.СтоимостьТоваров.Остатки(
                                   |                                                             &МоментИтогов,
                                   |                                                             Номенклатура В
                                   |                                                                             (ВЫБРАТЬ
                                   |                                                                                            ОтгружаемыеТовары.Номенклатура
                                   |                                                                             ИЗ
                                   |                                                                                            ОтгружаемыеТовары КАК ОтгружаемыеТовары)) КАК СтоимостьТоваровОстатки
                                   |                              ПО ОтгружаемыеТовары.Номенклатура = СтоимостьТоваровОстатки.Номенклатура
                                   |ИТОГИ
                                   |              СУММА(СуммаПродажи)
                                   |ПО
                                   |              ОБЩИЕ,
                                   |              Заказ”;
                                                                     
                    Если РежимПроведения = РежимПроведенияДокумента.Оперативный Тогда
                                   Движения.ОстаткиТоваров.Записывать = Истина;
                                   Движения.СтоимостьТоваров.Записывать = Истина;
                                   Движения.ОстаткиТоваров.Очистить();
                                   Движения.СтоимостьТоваров.Очистить();
                                   Движения.Записать();
                                   МоментИтогов = Дата(‘00010101’);
                    Иначе
                                   МоментИтогов = МоментВремени();
                    КонецЕсли;
                    Запрос.УстановитьПараметр(“МоментИтогов”, МоментИтогов);
     
                    Запрос.УстановитьПараметр(“Ссылка”, Ссылка);
                    РезультатЗапроса = Запрос.Выполнить();
                   
                    Движения.ОстаткиТоваров.Записывать = Истина;
                    Движения.СтоимостьТоваров.Записывать = Истина;
                    Движения.Продажи.Записывать = Истина;
                    Движения.СостояниеЗаказов.Записывать = Истина;
                   
                    Блокировка = Новый БлокировкаДанных;
                    ЭлементОстатки = Блокировка.Добавить(“РегистрНакопления.ОстаткиТоваров”);
                    ЭлементОстатки.ИсточникДанных = РезультатЗапроса;
                    ЭлементОстатки.ИспользоватьИзИсточникаДанных(“Номенклатура”, “Номенклатура”);
                    ЭлементОстатки.Режим = РежимБлокировкиДанных.Исключительный;
                    ЭлементСтоимость = Блокировка.Добавить(“РегистрНакопления.СтоимостьТоваров”);
                    ЭлементСтоимость.ИсточникДанных = РезультатЗапроса;
                    ЭлементСтоимость.ИспользоватьИзИсточникаДанных(“Номенклатура”, “Номенклатура”);
                    ЭлементСтоимость.Режим = РежимБлокировкиДанных.Исключительный;
                    Блокировка.Заблокировать();
     
                    СебестоимостьИтого = 0;
                    КолЗаказов = 0;
                   
                    ВыборкаОбщиеИтоги = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
                    Пока ВыборкаОбщиеИтоги.Следующий() Цикл
                                  
                                  
                                   ВыборкаИтоги = ВыборкаОбщиеИтоги.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
                                  
                                   Пока ВыборкаИтоги.Следующий() Цикл
                                                  
                                                   Выборка = ВыборкаИтоги.Выбрать();
                                                  
                                                   Пока Выборка.Следующий() Цикл
                                                                   Движение = Движения.ОстаткиТоваров.ДобавитьРасход();
                                                                   Движение.Период = Дата;
                                                                   Движение.Номенклатура = Выборка.Номенклатура;
                                                                   Движение.Склад = ТочкаВыдачи;
                                                                   Движение.Количество = Выборка.Количество;
                                                                  
                                                                  
                                                                   Движение = Движения.СтоимостьТоваров.ДобавитьРасход();
                                                                   Движение.Период = Дата;
                                                                   Движение.Номенклатура = Выборка.Номенклатура;
                                                                   Если Выборка.Количество = Выборка.КоличествоОстаток Тогда
                                                                                  Себестоимость = Выборка.СтоимостьОстаток;
                                                                   Иначе
                                                                                  Себестоимость = Выборка.Количество / Выборка.КоличествоОстаток * Выборка.СтоимостьОстаток;
                                                                   КонецЕсли;
                                                                   Движение.Стоимость = Себестоимость;
                                                                  
                                                                   СебестоимостьИтого = СебестоимостьИтого + Себестоимость;
                                                                  
                                                   КонецЦикла; 
                                                  
                                                   Движение = Движения.СостояниеЗаказов.Добавить();
                                                   Движение.Период = Дата;
                                                   Движение.Заказ = ВыборкаИтоги.Заказ;
                                                   Движение.Состояние = Перечисления.СостоянияЗаказов.Завершен;
                                                  
                                                   КолЗаказов = КолЗаказов + 1;
                                                  
                                   КонецЦикла;
                                  
                                   Движение = Движения.Продажи.Добавить();
                                   Движение.Период = Дата;
                                   Движение.ТочкаВыдачи = ТочкаВыдачи;
                                   Движение.КолЗаказов = КолЗаказов;
                                   Движение.Себестоимость = СебестоимостьИтого;
                                   Движение.Выручка = ВыборкаОбщиеИтоги.СуммаПродажи;
                                  
                    КонецЦикла;
    КонецПроцедуры
    </code>
    В документах ПоступлениеТоваров и ПеремещениеТоваров изменения не нужны.