Компания занимается оптовой торговлей поступление товаров отражается документом приходная накладная

Условие из сборника:
Компания занимается оптовой торговлей. Поступление товаров отражается
документом «Приходная накладная», продажа – «Расходная накладная». Помимо
продажи товара, могут оказываться дополнительные услуги, например по
доставке. И услуги и товары указываются в одной табличной части.
Учет товаров ведется в разрезе складов. Каждый из складов имеет свой
приоритет, который может меняться не чаще чем 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с специалист)

Функция СписатьСебестоимостьТоваров(ДокументСсылка) 

НачатьТранзакцию(РежимУправленияБлокировкойДанных.Управляемый);

МетодСписания = РегистрыСведений.УчетнаяПолитика.ПолучитьПоследнее(ДокументСсылка.Дата).УчетнаяПолитика;

Запрос = Новый Запрос;

Запрос.Текст = 

«ВЫБРАТЬ

| РасходнаяНакладнаяСписокНоменклатуры.Номенклатура

|ИЗ

| Документ.РасходнаяНакладная.СписокНоменклатуры КАК РасходнаяНакладнаяСписокНоменклатуры

|ГДЕ

| РасходнаяНакладнаяСписокНоменклатуры.Ссылка = &Ссылка

| И РасходнаяНакладнаяСписокНоменклатуры.Номенклатура.ВидНоменклатуры <> ЗНАЧЕНИЕ(Перечисление.ВидыНоменклатуры.Услуга)»;

Запрос.УстановитьПараметр(«Ссылка», ДокументСсылка);

РезультатЗапроса = Запрос.Выполнить();

Если НЕ РезультатЗапроса.Пустой() Тогда

НоменклатураДляБлокирования = РезультатЗапроса.Выгрузить();

Блокировка = Новый БлокировкаДанных;

ЭлементБлокировки = Блокировка.Добавить(«РегистрНакопления.СтоимостьНоменклатуры»);

ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;

ЭлементБлокировки.ИсточникДанных = НоменклатураДляБлокирования;

ЭлементБлокировки.ИспользоватьИзИсточникаДанных(«Номенклатура», «Номенклатура»);

Блокировка.Заблокировать();

КонецЕсли; 

ФлагУспешностиСписания = Истина;

НаборЗаписей = РегистрыНакопления.СтоимостьНоменклатуры.СоздатьНаборЗаписей();

НаборЗаписей.Отбор.Регистратор.Установить(ДокументСсылка);

НаборЗаписей.Записать();

Запрос = Новый Запрос;

Запрос.Текст = 

«ВЫБРАТЬ

| РасходнаяНакладнаяСписокНоменклатуры.Номенклатура КАК Номенклатура,

| СУММА(РасходнаяНакладнаяСписокНоменклатуры.Количество) КАК Количество

|ПОМЕСТИТЬ ВТ_Товары

|ИЗ

| Документ.РасходнаяНакладная.СписокНоменклатуры КАК РасходнаяНакладнаяСписокНоменклатуры

|ГДЕ

| РасходнаяНакладнаяСписокНоменклатуры.Ссылка = &Ссылка

| И РасходнаяНакладнаяСписокНоменклатуры.Номенклатура.ВидНоменклатуры <> ЗНАЧЕНИЕ(Перечисление.ВидыНоменклатуры.Услуга)

|

|СГРУППИРОВАТЬ ПО

| РасходнаяНакладнаяСписокНоменклатуры.Номенклатура

|

|ИНДЕКСИРОВАТЬ ПО

| Номенклатура

|;

|

|////////////////////////////////////////////////////////////////////////////////

|ВЫБРАТЬ

| ВТ_Товары.Номенклатура КАК Номенклатура,

| ВТ_Товары.Количество КАК Количество,

| СтоимостьНоменклатурыОстатки.Партия,

| ЕСТЬNULL(СтоимостьНоменклатурыОстатки.КоличествоОстаток, 0) КАК КоличествоОстаток,

| ЕСТЬNULL(СтоимостьНоменклатурыОстатки.СтоимостьОстаток, 0) КАК СтоимостьОстаток

|ИЗ

| ВТ_Товары КАК ВТ_Товары

| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.СтоимостьНоменклатуры.Остатки(

| &Момент,

| Номенклатура В

| (ВЫБРАТЬ

| ВТ_Товары.Номенклатура

| ИЗ

| ВТ_Товары КАК ВТ_Товары)) КАК СтоимостьНоменклатурыОстатки

| ПО ВТ_Товары.Номенклатура = СтоимостьНоменклатурыОстатки.Номенклатура

|

|УПОРЯДОЧИТЬ ПО

| СтоимостьНоменклатурыОстатки.Партия.МоментВремени

|ИТОГИ

| МАКСИМУМ(Количество),

| СУММА(КоличествоОстаток),

| СУММА(СтоимостьОстаток)

|ПО

| Номенклатура»;

Запрос.УстановитьПараметр(«Момент», ДокументСсылка.МоментВремени());

Запрос.УстановитьПараметр(«Ссылка», ДокументСсылка);

Если МетодСписания = Перечисления.УчетнаяПолитика.ЛИФО Тогда

Запрос.Текст = СтрЗаменить(Запрос.Текст,»СтоимостьНоменклатурыОстатки.Партия.МоментВремени», «СтоимостьНоменклатурыОстатки.Партия.МоментВремени УБЫВ»);

КонецЕсли; 

РезультатЗапроса = Запрос.Выполнить();

ВыборкаНоменклатура = РезультатЗапроса.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

Пока ВыборкаНоменклатура.Следующий() Цикл

Если ВыборкаНоменклатура.КоличествоОстаток < ВыборкаНоменклатура.Количество Тогда

ФлагУспешностиСписания = Ложь;

Сообщение = Новый СообщениеПользователю;

Нехватка = ВыборкаНоменклатура.Количество — ВыборкаНоменклатура.КоличествоОстаток;

Сообщение.Текст = «В документе » + ДокументСсылка.Номер + » не хватает » + Нехватка + » единиц товара » +ВыборкаНоменклатура.Номенклатура;

Сообщение.Сообщить(); 

Иначе

КоличествоНадоСписать = ВыборкаНоменклатура.Количество;

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

Пока ВыборкаДетальныеЗаписи.Следующий() Цикл

Если ВыборкаДетальныеЗаписи.КоличествоОстаток <= КоличествоНадоСписать Тогда

КоличествоКСписанию = ВыборкаДетальныеЗаписи.КоличествоОстаток;

СтоимостьКСписанию = ВыборкаДетальныеЗаписи.СтоимостьОстаток; 

КоличествоНадоСписать = КоличествоНадоСписать — КоличествоКСписанию; 

Иначе

КоличествоКСписанию = КоличествоНадоСписать;

Если ВыборкаДетальныеЗаписи.КоличествоОстаток <> 0 Тогда

СтоимостьКСписанию = КоличествоКСписанию * ВыборкаДетальныеЗаписи.СтоимостьОстаток 

/ ВыборкаДетальныеЗаписи.КоличествоОстаток;

Иначе

СтоимостьКСписанию = ВыборкаДетальныеЗаписи.СтоимостьОстаток;

КонецЕсли; 

КоличествоНадоСписать = 0;

КонецЕсли; 

Движение = НаборЗаписей.Добавить();

Движение.ВидДвижения = ВидДвиженияНакопления.Расход;

Движение.Период = ДокументСсылка.Дата;

Движение.Номенклатура = ВыборкаДетальныеЗаписи.Номенклатура;

Движение.Партия = ВыборкаДетальныеЗаписи.Партия;

Движение.Количество = КоличествоКСписанию;

Движение.Стоимость = СтоимостьКСписанию;

Если КоличествоНадоСписать <= 0 Тогда

Прервать

КонецЕсли;

КонецЦикла;

КонецЕсли;

КонецЦикла;

Если ФлагУспешностиСписания И НаборЗаписей.Количество() <> 0 Тогда

НаборЗаписей.Записать();

КонецЕсли; 

ЗафиксироватьТранзакцию();

Возврат ФлагУспешностиСписания;

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


       9. Создаем регламентную операцию которая будет рассчитывать себестоимость (Предопределенная — ИСТИНА, Имя метода — «РаботаНаСервере.СписаниеСебестоимости»)

      10. Обработка проведения «ПриходнойНакладной»

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

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


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


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


    

      11.Обработка проведения «Расходной накладной»

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

Движения.ОстаткиНоменклатуры.Записывать = Истина;

Движения.ОстаткиНоменклатуры.БлокироватьДляИзменения = Истина;

Для Каждого ТекСтрокаСписокНоменклатуры Из СписокНоменклатуры Цикл

Движение = Движения.ОстаткиНоменклатуры.Добавить();

Движение.ВидДвижения = ВидДвиженияНакопления.Расход;

Движение.Период = Дата;

Движение.Номенклатура = ТекСтрокаСписокНоменклатуры.Номенклатура;

Движение.Склад = Склад;

Движение.Количество = ТекСтрокаСписокНоменклатуры.Количество;

КонецЦикла;

Движения.Записать();

Запрос = Новый Запрос;

Запрос.Текст = 

«ВЫБРАТЬ

| ОстаткиНоменклатурыОстатки.Номенклатура,

| ОстаткиНоменклатурыОстатки.Склад,

| ОстаткиНоменклатурыОстатки.КоличествоОстаток,

| ОстаткиНоменклатурыОстатки.Номенклатура.Представление

|ИЗ

| РегистрНакопления.ОстаткиНоменклатуры.Остатки(

| &Граница,

| Склад = &Склад

| И Номенклатура В (&СписокТоваров)) КАК ОстаткиНоменклатурыОстатки

|ГДЕ

| ОстаткиНоменклатурыОстатки.КоличествоОстаток < 0″;

Запрос.УстановитьПараметр(«Граница», Новый Граница(МоментВремени()));

Запрос.УстановитьПараметр(«Склад», Склад);

Запрос.УстановитьПараметр(«СписокТоваров», СписокНоменклатуры.ВыгрузитьКолонку(«Номенклатура»));

РезультатЗапроса = Запрос.Выполнить();

Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл

Сообщение = Новый СообщениеПользователю;

Сообщение.Текст = «По номенклатуре » + Выборка.НоменклатураПредставление + » товара. Перерасход » + -Выборка.КоличествоОстаток;

Сообщение.Сообщить(); 

Отказ = Истина;

КонецЦикла;

// регистр Продажи 

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

Для Каждого ТекСтрокаСписокНоменклатуры Из СписокНоменклатуры Цикл

Движение = Движения.Продажи.Добавить();

Движение.Период = Дата;

Движение.Номенклатура = ТекСтрокаСписокНоменклатуры.Номенклатура;

Движение.Количество = ТекСтрокаСписокНоменклатуры.Количество;

Движение.Сумма = ТекСтрокаСписокНоменклатуры.Сумма;

КонецЦикла;

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

      12. Создаем обработку через которую запустим расчет себестоимости:

      Листинг модуля:


&НаСервере
Процедура РассчитатьСебестоимостьНаСервере()

ДатаНачалаОбработки = Последовательности.СписаниеСебестоимости.ПолучитьГраницу().Дата;
РаботаНаСервере.ВыполнитьСписание(ДатаНачалаОбработки, КонецДня(ТекущаяДата()));

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


&НаКлиенте
Процедура РассчитатьСебестоимость(Команда)
РассчитатьСебестоимостьНаСервере();
КонецПроцедуры

      13. Создадим отчет «Остатки товаров»

Запрос:

ВЫБРАТЬ
ОстаткиНоменклатурыОстатки.Номенклатура,
ОстаткиНоменклатурыОстатки.Склад,
ОстаткиНоменклатурыОстатки.КоличествоОстаток
ИЗ
РегистрНакопления.ОстаткиНоменклатуры.Остатки КАК ОстаткиНоменклатурыОстатки


Ресурсы:

Параметры:

Макеты:

Компановка:

Оперативный учет 1.7 (Билет 1)



Бухгалтерский учет

Компания занимается торговлей продуктами питания. Учет товаров ведется в разрезе сроков годности. Под сроком годности принимается календарная дата, до которой товар годен к употреблению. На один и тот же товар с разными сроками годности при его поступлении может указываться разная цена. Например, на товар со сроком годности 10 января 2010 цена может быть ниже, чем на товар со сроком годности 30 января 2010. Товар с одинаковым сроком годности может поступать разными документами и по разной цене. Возможна ситуация когда в одном документе один и тот же товар поступает с разными сроками годности (и по разной цене). Учет товаров в разрезе складов не ведется.

Документ «Приходная накладная» реализует следующую проводку:

Дт «Товары» — Кт «Поставщики» на количество и сумму закупаемого товара.

Продажа товара регистрируется документом «Расходная накладная». При продаже срок годности не указывается. В первую очередь списывается товар с наименьшим календарным сроком годности. Себестоимость определяется как средняя по товару по всем срокам годности. Т.е. например если 1 пачка йогурта со сроком годности 10.01.2010 поступила по цене 90 рублей и еще 1 пачка того же йогурта, но со сроком годности 30.01.2010 поступила по цене 110 рублей, то при списании себестоимость одной пачки данного йогурта равна 100 рублей.

Документ «Расходная накладная» реализует следующие проводки:

Дт «Прибыли и убытки» — Кт «Товары» на количество и сумму себестоимости

Дт «Покупатели» — Кт «Прибыли и убытки» на сумму в продажных ценах.

При проведении документа анализируется наличие этого товара в организации. Если товара не достаточно документ не проводится.

Необходимо создать отчет, выдающий данные о количественном и суммовом остатке товаров.

Остатки товаров на 10.01.2010

Товар

Срок годности

Количество

Сумма

Йогурт

550

110 000

20.01.10

50

10 000

05.02.10

500

100 000

Кефир

20

400

20.01.10

20

400

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

Решение:

1.  Настроим план счетов «Управленческий»:

— Добавим новый признак учета «Количественный» (Тип — Булево)

— Добавим новый  признак учета субконто «Суммовой» (Тип — Булево)

2. Добавим новый вид субконто «Срок годности» (Тип — дата) в предопределенные планы видов характеристик

4. Изменим счет «Товары» в плане счетов:

5. В табличную часть приходной накладной добавим реквизит «Срок годности».

6. Создадим регистр бухгалтерии «Управленческий» (План счетов — «Управленческий», Корреспонденция = ИСТИНА, Представление списка — «Журнал проводок». ) Ресурсы — «Сумма», «Количество».

7. Обработчик проведения «Приходной накладной»

// регистр Управленческий 

Движения.Управленческий.Записывать = Истина;

Для Каждого ТекСтрокаСписокНоменклатуры Из СписокНоменклатуры Цикл

Движение = Движения.Управленческий.Добавить();

Движение.СчетДт = ПланыСчетов.Управленческий.Товары;

Движение.СчетКт = ПланыСчетов.Управленческий.Поставщики;

Движение.Период = Дата;

Движение.Сумма = ТекСтрокаСписокНоменклатуры.Сумма;

Движение.КоличествоДт  = ТекСтрокаСписокНоменклатуры.Количество;

Движение.СубконтоДт[ПланыВидовХарактеристик.ВидыСубконто.Номенклатура] = ТекСтрокаСписокНоменклатуры.Номенклатура;

Движение.СубконтоДт[ПланыВидовХарактеристик.ВидыСубконто.СрокГодности] = ТекСтрокаСписокНоменклатуры.СрокГодности;

КонецЦикла;

8. Обработчик проведения «Расходной накладной»

//Регистр управленческий

Движения.Управленческий.Записывать = Истина;

Движения.Управленческий.Записать();

Блокировка = Новый БлокировкаДанных;

Элемент = Блокировка.Добавить(«РегистрБухгалтерии.Управленческий»);

Элемент.УстановитьЗначение(«Счет», ПланыСчетов.Управленческий.Товары);

Элемент.ИсточникДанных = СписокНоменклатуры;

Элемент.ИспользоватьИзИсточникаДанных(«Субконто1», «Номенклатура»);

Блокировка.Заблокировать();

Запрос = Новый Запрос;

Запрос.Текст = «ВЫБРАТЬ

| РасходнаяНакладнаяСписокНоменклатуры.Номенклатура КАК Номенклатура,

| СУММА(РасходнаяНакладнаяСписокНоменклатуры.Количество) КАК Количество

|ПОМЕСТИТЬ ВТ

|ИЗ

| Документ.РасходнаяНакладная.СписокНоменклатуры КАК РасходнаяНакладнаяСписокНоменклатуры

|ГДЕ

| РасходнаяНакладнаяСписокНоменклатуры.Ссылка = &Ссылка

| И РасходнаяНакладнаяСписокНоменклатуры.Количество > 0

|

|СГРУППИРОВАТЬ ПО

| РасходнаяНакладнаяСписокНоменклатуры.Номенклатура

|

|ИНДЕКСИРОВАТЬ ПО

| Номенклатура

|;

|

|////////////////////////////////////////////////////////////////////////////////

|ВЫБРАТЬ

| ВТ.Номенклатура КАК Номенклатура,

| УправленческийОстатки.Субконто2 КАК СрокГодности,

| ВТ.Количество КАК Количество,

| ЕСТЬNULL(УправленческийОстатки.КоличествоОстатокДт, 0) КАК КоличествоОстаток,

| ЕСТЬNULL(УправленческийОстаткиОбщие.СуммаОстатокДт, 0) КАК СуммаОстаток

|ИЗ

| ВТ КАК ВТ

| ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Управленческий.Остатки(

| &Момент,

| Счет = ЗНАЧЕНИЕ(ПланСчетов.Управленческий.Товары),

| ,

| Субконто1 В

| (ВЫБРАТЬ

| ВТ.Номенклатура

| ИЗ

| ВТ)) КАК УправленческийОстатки

| ПО ВТ.Номенклатура = УправленческийОстатки.Субконто1

| ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Управленческий.Остатки(

| &Момент,

| Счет = ЗНАЧЕНИЕ(ПланСчетов.Управленческий.Товары),

| ,

| Субконто1 В

| (ВЫБРАТЬ

| ВТ.Номенклатура

| ИЗ

| ВТ)) КАК УправленческийОстаткиОбщие

| ПО ВТ.Номенклатура = УправленческийОстаткиОбщие.Субконто1

|

|УПОРЯДОЧИТЬ ПО

| СрокГодности

|ИТОГИ

| МАКСИМУМ(Количество),

| СУММА(КоличествоОстаток),

| МАКСИМУМ(СуммаОстаток)

|ПО

| Номенклатура»;

Запрос.УстановитьПараметр(«Ссылка»,Ссылка);

Запрос.УстановитьПараметр(«Момент»,МоментВремени());

Результат = Запрос.Выполнить();

ВыборкаНом = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

Пока  ВыборкаНом.Следующий() Цикл

Если ВыборкаНом.Количество() >  ВыборкаНом.КоличествоОстаток Тогда

Сообщение = Новый СообщениеПользователю();

Сообщение.Текст = «Нехватает товара» + ВыборкаНом.Номенклатура.Наименование;

Сообщение.Сообщить();

Отказ = Истина;

КонецЕсли;

Если Отказ Тогда 

Продолжить;

КонецЕсли;

ОсталосьСписать = ВыборкаНом.Количество;

Выборка = ВыборкаНом.Выбрать();

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

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

ОсталосьСписать = ОсталосьСписать — Списать;

Движение = Движения.Управленческий.Добавить();

Движение.СчетДт = ПланыСчетов.Управленческий.ПрибылиУбытки;

Движение.СчетКт = ПланыСчетов.Управленческий.Товары;

Движение.Период = Дата;

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

Движение.КоличествоКт = Списать;

Движение.СубконтоКт[ПланыВидовХарактеристик.ВидыСубконто.Номенклатура] = Выборка.Номенклатура;

Движение.СубконтоКт[ПланыВидовХарактеристик.ВидыСубконто.СрокГодности] = Выборка.СрокГодности;

КонецЦикла;

КонецЦикла;

Движение = Движения.Управленческий.Добавить();

Движение.СчетДт = ПланыСчетов.Управленческий.Покупатели;

Движение.СчетКт = ПланыСчетов.Управленческий.ПрибылиУбытки;

Движение.Период = Дата;

Движение.Сумма = СуммаПоДокументу;

9.Создадим отчет 



Запрос отчета:

ВЫБРАТЬ

УправленческийОстатки.Субконто1 КАК Товар,

УправленческийОстатки.СуммаОстатокДт КАК Сумма,

УправленческийОстатки1.Субконто2 КАК СрокГодности,

УправленческийОстатки1.КоличествоОстатокДт КАК Количество

ИЗ

РегистрБухгалтерии.Управленческий.Остатки(, Счет = ЗНАЧЕНИЕ(ПланСчетов.Управленческий.Товары), , ) КАК УправленческийОстатки

ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Управленческий.Остатки(, Счет = ЗНАЧЕНИЕ(ПланСчетов.Управленческий.Товары), , ) КАК УправленческийОстатки1

ПО УправленческийОстатки.Субконто1 = УправленческийОстатки1.Субконто1

Интересная задачка

Я
   morozov_sv

20.07.09 — 13:00

Недавно попалась одна задачка, вот только хорошего решения так и не придумал:

«Компания занимается оптовой торговлей. Поступление товаров отражается документом «Приходная накладная», продажа — «Расходная накладная».

Складской учет не ведется.

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

Вопрос: как красиво сделать «… В первую очередь должен списываться товар из, указанной в табличной части … «

  

Партнерская программа EFSOL Oblako

   Господин ПЖ

1 — 20.07.09 — 13:03

завести поле Приортет. у партии из ТЧ = 0, у остальных например 1. И сортировать

   Asmody

2 — 20.07.09 — 13:04

похожая фиговина попадалась на экзаме по платформе. делается 1м запросом

   Ненавижу 1С

3 — 20.07.09 — 13:05

>>Складской учет не ведется
то есть остатки мы не ведем никак, в том числе в разрезе партий
интересно

   Snovy

4 — 20.07.09 — 13:05

Мне кажется, что не может быть не только хорошего, но и вообще никакого решения у задачки, в условиях которой необходимо организовать партионное фифо/лифо при этом «складской учет не ведется»…

   Михаил Козлов

5 — 20.07.09 — 13:05

В запросе к остаткам партий отсортировать по полю, которое определяется, примерно, так:

ВЫБОР КОГДА рег.ДокументОприходования = док.Партия ТОГДА 0 ИНАЧЕ 1 КОНЕЦ КАК приоритетПартии

   morozov_sv

6 — 20.07.09 — 13:05

(1) Этот способ хорош, когда указывается одна партия для всего документа. Но нужно учитывать, что в табличной части может одна и та же номенклатура повторятся с различными партиями. А это сложнее

   morozov_sv

7 — 20.07.09 — 13:06

(3) (4) думаю, что они под этим подразумевали, что остатки в не ведутся в разрезе склада

   Господин ПЖ

8 — 20.07.09 — 13:07

(3, 4) это в переводе с языка инопланетян, которые пишут билеты — «нету спр. складов и учет в их разрезе не ведется»

   НЕА123

9 — 20.07.09 — 13:08

(6)

можно вместо приоритета указывать кол-во списанных, или остаток.

   Asmody

10 — 20.07.09 — 13:09

(6) не сильно сложнее. добавляются номера строк и устанавливается приоритет при проведении. (ну типа для строки N учитываем возможные последствия обработки строк M>N). тоже запросом можно организовать

   Михаил Козлов

11 — 20.07.09 — 13:12

(6) И чему это мешает? Ну будет для каждой строки своя приоритетная партия. Ясно, что нужно хранить уже списанные (в рамках этого документа) партии (чтобы не списать дважды). Так и делается в типовой.

   Господин ПЖ

12 — 20.07.09 — 13:12

(10) >>(ну типа для строки N учитываем возможные последствия обработки строк M>N)

это как?

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

Товар1 Аналог 0 5
Товар2 Аналог 0 5

А Аналога не 10, его всего 5. Трахать себе мозг «вычитанием» при обходе?

   morozov_sv

13 — 20.07.09 — 13:18

Есть один недоработанный вариант:

ВЫБРАТЬ

   РасходнаяНакладнаяТовары.Номенклатура,

   СУММА(РасходнаяНакладнаяТовары.Количество) КАК Количество,

   СУММА(РасходнаяНакладнаяТовары.Сумма) КАК Сумма,

   РасходнаяНакладнаяТовары.Партия

ПОМЕСТИТЬ СписокТоваров

ИЗ

   Документ.РасходнаяНакладная.Товары КАК РасходнаяНакладнаяТовары

ГДЕ

   РасходнаяНакладнаяТовары.Ссылка = &Ссылка

СГРУППИРОВАТЬ ПО

   РасходнаяНакладнаяТовары.Номенклатура,

   РасходнаяНакладнаяТовары.Партия

;

////////////////////////////////////////////////////////////////////////////////

ВЫБРАТЬ

   СписокТоваров.Номенклатура КАК Номенклатура,

   СписокТоваров.Количество КАК Количество,

   СписокТоваров.Сумма КАК Сумма,

   ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) КАК КоличествоОстаток,

   ЕСТЬNULL(ОстаткиНоменклатурыОстатки.СуммаОстаток, 0) КАК СуммаОстаток,

   ОстаткиНоменклатурыОстатки.Партия КАК Партия,

   ВЫБОР

       КОГДА СписокТоваров.Партия = ОстаткиНоменклатурыОстатки.Партия

           ТОГДА 1

       ИНАЧЕ 0

   КОНЕЦ КАК СортировкаПартий

ИЗ

   СписокТоваров КАК СписокТоваров

       ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиНоменклатуры.Остатки(

               &МоментВремени,

               Номенклатура В

                   (ВЫБРАТЬ РАЗЛИЧНЫЕ

                       А.Номенклатура

                   ИЗ

                       СписокТоваров КАК А)) КАК ОстаткиНоменклатурыОстатки

       ПО СписокТоваров.Номенклатура = ОстаткиНоменклатурыОстатки.Номенклатура

УПОРЯДОЧИТЬ ПО

   Номенклатура,

   СортировкаПартий УБЫВ,

   ОстаткиНоменклатурыОстатки.Партия.МоментВремени УБЫВ

ИТОГИ

   МАКСИМУМ(Количество),

   МАКСИМУМ(Сумма),

   СУММА(КоличествоОстаток),

   СУММА(СуммаОстаток)

ПО

   Номенклатура

;

////////////////////////////////////////////////////////////////////////////////

УНИЧТОЖИТЬ СписокТоваров

Ошибка в том, что если в табличной части будет несколько строк с одной и той же номенклатурой и разной партией, то можно списать в минус…

   Asmody

14 — 20.07.09 — 13:25

(12) можно не трахать. на вскидку:
1. делаем запрос, из которого видно в каком порядке обходить строки и их партии
2. остатки по партиям из запроса 1 сваливаем в кеш
3. обходим результат запроса 1, сверяясь с остатками из кеша, формируем движения, изменяем кеш

при этом учитываем возможные косяки одновременного проведения доков (ну типа ставим где надо ДЛЯ ИЗМЕНЕНИЯ, блокировки и т.п.)

   morozov_sv

15 — 20.07.09 — 13:31

(14) Спасибо, буду пробывать

   Господин ПЖ

16 — 20.07.09 — 15:14

(14) кучеряво это всё для задачи на 1-1,5 часа…

   morozov_sv

17 — 20.07.09 — 15:18

(10) «тоже запросом можно организовать»

вот ломаю голову как это запросом можно сделтаь

   morozov_sv

18 — 21.07.09 — 10:26

Решил с помощью запроса:

Запрос = Новый Запрос(

   «ВЫБРАТЬ

   |    РасходнаяНакладнаяТовары.Номенклатура,

   |    СУММА(РасходнаяНакладнаяТовары.Количество) КАК Количество,

   |    СУММА(РасходнаяНакладнаяТовары.Сумма) КАК Сумма,

   |    РасходнаяНакладнаяТовары.Партия

   |ПОМЕСТИТЬ СписокТоваров

   |ИЗ

   |    Документ.РасходнаяНакладная.Товары КАК РасходнаяНакладнаяТовары

   |ГДЕ

   |    РасходнаяНакладнаяТовары.Ссылка = &Ссылка

   |

   |СГРУППИРОВАТЬ ПО

   |    РасходнаяНакладнаяТовары.Номенклатура,

   |    РасходнаяНакладнаяТовары.Партия

   |;

   |

   |////////////////////////////////////////////////////////////////////////////////

   |ВЫБРАТЬ

   |    СписокТоваров.Номенклатура КАК Номенклатура,

   |    СписокТоваров.Количество КАК Количество,

   |    СписокТоваров.Сумма КАК Сумма,

   |    ВЫБОР

   |        КОГДА ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) > СписокТоваров.Количество

   |            ТОГДА СписокТоваров.Количество

   |        ИНАЧЕ ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0)

   |    КОНЕЦ КАК КоличествоОстаток,

   |    ВЫБОР

   |        КОГДА ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) > СписокТоваров.Количество

   |            ТОГДА ВЫРАЗИТЬ(СписокТоваров.Количество / ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) * ЕСТЬNULL(ОстаткиНоменклатурыОстатки.СуммаОстаток, 0) КАК ЧИСЛО(15, 2))

   |        ИНАЧЕ ЕСТЬNULL(ОстаткиНоменклатурыОстатки.СуммаОстаток, 0)

   |    КОНЕЦ КАК СуммаОстаток,

   |    СписокТоваров.Партия КАК Партия,

   |    1 КАК ДляСортировки,

   |    СписокТоваров.Партия.МоментВремени КАК ПартияМоментВремени

   |ИЗ

   |    СписокТоваров КАК СписокТоваров

   |        ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиНоменклатуры.Остатки(

   |                &МоментВремени,

   |                Номенклатура В

   |                    (ВЫБРАТЬ РАЗЛИЧНЫЕ

   |                        А.Номенклатура

   |                    ИЗ

   |                        СписокТоваров КАК А)) КАК ОстаткиНоменклатурыОстатки

   |        ПО СписокТоваров.Номенклатура = ОстаткиНоменклатурыОстатки.Номенклатура

   |            И СписокТоваров.Партия = ОстаткиНоменклатурыОстатки.Партия

   |

   |ДЛЯ ИЗМЕНЕНИЯ

   |    РегистрНакопления.ОстаткиНоменклатуры.Остатки

   |

   |ОБЪЕДИНИТЬ ВСЕ

   |

   |ВЫБРАТЬ

   |    СписокТоваровБезПартий.Номенклатура,

   |    СписокТоваровБезПартий.Количество,

   |    СписокТоваровБезПартий.Сумма,

   |    ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) — ВЫБОР

   |        КОГДА ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) > ЕСТЬNULL(СписокТоваров.Количество, 0)

   |            ТОГДА ЕСТЬNULL(СписокТоваров.Количество, 0)

   |        ИНАЧЕ ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0)

   |    КОНЕЦ,

   |    ЕСТЬNULL(ОстаткиНоменклатурыОстатки.СуммаОстаток, 0) — ВЫБОР

   |        КОГДА ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) > ЕСТЬNULL(СписокТоваров.Количество, 0)

   |            ТОГДА ВЫРАЗИТЬ(ЕСТЬNULL(СписокТоваров.Количество, 0) / ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) * ЕСТЬNULL(ОстаткиНоменклатурыОстатки.СуммаОстаток, 0) КАК ЧИСЛО(15, 2))

   |        ИНАЧЕ ЕСТЬNULL(ОстаткиНоменклатурыОстатки.СуммаОстаток, 0)

   |    КОНЕЦ,

   |    ОстаткиНоменклатурыОстатки.Партия,

   |    0,

   |    ОстаткиНоменклатурыОстатки.Партия.МоментВремени

   |ИЗ

   |    (ВЫБРАТЬ

   |        СписокТоваров.Номенклатура КАК Номенклатура,

   |        СУММА(СписокТоваров.Количество) КАК Количество,

   |        СУММА(СписокТоваров.Сумма) КАК Сумма

   |    ИЗ

   |        СписокТоваров КАК СписокТоваров

   |    

   |    СГРУППИРОВАТЬ ПО

   |        СписокТоваров.Номенклатура) КАК СписокТоваровБезПартий

   |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиНоменклатуры.Остатки(

   |                &МоментВремени,

   |                Номенклатура В

   |                    (ВЫБРАТЬ РАЗЛИЧНЫЕ

   |                        А.Номенклатура

   |                    ИЗ

   |                        СписокТоваров КАК А)) КАК ОстаткиНоменклатурыОстатки

   |            ЛЕВОЕ СОЕДИНЕНИЕ СписокТоваров КАК СписокТоваров

   |            ПО ОстаткиНоменклатурыОстатки.Номенклатура = СписокТоваров.Номенклатура

   |                И ОстаткиНоменклатурыОстатки.Партия = СписокТоваров.Партия

   |        ПО СписокТоваровБезПартий.Номенклатура = ОстаткиНоменклатурыОстатки.Номенклатура

   |ГДЕ

   |    (ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) — ВЫБОР

   |                КОГДА ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) > ЕСТЬNULL(СписокТоваров.Количество, 0)

   |                    ТОГДА ЕСТЬNULL(СписокТоваров.Количество, 0)

   |                ИНАЧЕ ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0)

   |            КОНЕЦ <> 0

   |            ИЛИ ЕСТЬNULL(ОстаткиНоменклатурыОстатки.СуммаОстаток, 0) — ВЫБОР

   |                КОГДА ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) > ЕСТЬNULL(СписокТоваров.Количество, 0)

   |                    ТОГДА ВЫРАЗИТЬ(ЕСТЬNULL(СписокТоваров.Количество, 0) / ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) * ЕСТЬNULL(ОстаткиНоменклатурыОстатки.СуммаОстаток, 0) КАК ЧИСЛО(15, 2))

   |                ИНАЧЕ ЕСТЬNULL(ОстаткиНоменклатурыОстатки.СуммаОстаток, 0)

   |            КОНЕЦ <> 0)

   |

   |УПОРЯДОЧИТЬ ПО

   |    Номенклатура,

   |    ДляСортировки УБЫВ,

   |    ПартияМоментВремени УБЫВ

   |ИТОГИ

   |    МАКСИМУМ(Количество),

   |    МАКСИМУМ(Сумма),

   |    СУММА(КоличествоОстаток),

   |    СУММА(СуммаОстаток)

   |ПО

   |    Номенклатура

   |;

   |

   |////////////////////////////////////////////////////////////////////////////////

   |УНИЧТОЖИТЬ СписокТоваров»);

   
   Если ФИФО Тогда

       Запрос.Текст = СтрЗаменить(Запрос.Текст,»ПартияМоментВремени УБЫВ»,»ПартияМоментВремени»);

   КонецЕсли;

   
   Запрос.УстановитьПараметр(«МоментВремени», МоментВремени());

   Запрос.УстановитьПараметр(«Ссылка», Ссылка);

   
   ВыборкаНоменклатура = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);

   Пока ВыборкаНоменклатура.Следующий() Цикл

       Если ВыборкаНоменклатура.КоличествоОстаток < ВыборкаНоменклатура.Количество Тогда

           Сообщить(«Не хватает » + (ВыборкаНоменклатура.Количество — ВыборкаНоменклатура.КоличествоОстаток) +

                    » шт товара » + ВыборкаНоменклатура.Номенклатура + «!»,СтатусСообщения.Важное);

           Отказ = Истина;

       Иначе

           ОсталосьСписать = ВыборкаНоменклатура.Количество;

           ВыборкаПартия = ВыборкаНоменклатура.Выбрать();

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

               Движение = Движения.ОстаткиНоменклатуры.ДобавитьРасход();

               Движение.Период = Дата;

               Движение.Номенклатура = ВыборкаПартия.Номенклатура;

               Движение.Партия = ВыборкаПартия.Партия;                

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

               Движение.Сумма = Движение.Количество / ВыборкаПартия.КоличествоОстаток * ВыборкаПартия.СуммаОстаток;

               ОсталосьСписать = ОсталосьСписать — Движение.Количество;

           КонецЦикла;

       КонецЕсли;

   КонецЦикла;

   Kashemir

19 — 21.07.09 — 10:50

СписокТоваров.Количество / ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0)

Опасные конструкции по тексту ;-)

  

morozov_sv

20 — 21.07.09 — 11:01

(19) Согласен, в данном случае ЕСТЬNULL не нужен, т.к. есть условие

ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток, 0) > СписокТоваров.Количество

где «СписокТоваров.Количество» берется из табличной части и всегда > 0.

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

как проводить документы с отрицательными остатками. Писать их в определенную партию? или просто оставлять без партии? А затем при поступлении списывать этот отрицательный остаток? Или писать в еще в один регистр? Прошу помощи не могу разобраться


Чтобы получить от этой работы максимум пользы, старайтесь ответить на вопросы перед тем, как смотреть следующий шаг.

Вот фрагмент задачи 1.12 из сборника для подготовки к экзамену «1С:Специалист»:


«Компания занимается оптовой торговлей. Принята следующая схема
работы: поступление товаров отражается документом «Приходная накладная». По
предварительной договоренности с покупателем менеджер может оформить
резерв (документ «Резервирование товара»), причем наличие товара в этот
момент не важно, товар может отсутствовать. Непосредственно отгрузка товара
покупателю отражается документом «Расходная накладная», при этом происходит
снятие резерва.

Учет товаров ведется в разрезе складов. В документах «Приходная
накладная» и Расходная накладная» склад только один (склад – реквизит шапки).
При проведении расходной накладной необходимо проверить наличие
товара на складе и «свободного» (будет описано далее) товара. В том случае,
когда товара недостаточно, документ не проводится и выводится
соответствующее сообщение об ошибке.

У каждого менеджера есть приоритет, чем больше приоритет, тем более
ответственный менеджер и тем важнее его продажи. Таким образом, если два
менеджера одновременно зарезервировали один и тот же товара, то менеджер с
большим приоритетом может продать товар, зарезервированный менеджером с
меньшим приоритетом. Менеджер с низким приоритетом продать чужой резерв
не имеет права. Таким образом, «свободный» товар менеджера определяется как
товар на всех складах минус резерв всех остальных менеджеров с приоритетом
большим либо таким же, как и у текущего менеджера.

Приоритет устанавливается для каждого менеджера индивидуально и
может меняться не чаще чем 1 раз в месяц. При продаже необходимо
использовать приоритет менеджера, актуальный на дату продажи.
Себестоимость товара рассчитывается как средняя по складу.»

Недостаток этой задачи состоит в том, что не сформулировано чётко, как должен сниматься резерв.
В контексте этой задачи товар можно разделить на четыре категории:

  1. Зарезервированный менеджерами с приоритетом, высшим ии равным приоритету продающего менеджера
  2. Зарезервированный менеджерами с приоритетом, меньшим приоритета продающего менеджера
  3. Зарезервированный самим менеджером
  4. Никем не зарезервированный

Товар из первой категории продавать нельзя. Что касается товара остальных категорий, то давайте добавим своё условие:

«При продаже товара снятие резерва происходит так: Сначала снимается резерв продающего менеджера. Затем учитывается никем не зарезервированный товар (если он есть). И в последнюю очередь снимается резерв остальных менеджеров (то есть менеджеров с низшим приоритетом), причём сначала снимается резерв менеджеров с самым низким приоритетом.»

Начнём решать. Сделаем регистр накопления «Остатки номенклатуры», измерения «Номенклатура», «Склад», ресурсы «Количество», «Сумма».

Регистр накопления «Резервы номенклатуры», измерения «Номенклатура», «Менеджер», ресурс «Количество».

Регистр сведений «Приоритеты менеджеров», периодический в пределах месяца, режим записи независимый, одно измерение «Менеджер», один ресурс «Приоритет».

Документ «Приходная накладная» имеет реквизит «Склад» и табличную часть «Остатки номенклатуры» и делает движения в регистр «Остатки номенклатуры». Обработку его проведения сделаем конструктором.
Чтобы увидеть полный код обработки проведения документа «Приходная накладная», кликните здесь.

Также конструктором сделаем обработку проведения документа «Резервирование товара». Он будет делать движения в регистр «Резервы номенклатуры», и будет иметь реквизит «Менеджер» и табличную часть «Остатки номенклатуры» (Номенклатура, Количество).
Чтобы увидеть полный код обработки проведения документа «Приходная накладная», кликните здесь.

Документ «Расходная накладная» имеет реквизиты «Склад» и «Менеджер», Табличную часть «Остатки номенклатуры» (Номенклатура, Количество).

Вся «соль» этой задачи в обработке проведения Расходной накладной. Что должна делать Расходная накладная? Списывать номенклатуру в регистре «Остатки номенклатуры» и, при необходимости, в регистре «Резервы номенклатуры». Какая информация нам для этого потребуется?

  • Потребуются данные документа.
  • Потребуется приоритет продающего менеджера.
  • Он потребуется для того, чтобы получить список менеджеров, приоритет которых ниже, чем у данного менеджера.

  • Потребуется количество остатка каждого вида списываемой номенклатуры на данном складе.
  • Также, для списания, потребуется соответствующая сумма остатка на данном складе.

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

    1. количество, которое зарезервировано продающим менеджером
    2. каждым из менеджеров, приоритет которых ниже, чем у данного
    3. никем не зарезервировано.

Давайте начнём делать обработку проведения. Что напишем сначала?

Запишем пустые наборы записей в регистры, на случай, если там имеются записи этого документа. Затем сделаем запрос к табличной части документа и сохраним её данные во временной таблице. Выберем из неё номенклатуру и заблокируем регистры по значениям этой номенклатуры.



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

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

Блокировка.Заблокировать();
 

Теперь давайте выберем и поместим во временную таблицу всех менеджеров, чей приоритет меньше приоритета данного менеджера. Причём сделаем это одним пакетным запросом. Попробуйте придумать такой запрос, прежде чем смотреть дальше.


	Запрос.Текст = 
		"ВЫБРАТЬ ПЕРВЫЕ 1
		|	ПриоритетыМенеджеровСрезПоследних.Приоритет КАК Приоритет
		|ПОМЕСТИТЬ ВТПриоритетЭтогоМенеджера
		|ИЗ
		|	РегистрСведений.ПриоритетыМенеджеров.СрезПоследних(&МоментВремени, Менеджер = &Менеджер) КАК ПриоритетыМенеджеровСрезПоследних
		|
		|ИНДЕКСИРОВАТЬ ПО
		|	Приоритет
		|;
		|
		|////////////////////////////////////////////////////////////////////////////////
		|ВЫБРАТЬ
		|	ПриоритетыМенеджеровСрезПоследних.Менеджер КАК Менеджер,
		|	ПриоритетыМенеджеровСрезПоследних.Приоритет КАК Приоритет
		|ПОМЕСТИТЬ МенеджерыНизкогоПриоритета
		|ИЗ
		|	ВТПриоритетЭтогоМенеджера КАК ВТПриоритетЭтогоМенеджера
		|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПриоритетыМенеджеров.СрезПоследних(&МоментВремени, ) КАК ПриоритетыМенеджеровСрезПоследних
		|		ПО ВТПриоритетЭтогоМенеджера.Приоритет > ПриоритетыМенеджеровСрезПоследних.Приоритет
		|
		|ИНДЕКСИРОВАТЬ ПО
		|	Менеджер
		|;
		|

 
 

Ранее мы сделали временную таблицу «ВТсписокНоменклатуры». Давайте сделаем на основе этой таблицы другую временную таблицу (назовём её «ВТВсёПоНоменклатуре»), в которой соберём информацию, связанную с номенклатурой

  • количество, зарезервированное данным менеджером
  • количество, которое никем не зарезервировано (а кстати, как его вычислить?)
  • количество на складе
  • сумму на складе

Пусть это будет третий запрос пакета.


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

Количество, которое никем не зарезервировано мы вычислили как разницу между полным остатком и полным резервом. Для того, чтобы их получить, мы прописали в параметрах виртуальных таблиц только момент времени и список номенклатуры. Чтобы получить резерв данного менеджера, пришлось обратиться к виртуальной таблице остатков регистра «Резервы номенклатуры» ещё раз, но уже добавив параметр «Менеджер».

Предлагаю также добавить в имеющуюся временную таблицу «ВТМенеджерыНизкогоПриоритета» данные по резервам по каждому менеджеру из этой таблицы каждой номенклатуры из документа, и создать на её основе другую временную таблицу «ВТРезервыМенеджеров».


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

Теперь мы можем объединить временные таблицы «ВТВсёПоНоменклатуре» и «ВТРезервыМенеджеров» в финальном запросе пакета, который выберет всё, что нам надо. Какое соединение используем?

Используем левое соединение по номенклатуре, слева будет «ВТВсёПоНоменклатуре», поскольку нам надо будет обходить всю номенклатуру. В таблице же «ВТРезервыМенеджеров» может быть несколько значений для той или иной номенклатуры (то есть несколько менеджеров, имеющих по ней резервы), а может не быть ни одного. Из этого следует важный вывод: придётся прописать в запросе итоги, чтобы в итоговой выборке обходить номенклатуру, в в выборке детальных записей обходить менеджеров.

Как пропишем итоги? Как произведём упорядочивание?


	|ВЫБРАТЬ
		|	ВТВсёПоНоменклатуре.Номенклатура КАК Номенклатура,
		|	ВТВсёПоНоменклатуре.КоличествоПоДокументу КАК КоличествоПоДокументу,
		|	ВТВсёПоНоменклатуре.НезарезервированноеКоличество КАК НезарезервированноеКоличество,
		|	ВТВсёПоНоменклатуре.КоличествоЗарезервированноеЭтимМенеджером КАК КоличествоЗарезервированноеЭтимМенеджером,
		|	ВТВсёПоНоменклатуре.КоличествоНаСкладе КАК КоличествоНаСкладе,
		|	ВТВсёПоНоменклатуре.СуммаНаСкладе КАК СуммаНаСкладе,
		|	ВТРезервыМенеджеров.Менеджер КАК Менеджер,
		|	ВТРезервыМенеджеров.Приоритет КАК Приоритет,
		|	ЕСТЬNULL(ВТРезервыМенеджеров.РезервМенеджераПоНоменклатуре, 0) КАК РезервМенеджераПоНоменклатуре
		|ИЗ
		|	ВТВсёПоНоменклатуре КАК ВТВсёПоНоменклатуре
		|		ЛЕВОЕ СОЕДИНЕНИЕ ВТРезервыМенеджеров КАК ВТРезервыМенеджеров
		|		ПО ВТВсёПоНоменклатуре.Номенклатура = ВТРезервыМенеджеров.Номенклатура
		|
		|УПОРЯДОЧИТЬ ПО
		|	Номенклатура,
		|	Приоритет
		|ИТОГИ
		|	МАКСИМУМ(КоличествоПоДокументу),
		|	МАКСИМУМ(НезарезервированноеКоличество),
		|	МАКСИМУМ(КоличествоЗарезервированноеЭтимМенеджером),
		|	МАКСИМУМ(КоличествоНаСкладе),
		|	МАКСИМУМ(СуммаНаСкладе)
		|ПО
		|	Номенклатура";

В итогах я прописал агрегатную функцию МАКСИМУМ, хотя думаю, подошли бы и функции МИНИМУМ, СРЕДНЕЕ. Для нас важно, чтобы в итогах не изменились те значения, которые были в основном теле запроса. Упорядочивание я произвёл сначала по номенклатуре, хотя само по себе это упорядочивание для нас не важно. Важно упорядочивание по приоритету, так как сперва должны списываться резервы с низшим приоритетом.
РезервМенеджераПоНоменклатуре я обернул в функцию ЕСТЬNULL, так как резервов менеджеров может не быть, и тогда при обходе выборки будет некорректно работать сравнение.

Всё, с запросом закончили. Пора делать выборку. Как спишем остатки номенклатуры? Какую проверку проведём?


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


Списание остатков произвёл «классическим» способом, с проверкой остатков на складе, с полным списанием суммы, если количество в документе равно количеству остатка.

Теперь пора списывать резервы. Что следует сделать в первую очередь? Как учесть тот факт, что любого вида резервов, которые мы будем последовательно списывать, может и не быть?

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


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

	    КонецЕсли; 
		
		Если НадоСписатьРезервов > 0 Тогда
		
			ВыборкаДетальныезаписи = ВыборкаИтог.Выбрать();

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

Однако после прохождения цикла по детальным записям может оказаться, что переменная «НадоСписатьРезервов» всё равно больше нуля. Что будем делать тогда?

Если переменная «НадоСписатьРезервов» после всех списаний больше нуля, то резервов не хватает, и придётся отказаться от проведения. Также надо сообщить об этом пользователю. Где напишем отказ?

Отказ и сообщение напишем после окончания цикла по детальным записям.


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

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


Чтобы увидеть полный код обработки проведения документа «Расходная накладная», кликните здесь.

Конфигурацию решения задачи можно скачать здесь.

Об ошибках сообщайте по электронной почте obuchmat@mail.ru

Вот ещё одна задача

Наверх

На домашнюю страницу

Учебный курс: Подготовка на 1С:Специалист по платформе 1С:Предприятие 8.3

В каждой экзаменационной задаче, которая требует автоматизировать учет номенклатуры, необходимо реализовать поступление товаров в компанию. Такая подзадача встречается в следующих задачах сборника для подготовки к экзамену «1С:Специалист по платформе»: № 1.1, 1.2, 2.9, 2.14 и других.

Рассмотрим, как быстро реализовать данный функционал.

Постановка задачи:

Компания занимается оптовой торговлей. Поступление товаров отражается документом «Приходная накладная».

К сожалению, у Вас недостаточно прав для дальнейшего просмотра.

Если Вы приобрели курс, но еще не активировали токен — пожалуйста, активируйте доступ по инструкциям, высланным на Ваш email после покупки.

Если Вы не залогинены на сайте — залогиньтесь, вернитесь на эту страницу и обновите ее.

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

Комментарии закрыты

Понравилась статья? Поделить с друзьями:

Другие крутые статьи на нашем сайте:

0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии