понедельник, 2 марта 2015 г.

1c специалист задача 1.23

Условие из сборника:
Компания занимается оптовой торговлей. Поступление товаров отражается документом «Приходная накладная», продажа - «Расходная накладная». Продажа происходит с учетом единиц измерения, т.е. для каждой номенклатурной позиции может быть произвольное количество единиц измерения, например: штука; пачка из 10 штук; контейнер из 500 штук и т.д. Если в накладной будет указана продажа 3-х пачек, то должны быть списаны 30 штук. Кроме того, в расходной накладной могут также быть указаны услуги (например, доставка). И товары и услуги необходимо указывать в одной табличной части. Учет товаров ведется в разрезе складов. При проведении расходной накладной необходимо в первую очередь контролировать хватает ли товара вообще. Если нет – выдавать соответствующее предупреждение с указанием количества нехватки и не позволять проводить документ. Списание себестоимости товаров должно быть организовано только по складам, указанным для него в табличной части документа. Себестоимость товара рассчитывается как средняя по складу. Поступление товара происходит на один выбранный пользователем в документе «Приходная накладная» склад. Необходимо построить отчет по анализу продаж товаров за период. Прибыль рассчитывается:




Решение:
1) Ранее уже встречались задачи на тему единиц измерения. Реализуем тем же способом,через регистр сведений с измерениями "Номенклатура" и "Единица измерения". и ресурсом "количество". 
Добавляем справочник "склады".
Потребуется  2 регистра "Остатки номенклатуры" и оборотный регистр "Продажи".
2) Переходим к приходной накладной. Добавляем в шапку "Склад" и плавно переходим к обработке проведения.
Процедура ОбработкаПроведения(Отказ, Режим)
Движения.ОстаткиНоменклатуры.Записывать = Истина;

Запрос = Новый("Запрос");
Запрос.Текст = "ВЫБРАТЬ
              | КоэффициентыЕИ.ЕИ,
              | ВЫБОР
              | КОГДА КоэффициентыЕИ.Количество ЕСТЬ NULL 
              | ТОГДА ПриходнаяНакладнаяСписокНоменклатуры.Количество
              | ИНАЧЕ ПриходнаяНакладнаяСписокНоменклатуры.Количество * КоэффициентыЕИ.Количество
              | КОНЕЦ КАК Количество,
              | ПриходнаяНакладнаяСписокНоменклатуры.Ссылка.Склад,
              | ПриходнаяНакладнаяСписокНоменклатуры.Ссылка.Дата КАК Период,
              | ПриходнаяНакладнаяСписокНоменклатуры.Сумма,
              | ПриходнаяНакладнаяСписокНоменклатуры.Номенклатура
              |ИЗ
              | Документ.ПриходнаяНакладная.СписокНоменклатуры КАК ПриходнаяНакладнаяСписокНоменклатуры
              | ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КоэффициентыЕИ КАК КоэффициентыЕИ
              | ПО ПриходнаяНакладнаяСписокНоменклатуры.Номенклатура = КоэффициентыЕИ.Номенклатура
              | И ПриходнаяНакладнаяСписокНоменклатуры.ЕдиницаИзмерения = КоэффициентыЕИ.ЕИ
              |ГДЕ
              | ПриходнаяНакладнаяСписокНоменклатуры.Ссылка = &Ссылка
              | И ПриходнаяНакладнаяСписокНоменклатуры.Номенклатура.ТипТовара <> &ТипТовара";

Запрос.УстановитьПараметр("Ссылка", Ссылка);
Запрос.УстановитьПараметр("ТипТовара", Перечисления.ТипТовара.Услуга);

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Движение = Движения.ОстаткиНоменклатуры.ДобавитьПриход();
ЗаполнитьЗначенияСвойств(Движение,Выборка);
КонецЦикла;


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

3) Плавно переходим к расходной накладной. Особенностью задачи является то, что склад является реквизитом табличной части.
Довольно странное требование вывести сообщение о нехватке итогового количества. Зачем??? ведь все- равно списываем с конкретного склада и себестоимость по рассчитываем по складу.
Но да ладно надо значит надо. Реализуем и это. Для этого необходимо будем таблицу документа связать с 2-мя виртуальными таблицами (по складу и по всем складам).

Процедура ОбработкаПроведения(Отказ, РежимПроведения)
//1 Очистка движений
Движения.ОстаткиНоменклатуры.Записывать = Истина;
Движения.ОстаткиНоменклатуры.Очистить();
Движения.ОстаткиНоменклатуры.Записать();

Движения.Продажи.Записывать = Истина;

// Блокировка
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ОстаткиНоменклатуры");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
ЭлементБлокировки.ИсточникДанных = СписокНоменклатуры;
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Номенклатура", "Номенклатура");
Блокировка.Заблокировать(); 

//Запрос
Запрос = Новый("Запрос");
Запрос.Текст = "ВЫБРАТЬ
              | РасходнаяНакладнаяСписокНоменклатуры.Номенклатура КАК Номенклатура,
              | СУММА(ВЫБОР
              | КОГДА КоэффициентыЕИ.Количество ЕСТЬ NULL 
              | ТОГДА РасходнаяНакладнаяСписокНоменклатуры.Количество
              | ИНАЧЕ РасходнаяНакладнаяСписокНоменклатуры.Количество * КоэффициентыЕИ.Количество
              | КОНЕЦ) КАК Количество,
              | СУММА(РасходнаяНакладнаяСписокНоменклатуры.Сумма) КАК Сумма,
              | РасходнаяНакладнаяСписокНоменклатуры.Склад
              |ПОМЕСТИТЬ ДокТЧ
              |ИЗ
              | Документ.РасходнаяНакладная.СписокНоменклатуры КАК РасходнаяНакладнаяСписокНоменклатуры
              | ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КоэффициентыЕИ КАК КоэффициентыЕИ
              | ПО РасходнаяНакладнаяСписокНоменклатуры.Номенклатура = КоэффициентыЕИ.Номенклатура
              | И РасходнаяНакладнаяСписокНоменклатуры.ЕдиницаИзмерения = КоэффициентыЕИ.ЕИ
              |ГДЕ
              | РасходнаяНакладнаяСписокНоменклатуры.Ссылка = &Ссылка
              | И РасходнаяНакладнаяСписокНоменклатуры.Номенклатура.ТипТовара <> &ТипТовара
              |
              |СГРУППИРОВАТЬ ПО
              | РасходнаяНакладнаяСписокНоменклатуры.Номенклатура,
              | РасходнаяНакладнаяСписокНоменклатуры.Склад
              |
              |ИНДЕКСИРОВАТЬ ПО
              | Номенклатура
              |;
              |
              |////////////////////////////////////////////////////////////////////////////////
              |ВЫБРАТЬ
              | ДокТЧ.Номенклатура КАК Номенклатура,
              | ДокТЧ.Количество КАК КолДок,
              | ДокТЧ.Сумма КАК СумДок,
              | ЕСТЬNULL(ОстаткиСклад.КоличествоОстаток, 0) КАК КолСклад,
              | ЕСТЬNULL(ОстаткиСклад.СуммаОстаток, 0) КАК СумСклад,
              | ЕСТЬNULL(ОстаткиВсего.КоличествоОстаток, 0) КАК ВсегоКол,
              | ДокТЧ.Склад
              |ИЗ
              | ДокТЧ КАК ДокТЧ
              | ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиНоменклатуры.Остатки(
              | &ТочкаИтогов,
              | (Номенклатура, Склад) В
              | (ВЫБРАТЬ
              | ДокТЧ.Номенклатура,
              | ДокТЧ.Склад
              | ИЗ
              | ДокТЧ КАК ДокТЧ)) КАК ОстаткиСклад
              | ПО ДокТЧ.Склад = ОстаткиСклад.Склад
              | И ДокТЧ.Номенклатура = ОстаткиСклад.Номенклатура
              | ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиНоменклатуры.Остатки(
              | &ТочкаИтогов,
              | Номенклатура В
              | (ВЫБРАТЬ
              | ДокТЧ.Номенклатура
              | ИЗ
              | ДокТЧ)) КАК ОстаткиВсего
              | ПО ДокТЧ.Номенклатура = ОстаткиВсего.Номенклатура";



Запрос.УстановитьПараметр("Ссылка",Ссылка);
Запрос.УстановитьПараметр("ТипТовара",Перечисления.ТипТовара.Услуга);
Если РежимПроведения = РежимПроведенияДокумента.Оперативный Тогда  
ТочкаИтогов=Неопределено;
Иначе
ТочкаИтогов = Новый Граница(МоментВремени(),ВидГраницы.Исключая);
КонецЕсли;
Запрос.УстановитьПараметр("ТочкаИтогов", ТочкаИтогов);

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл
Если Выборка.ВсегоКол < Выборка.КолДок Тогда 
Отказ = Истина;
Сообщение = Новый("СообщениеПользователю");
Сообщение.Текст ="Недостаточно товара по всем складам "+ Выборка.Номенклатура +" надо еще " +(Выборка.КолДок - Выборка.ВсегоКол);
Сообщение.Сообщить();
Продолжить;
Иначе

Если Выборка.КолСклад < Выборка.КолДок Тогда 
Отказ = Истина;
Сообщение = Новый("СообщениеПользователю");
Сообщение.Текст ="Недостаточно товара на выбранном складе"+ Выборка.Номенклатура +" надо еще " +(Выборка.КолДок - Выборка.КолСклад);
Сообщение.Сообщить();

Иначе
Движение = Движения.ОстаткиНоменклатуры.ДобавитьРасход();
Движение.Период = Дата;
Движение.Номенклатура =Выборка.Номенклатура ;
Движение.Склад = Выборка.Склад;
Движение.Количество = Выборка.КолДок;
Если Выборка.КолСклад <> 0 Тогда 
Себестоимость= Выборка.КолДок * Выборка.СумСклад/Выборка.КолСклад;
Иначе
Себестоимость =0;
КонецЕсли;
Движение.Сумма = Себестоимость;

// продажи
Движение = Движения.Продажи.Добавить();
Движение.Период = Дата;
Движение.Номенклатура =Выборка.Номенклатура ;
Движение.Количество = Выборка.КолДок;
Движение.Себестоимость = Себестоимость;
Движение.СуммаПродажи = Выборка.СумДок;

КонецЕсли;
КонецЕсли;

КонецЦикла;
КонецПроцедуры


4) Делаем отчет. Он аналогичен отчету из задачи 1.21.




Скачать решение задачи 1.23

1c специалист задача 1.22

Условие из сборника:
Компания занимается оптовой торговлей. Поступление товаров отражается документом «Приходная накладная», продажа - «Расходная накладная». Помимо продажи товара, могут оказываться дополнительные услуги, например по доставке. И услуги и товары указываются в одной табличной части. Учет товаров ведется в разрезе складов. Каждый из складов имеет свой приоритет, который может меняться не чаще чем 1 раз в месяц. При проведении расходной накладной необходимо в первую очередь контролировать хватает ли товара вообще. Если нет – выдавать соответствующее предупреждение с указанием количества нехватки и не позволять проводить документ. Списание себестоимости товаров должно быть организовано по складам, в зависимости от текущего значения их приоритета и выбранного в документе склада. В первую очередь товар списывается со склада, указанного в шапке документа, далее со склада с минимальным приоритетом, потом со следующего склада с большим приоритетом и т.д. пока не спишется все необходимое количество. Себестоимость товаров рассчитывается как средняя по складу. Поступление товара происходит на один выбранный пользователем в документе «Приходная накладная» склад. Необходимо построить отчет по движениям товаров за период по количеству и сумме.


Решение:
Задача почти идентична предыдущей, поэтому особо комментировать ничего.
Удаляем неиспользуемые регистры из предыдущей задачи и куски кода касающиеся их в обработках проведения.
Добавляем перечисление "тип товара" и реквизит этого типа в справочник "номенклатура".
Добавляем условие в обработках проведения, на то что товар <> услуга.
Делаем простой отчет по таблице остатков и оборотов регистра.

Скачать решение задачи 1.22

1c специалист задача 1.21

Условие из сборника:
Компания занимается оптовой торговлей. Поступление товаров отражается документом «Приходная накладная», продажа – «Расходная накладная». Помимо продажи товара, могут оказываться дополнительные услуги, например по доставке. И услуги и товары указываются в одной табличной части. Учет товаров ведется в разрезе складов. Каждый из складов имеет свой приоритет, который может меняться не чаще чем 1 раз в месяц. При проведении расходной накладной необходимо в первую очередь контролировать хватает ли товара вообще. Если нет – выдавать соответствующее предупреждение с указанием количества нехватки и не позволять проводить документ. Списание себестоимости товаров должно быть организовано по складам, в зависимости от текущего (на момент проведения документа) значения их приоритета. В первую очередь товар списывается со склада с минимальным приоритетом, потом со следующего склада с большим приоритетом и т.д. Себестоимость товаров рассчитывается как средняя по складу. Поступление товара происходит на один выбранный пользователем в документе «Приходная накладная» склад. Закупки производятся менеджерами, причем менеджер никак не связан со складом, на который приходуется товар. Необходимо построить отчеты о закупках за период товаров менеджерами и анализ продаж за период.



Решение:
1) Добавляем недостающие объекты:
В системе будет 3 регистра накопления( Остатки номенклатуры(тип остатки) и 2 оборотных "Продажи" и "Закупки".
2) добавим справочник "склады" и регистр сведений "Приоритеты складов", заполним этот регистр.
3)  Опишем обработку проведения "Приходной накладной".
Склад и менеджер - реквизиты шапки.

Процедура ОбработкаПроведения(Отказ, Режим)
Движения.ОстаткиНоменклатуры.Записывать = Истина;
Движения.Закупки.Записывать = Истина;
Для Каждого ТекСтрокаСписокНоменклатуры Из СписокНоменклатуры Цикл
// регистр ОстаткиНоменклатуры Приход
Движение = Движения.ОстаткиНоменклатуры.Добавить();
Движение.ВидДвижения = ВидДвиженияНакопления.Приход;
Движение.Период = Дата;
Движение.Номенклатура = ТекСтрокаСписокНоменклатуры.Номенклатура;
Движение.Склад = Склад;
Движение.Количество = ТекСтрокаСписокНоменклатуры.Количество;
Движение.Сумма = ТекСтрокаСписокНоменклатуры.Сумма;

Запись = Движения.Закупки.Добавить();
Запись.Период = Дата;
Запись.Номенклатура = ТекСтрокаСписокНоменклатуры.Номенклатура;
Запись.Менеджер     = Менеджер;
Запись.Количество   = ТекСтрокаСписокНоменклатуры.Количество;
Запись.Склад        = Склад;
КонецЦикла;
КонецПроцедуры

4) Проведя несколько приходных накладных можем сделать отчет по закупкам.

5) Пишем обработку проведения расходной накладной.
//1 Очистка движений
Движения.ОстаткиНоменклатуры.Записывать = Истина;
Движения.ОстаткиНоменклатуры.Очистить();
Движения.ОстаткиНоменклатуры.Записать();

Движения.Продажи.Записывать = Истина;
Движения.Продажи.Очистить();
Движения.Продажи.Записать();

// Блокировка
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ОстаткиНоменклатуры");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
ЭлементБлокировки.ИсточникДанных = СписокНоменклатуры;
ЭлементБлокировки.ИспользоватьИзИсточникаДанных("Номенклатура", "Номенклатура");
Блокировка.Заблокировать(); 

//Запрос
Запрос = Новый("Запрос");
Запрос.Текст = "ВЫБРАТЬ
              | РасходнаяНакладнаяСписокНоменклатуры.Номенклатура КАК Номенклатура,
              | СУММА(РасходнаяНакладнаяСписокНоменклатуры.Количество) КАК Количество,
              | СУММА(РасходнаяНакладнаяСписокНоменклатуры.Сумма) КАК Сумма
              |ПОМЕСТИТЬ ДокТЧ
              |ИЗ
              | Документ.РасходнаяНакладная.СписокНоменклатуры КАК РасходнаяНакладнаяСписокНоменклатуры
              |ГДЕ
              | РасходнаяНакладнаяСписокНоменклатуры.Ссылка = &Ссылка
              |
              |СГРУППИРОВАТЬ ПО
              | РасходнаяНакладнаяСписокНоменклатуры.Номенклатура
              |
              |ИНДЕКСИРОВАТЬ ПО
              | Номенклатура
              |;
              |
              |////////////////////////////////////////////////////////////////////////////////
              |ВЫБРАТЬ
              | ПриоритетыСкладовСрезПоследних.Приоритет КАК Приоритет,
              | ДокТЧ.Номенклатура КАК Номенклатура,
              | ДокТЧ.Количество КАК КолДок,
              | ДокТЧ.Сумма КАК СумДок,
              | ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) КАК ОстатокКол,
              | ЕСТЬNULL(ОстаткиНоменклатурыОстатки.СуммаОстаток, 0) КАК ОстатокСум,
              | ОстаткиНоменклатурыОстатки.Склад КАК Склад
              |ИЗ
              | ДокТЧ КАК ДокТЧ
              | ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиНоменклатуры.Остатки(
              | &ТочкаИтогов,
              | Номенклатура В
              | (ВЫБРАТЬ
              | ДокТЧ.Номенклатура
              | ИЗ
              | ДокТЧ)) КАК ОстаткиНоменклатурыОстатки
              | ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПриоритетыСкладов.СрезПоследних(&Период, ) КАК ПриоритетыСкладовСрезПоследних
              | ПО ОстаткиНоменклатурыОстатки.Склад = ПриоритетыСкладовСрезПоследних.Склад
              | ПО ДокТЧ.Номенклатура = ОстаткиНоменклатурыОстатки.Номенклатура
              |
              |УПОРЯДОЧИТЬ ПО
              | Приоритет
              |ИТОГИ
              | МАКСИМУМ(КолДок),
              | МАКСИМУМ(СумДок),
              | СУММА(ОстатокКол),
              | СУММА(ОстатокСум)
              |ПО
              | Номенклатура";
  
  
  Запрос.УстановитьПараметр("Ссылка",Ссылка);
  Запрос.УстановитьПараметр("Период",Дата);
  Если РежимПроведения = РежимПроведенияДокумента.Оперативный Тогда  
  ТочкаИтогов=Неопределено;
  Иначе
  ТочкаИтогов = Новый Граница(МоментВремени(),ВидГраницы.Исключая);
  КонецЕсли;
  Запрос.УстановитьПараметр("ТочкаИтогов", ТочкаИтогов);
  
  ВыборкаНоменлатура = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам,"Номенклатура");
  
  Пока ВыборкаНоменлатура.Следующий() Цикл
  Если ВыборкаНоменлатура.ОстатокКол < ВыборкаНоменлатура.КолДок Тогда 
Отказ = Истина;
Сообщение = Новый("СообщениеПользователю");
Сообщение.Текст ="Недостаточно товара "+ ВыборкаНоменлатура.Номенклатура +" надо еще " +(ВыборкаНоменлатура.колДок - ВыборкаНоменлатура.ОстатокКол);
Сообщение.Сообщить();
Иначе
ОсталосьСписать = ВыборкаНоменлатура.КолДок;
Товар = ВыборкаНоменлатура.Номенклатура;

ВыборкаСклад = ВыборкаНоменлатура.Выбрать();
Пока ВыборкаСклад.Следующий() и ОсталосьСписать>0 Цикл

КоличествоКСписанию = Мин(ОсталосьСписать, ВыборкаСклад.ОстатокКол);

Движение = Движения.ОстаткиНоменклатуры.ДобавитьРасход();
Движение.Период = Дата;
Движение.Номенклатура = Товар;
Движение.Склад = ВыборкаСклад.Склад;
Движение.Количество = КоличествоКСписанию;
Если ВыборкаСклад.ОстатокКол <> 0 Тогда 
Себестоимость= КоличествоКСписанию * ВыборкаСклад.ОстатокСум/ВыборкаСклад.ОстатокКол;
Иначе
Себестоимость =0;
КонецЕсли;
Движение.Сумма = Себестоимость;
//продажи
Движение = Движения.Продажи.Добавить();
Движение.Период = Дата;
Движение.Номенклатура = Товар;
Движение.Количество = КоличествоКСписанию;
Движение.Себестоимость = Себестоимость;
Движение.СуммаПродаж = КоличествоКСписанию * (ВыборкаСклад.СумДок/ВыборкаСклад.КолДок);
ОсталосьСписать = ОсталосьСписать - КоличествоКСписанию;
КонецЦикла;
  КонецЕсли;
  КонецЦикла;

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

СГРУППИРОВАТЬ ПО
ПродажиОбороты.Номенклатура,
ПродажиОбороты.КоличествоОборот,
ПродажиОбороты.СебестоимостьОборот,
ПродажиОбороты.СуммаПродажОборот
;

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

СГРУППИРОВАТЬ ПО
Продажи.Номенклатура,
Продажи.Количество,
Продажи.Себестоимость,
Продажи.Продажа,
Продажи.Прибыль


Скачать решение задачи 1.21 (1с специалист)

воскресенье, 1 марта 2015 г.

1c специалист задача 1.20

Условие из сборника:
Задача 1.20. Компания занимается оптовой торговлей. Все операции отражаются документами «Приходная накладная», «Расходная накладная», «Приход денег» и «Расход денег», причем для каждого из них может быть указана своя статья затрат. Таким образом, документ «Расход денег» может отражать операции например по оплате поставщику или возврата от покупателя в зависимости от выбранной статьи затрат. Структурно компания состоит из нескольких подразделений. В целях ведения управленческого учета для каждого отдела заводится бюджет (документ «Бюджет») на предстоящий месяц с указанием всех предполагаемых статей затрат, сумм по ним и возможного превышения этих сумм в суммовом выражении. Следует считать, что каждое подразделение может вводить несколько документов «Бюджет», данные которых должны суммироваться для формирования итогового бюджета. В целях контроля над исполнением бюджета при проведении любого документа должен происходить анализ фактических затрат и выводится соответствующее предупреждение, в случае превышения над бюджетом. Например, если по статье «оплата поставщикам» запланировано 100 000 и 20 000, то при суммарной оплате более 100 000 и более 120 000 должны быть выданы соответствующие предупреждения. Можно считать, что документы задним числом не вводятся, но существующие документы могут быть перепроведены. Необходимо создать отчет по исполнению бюджета за период, кратный месяцу.


Решение:
Возможно, мне на до конца удалось постичь весь глубокий замысел составителей задачи. Реально тяжело представить как в реальной жизни документом "Приход денег" списываются затраты. Но делать нечего, приходится абстрагироваться.
1) Заведем оборотный регистр "Бюджет" и справочник "СтатьиЗатрат".
 В регистре 2 измерения "Подразделение" и "Статья" и 3 ресурса (ПланСумма. планСуммапревышений, и факт).
2) Создаем все необходимые документы: «Приходная накладная», «Расходная накладная», «Приход денег» и «Расход денег»,"Бюджет"(у него еще реквизит "сумма план превышений")  у каждого реквизиты шапки "Подразделение", СтатьяЗатрат и "СуммаДокумента".
Каждый из Них является регистратором регистра "Бюджет".
3) Пишем обработку проведения документа "Бюджет"

Процедура ОбработкаПроведения(Отказ, Режим)

// регистр Бюджет
Движения.Бюджет.Записывать = Истина;
Движение = Движения.Бюджет.Добавить();
Движение.Период = Дата;
Движение.Подразделение = Подразделение;
Движение.СтатьяЗатрат = СтатьяЗатрат;
Движение.ПлановаяСуммаЗатрат = ПлановаяСумма;
Движение.ПлановаяСуммаПревышения = ПлановаяСуммаПревышения;
КонецПроцедуры


4) Пишем обработку проведения остальных документов. Она будет одинакова для всех документов.
// регистр Бюджет
Движения.Бюджет.Записывать = Истина;
Движение = Движения.Бюджет.Добавить();
Движение.Период = Дата;
Движение.Подразделение = Подразделение;
Движение.СтатьяЗатрат = СтатьяЗатрат;
Движение.ФактическаяСумма = СуммаДокумента;

Движения.Бюджет.Записать();
Бюджет.АнализФактическихЗатрат(Подразделение, СтатьяЗатрат,Дата);

Обратите внимание на команду Записать() перед вызовом процедуры общего модуля, иначе  движения текущего документа не будут учтены.

5) Процедура общего модуля

Процедура АнализФактическихЗатрат(Подразделение,СтатьяЗатрат, ДатаДок) Экспорт
Запрос = Новый("Запрос");
Запрос.Текст ="ВЫБРАТЬ
             | БюджетОбороты.Подразделение КАК Подразделение,
             | БюджетОбороты.СтатьяЗатрат КАК СтатьяЗатрат,
             | ЕСТЬNULL(БюджетОбороты.ПлановаяСуммаЗатратОборот, 0) КАК ПлановаяСуммаЗатрат,
             | ЕСТЬNULL(БюджетОбороты.ПлановаяСуммаПревышенияОборот, 0) КАК ПлановаяСуммаПревышения,
             | ЕСТЬNULL(БюджетОбороты.ФактическаяСуммаОборот, 0) КАК ФактическаяСумма
             |ИЗ
             | РегистрНакопления.Бюджет.Обороты(
             | &НачалоПериода,
             | &КонецПериода,
             | ,
             | Подразделение = &Подразделение
             | И СтатьяЗатрат = &СтатьяЗатрат) КАК БюджетОбороты
             |ИТОГИ
             | СУММА(ПлановаяСуммаЗатрат),
             | СУММА(ПлановаяСуммаПревышения),
             | СУММА(ФактическаяСумма)
             |ПО
             | СтатьяЗатрат" ;
Запрос.УстановитьПараметр("Подразделение",Подразделение);
Запрос.УстановитьПараметр("СтатьяЗатрат",СтатьяЗатрат);
Запрос.УстановитьПараметр("НачалоПериода",НачалоМесяца(ДатаДок));
Запрос.УстановитьПараметр("КонецПериода",КонецМесяца(ДатаДок));
ТекстСообщения ="";
ВыборкаИтоги = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам,"СтатьяЗатрат");
ВыборкаИтоги.Следующий();
Если ВыборкаИтоги.ФактическаяСумма > ВыборкаИтоги.ПлановаяСуммаЗатрат  Тогда
СуммаПревышения = ВыборкаИтоги.ФактическаяСумма - ВыборкаИтоги.ПлановаяСуммаЗатрат ;
ТекстСообщения = ТекстСообщения + "Фактическая сумма затрат по статье "+ ВыборкаИтоги.СтатьяЗатрат + " превышает плановую сумму на " +СуммаПревышения  ;
КонецЕсли;
Если ВыборкаИтоги.ФактическаяСумма > ВыборкаИтоги.ПлановаяСуммаЗатрат+ВыборкаИтоги.ПлановаяСуммаПревышения Тогда
СуммаПревышения = ВыборкаИтоги.ФактическаяСумма-   ВыборкаИтоги.ПлановаяСуммаЗатрат-ВыборкаИтоги.ПлановаяСуммаПревышения;
ТекстСообщения = ТекстСообщения +Символы.ПС+ "Фактическая сумма затрат по статье "+ ВыборкаИтоги.СтатьяЗатрат + " превышает плановую сумму с превышением на " +СуммаПревышения  ;
КонецЕсли;
Если ЗначениеЗаполнено(ТекстСообщения) Тогда 
Сообщение = Новый("СообщениеПользователю");
Сообщение.Текст= ТекстСообщения;
Сообщение.Сообщить();
КонецЕсли;

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

6) Отчет
Текст запроса:
ВЫБРАТЬ
БюджетОбороты.Период,
БюджетОбороты.Подразделение,
БюджетОбороты.СтатьяЗатрат,
БюджетОбороты.ПлановаяСуммаЗатратОборот КАК План,
БюджетОбороты.ФактическаяСуммаОборот КАК Факт,
ВЫБОР
КОГДА БюджетОбороты.ПлановаяСуммаЗатратОборот <> 0
ТОГДА ВЫРАЗИТЬ(БюджетОбороты.ФактическаяСуммаОборот / БюджетОбороты.ПлановаяСуммаЗатратОборот * 100 КАК ЧИСЛО(13, 2))
КОНЕЦ КАК Процент
ИЗ
РегистрНакопления.Бюджет.Обороты(&ДатаНачала, &ДатаОкончания, Месяц, ) КАК БюджетОбороты

ресурсы рассчитываем по "статье затрат".

Скачать решение задачи 1.20