Опубликован: 06.12.2011 | Уровень: для всех | Доступ: свободно
Лекция 8:

Проведение расходного документа, журналы документов, программная работа с документами

< Лекция 7 || Лекция 8: 12345 || Лекция 9 >
Аннотация: Лекция посвящена конструированию процедуры проведения расходного документа, особое внимание уделено созданию сложных запросов с помощью консоли запросов. Рассмотрена работа с объектом Журнал документов, а так же – методы программной работы с документами.

Проведение расходного документа

Мы уже настроили проведение документа, который отражает приход материалов. Теперь займемся проведением документа, отвечающего за их списание. Это – документ ОтпускМатериаловМастеру. Для начала сформулируем цели, которых мы хотим достичь при проведении данного документа. Если в случае с документом поступления материалов в нашей конфигурации все довольно просто – нам нужно лишь отразить поступление материалов без каких-либо дополнительных проверок или расчетов, то списание материалов даже в нашем, достаточно простом случае, превращается в непростую задачу.

Во-первых, мы хотим, чтобы система не позволяла списать больше материалов, чем числится за конкретным ответственным лицом. Это означает, что перед формированием движений мы должны сверить данные, введенные в табличную часть документа с данными по остаткам материалов, хранящимися в нашей базе, и, в том случае, если материалов нам не хватит – отказаться проводить документ и сообщить пользователю об ошибке.

Во-вторых, списывая материалы, мы должны придерживаться какой-либо политики оценки. Наиболее простая и широко используемая политика – это списание материалов по средней стоимости.

Предположим, мы приняли две партии одного и того же товара – в первой было 10 единиц по 9 рублей единица (общая стоимость 90 рублей), во второй – 20 единиц по 12 рублей единица (общая стоимость 240 рублей). В регистре мы храним общую стоимость материалов и их общее количество. Поэтому, списывая по методу средней стоимости, например, 15 единиц товара, мы сначала должны найти среднюю стоимость единицы имеющихся товаров, разделив их общую стоимость на общее количество – в нашем случае это (90+240)/(10+20)=11 рублей – и умножить полученную стоимость на количество списываемых товаров – то есть, 11*15=165 рублей. Таким образом, мы сможем оценивать стоимость списанных товаров и оценивать стоимость остатков.

Существуют и другие методы списания материальных ценностей, в частности – это ФИФО, ЛИФО. Вполне можно организовать учет каждой единицы материальных ценностей и списание их по индивидуальной себестоимости. Мы реализуем списание материалов по средней стоимости.

Определившись с нашими двумя основными задачами – реализации списания материалов по средней стоимости и контроля остатков, приступим к работе над процедурой для проведения нашего документа.

Перейдем в модуль объекта документа ОтпускМатериаловМастеру, с помощью панели инструментов Модуль создадим процедуру ОбработкаПроведения. Данные из табличной части мы будем получать с помощью запроса – в дальнейшем мы будем развивать этот запрос для получения необходимых сведений об остатках номенклатуры.

При создании запроса очень удобно пользоваться консолью запросов, которая позволяет в режиме 1С:Предприятие тут же проверять результаты, возвращаемые запросом. Подобные обработки можно найти на дисках ИТС, на различных Интернет-ресурсах, в частности, мы использовали в примерах консоль запросов для управляемого приложения, которую можно найти по адресу: http://nashe1c.ru/materials-view.jsp?id=307.

Итак, обработку консоли запросов следует открыть командой Главное меню > Файл > Открыть. Начнем конструировать запрос, выбрав все поля из таблицы документа ОтпускМатериаловМастеру, рис. 7.1.

Конструирование запроса с помощью консоли запросов

увеличить изображение
Рис. 7.1. Конструирование запроса с помощью консоли запросов

Наш запрос имеет такой вид:

ВЫБРАТЬ
  *
ИЗ
  Документ.ОтпускМатериаловМастеру.Материалы

Мы выбрали все поля из таблицы, не вводя никаких ограничений. Мы собираемся получать данные из таблицы документа, проведением которого мы занимаемся. В запросе же мы получили данные по всем документам. Ограничим наш запрос по документу. Модифицируем запрос в консоли таким образом:

ВЫБРАТЬ
  *
ИЗ
  Документ.ОтпускМатериаловМастеру.Материалы
ГДЕ
  Ссылка=&Ссылка

Для того, чтобы задать параметр запроса в консоли запросов, перейдем на вкладку Параметры запроса, нажмем на кнопку Заполнить, после чего в поле Значение параметра выберем нужное его значение, в нашем случае – это будет один из документов ОтпускМатериаловМастеру, рис. 7.2.

Настройка параметра запроса

увеличить изображение
Рис. 7.2. Настройка параметра запроса

Выполнив этот запрос, получим таблицу Материалы из указанного документа. Теперь подумаем над тем, какие именно данные нас интересуют. Нам нужны, во-первых, сведения о номенклатуре (поле Номенклатура), во-вторых – о количестве номенклатуры, которую мы хотим списать (поле Количество). Модифицируем запрос следующим образом:

ВЫБРАТЬ
  ДокМ.Номенклатура,
  ДокМ.Количество
ИЗ
  Документ.ОтпускМатериаловМастеру.Материалы КАК ДокМ
ГДЕ
  Ссылка=&Ссылка

Этот запрос даст нам такой результат:

Номенклатура Количество
Одеколон 2
Духи 11
УФ-гель 7
Лак для волос 3
Одеколон 3

В документе мы намеренно смоделировали ситуацию, в которой пользователь, заполняя его, два раза ввел одну и ту же номенклатурную позицию. Сгруппируем теперь результаты запроса по полю Номенклатура – придем к такому тексту запроса:

ВЫБРАТЬ
  ДокМ.Номенклатура,
  СУММА (ДокМ.Количество) КАК Количество
ИЗ
  Документ.ОтпускМатериаловМастеру.Материалы КАК ДокМ
ГДЕ
  Ссылка=&Ссылка
СГРУППИРОВАТЬ ПО ДокМ.Номенклатура

Здесь мы применили функцию СУММА к количественному показателю и с помощью выражения СГРУППИРОВАТЬ ПО сгруппировали результаты по полю Номенклатура. Это привело к такому результату:

Номенклатура Количество
Духи 11
Одеколон 5
УФ-гель 7
Лак для волос 3

Теперь все данные, которые нужны нам для проведения документа, мы получили. Следующим этапом работы над запросом будет добавление в него команд для выбора нужных данных из регистра накопления ОстаткиМатериалов. Мы приходим к такому запросу:

ВЫБРАТЬ
  ДокМ.Номенклатура,
  СУММА (ДокМ.Количество) КАК Количество,
  МАКСИМУМ (ОстМ.КоличествоОстаток) КАК КоличествоОстатков,
  МАКСИМУМ (ОстМ.СуммаОстаток) КАК СуммаОстатков
ИЗ
  Документ.ОтпускМатериаловМастеру.Материалы КАК ДокМ
  ЛЕВОЕ СОЕДИНЕНИЕ
  РегистрНакопления.ОстаткиМатериалов.Остатки(&МоментВремени) Как ОстМ
  ПО
    ДокМ.Номенклатура = ОстМ.Номенклатура
ГДЕ
  Ссылка=&Ссылка
СГРУППИРОВАТЬ ПО ДокМ.Номенклатура

Здесь мы соединили таблицу регистра остатков с полученной таблицей документа по полю Номенклатура. К числовым полям, полученным из регистра, мы применили функцию МАКСИМУМ – иначе запрос будет выполняться неверно. В частности, если бы выше мы не выполнили группировку результатов запроса по полю Номенклатура, то в результатах запроса мы получили бы несколько полей с одной и той же номенклатурой, к каждому из которых было бы присоединено одно и то же поле из таблицы регистра.

Поля в таблице документа несут значимую информацию – если даже номенклатура повторяется, это подразумевает то, что пользователь сознательно ввел ее несколько раз (возможно для того, чтобы, выведя печатную форму документа, добавить какие-то дополнительные комментарии). А присоединение к этим данным одних и тех же данных из регистра накопления нас не устраивает. Поэтому мы суммируем данные по количеству материалов из табличной части, а к полям таблицы регистров применяем функцию МАКСИМУМ. Применение функции МАКСИМУМ здесь не принципиально – с тем же успехом можно было бы применить и функцию МИНИМУМ, и другие подходящие – их суть сводится к переходу от нескольких одинаковых значений к одному.

Вышеописанный запрос привел к такому результату:

Номенклатура Количество КоличествоОстатков СуммаОстатков
Духи 11 36 4 899
Одеколон 5 18 3 510
УФ-гель 7 11 3 350
Лак для волос 3 NULL NULL

Здесь нас не устраивают два момента. Во-первых, в полях КоличествоОстатков и СуммаОстатков показаны данные по всем ответственным лицам – а нам нужно знать данные лишь по тому ответственному, с которого мы материалы списываем. Во-вторых, по номенклатурной позиции, по которой данных в регистре ОстаткиМатериалов не имеется, в полях находится значение NULL. Для того, чтобы попытка работать с этим значением не привела в будущем к возникновению ошибок, обработаем поля, полученные из регистра, функцией ЕСТЬNULL.

Модифицируем запрос в соответствии с последними соображениями.

ВЫБРАТЬ
  ДокМ.Номенклатура,
  СУММА (ДокМ.Количество) КАК Количество,
  МАКСИМУМ (ЕСТЬNULL(ОстМ.КоличествоОстаток, 0)) КАК КоличествоОстатков,
  МАКСИМУМ (ЕСТЬNULL(ОстМ.СуммаОстаток, 0)) КАК СуммаОстатков
ИЗ
  Документ.ОтпускМатериаловМастеру.Материалы КАК ДокМ
  ЛЕВОЕ СОЕДИНЕНИЕ
  РегистрНакопления.ОстаткиМатериалов.Остатки(&МоментВремени , ОтветственныйСотрудник = &ОтвСотр) Как ОстМ
  ПО
    ДокМ.Номенклатура = ОстМ.Номенклатура
ГДЕ
  Ссылка=&Ссылка
СГРУППИРОВАТЬ ПО ДокМ.Номенклатура

Здесь мы добавили отбор из регистра только записей, относящихся к заданному ответственному сотруднику (ОтветственныйСотрудник = &ОтвСотр) и применили к показателям количества и суммы, полученным из регистра, функцию ЕСТЬNULL. Если в поле находится NULL, мы заменяем это значение нулем.

Результат запроса теперь выглядит так:

Номенклатура Количество КоличествоОстатков СуммаОстатков
Духи 11 15 1 860
Одеколон 5 2 400
УФ-гель 7 3 900
Лак для волос 3 0 0

На данном этапе запрос возвращает нам исключительно те данные, которые нужны для решения задачи. А именно – эти данные позволяют нам понять, хватит ли материалов, числящихся за ответственным лицом, для списания запрошенного в документе количества материалов. Так же, этими данными мы сможем воспользоваться при формировании движений по регистру накопления – эти движения можно будет формировать в цикле обхода результатов запроса.

< Лекция 7 || Лекция 8: 12345 || Лекция 9 >
Лариса Дятчина
Лариса Дятчина

Код 

&НаКлиенте

Процедура ОсновноеКонтактноеЛицоПриИзменении(Элемент)

Если НЕ ПроверитьЗаполнениеРеквизита() Тогда

 Сообщить("Выбранное контактное лицо, "+Объект.ОсновноеКонтактноеЛицо+",не работает у контрагента.");

КонецЕсли;

КонецПроцедуры

 

&НаСервере

Функция ПроверитьЗаполнениеРеквизита()

 Возврат (Объект.ОсновноеКонтактноеЛицо.ПредставительРаботает);  

КонецФункции

&НаСервере

Процедура УстановитьНомерПредставителя()

 

 Объект.ТелефонКонтактногоЛица=Объект.ОсновноеКонтактноеЛицо.КонтактныеСведения;

КонецПроцедуры

При проверке выдает ошибку:

{Справочник.Контрагенты.Форма.ФормаСписка.Форма(12,11)}: Переменная не определена (Объект)
 Возврат (<<?>>Объект.ОсновноеКонтактноеЛицо.ПредставительРаботает);   (Проверка: Сервер)
{Справочник.Контрагенты.Форма.ФормаСписка.Форма(17,2)}: Переменная не определена (Объект)
 <<?>>Объект.ТелефонКонтактногоЛица=Объект.ОсновноеКонтактноеЛицо.КонтактныеСведения; (Проверка: Сервер)
{Справочник.Контрагенты.Форма.ФормаСписка.Форма(17,32)}: Переменная не определена (Объект)
 Объект.ТелефонКонтактногоЛица=<<?>>Объект.ОсновноеКонтактноеЛицо.КонтактныеСведения; (Проверка: Сервер)
{Справочник.Контрагенты.Форма.ФормаСписка.Форма(6,41)}: Переменная не определена (Объект)
 Сообщить("Выбранное контактное лицо, "+<<?>>Объект.ОсновноеКонтактноеЛицо+",не работает у контрагента."); (Проверка: Тонкий клиент)

 

работаю на версии 1С:Предприятие 8.3 (8.3.10.2650)

максим матасов
максим матасов
Равиль Латыпов
Равиль Латыпов
Россия, Казань, Казанский Национальный Исследовательский Технический Университет