Списание по партиям, когда документ партии указан в шапке документа

1. Dermidont 11 26.08.20 14:57 Сейчас в теме
Доброе утро, друзья!
Пытаюсь решить задачу по партионному учёту, вроде сделал, но хотелось бы услышать мнение специалистов, о возможных допущенных мною недостатках. По условию задачи складской учёт не ведётся, в первую очередь товар должен списываться из указанной в шапке партии. В случае, если товара по выбранной партии не хватает, необходимо списывать по методу фифо, либо лифо. После размышления над условием задачи решил пакетом запросов получить все данные, а вот движения делать за два цикла, первый цикл по остаткам в выбранном документе партии, второй - по всем остальным остаткам, исключая остатки по выбранной партии. Текст обработки проведения:

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

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

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


И на всякий случай выгрузка каркасной конфигурации во вложении. Буду признателен за любую конструктивную критику.
Прикрепленные файлы:
1Cv8.dt
По теме из базы знаний
Найденные решения
2. DanDy 55 26.08.20 17:10 Сейчас в теме
тут достаточно 1 запроса и 1 цикла.
Если вы изучали примеры решения то обратите на это внимание.

решается всё элементарно

Получаете запросом остатки в разрезе партий.
Вводите поле "Приоритет" например (прямо в запросе) которое равно 1 когда партия остатка совпадает с партией из ШАПКИ и равно 0 Когда Партия не совпадает.

Ну у далее настраиваете порядок результата ПРИОРИТЕТ по УБЫВАНИЮ, а партия в зависимости от ФИФО или ЛИФО.

Ну и далее собственно делаем движения аналогично задачи без приоритетной партии (надеюсь вы это уже умеете)
serverstar; Hogyoku; +2 Ответить
Остальные ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. DanDy 55 26.08.20 17:10 Сейчас в теме
тут достаточно 1 запроса и 1 цикла.
Если вы изучали примеры решения то обратите на это внимание.

решается всё элементарно

Получаете запросом остатки в разрезе партий.
Вводите поле "Приоритет" например (прямо в запросе) которое равно 1 когда партия остатка совпадает с партией из ШАПКИ и равно 0 Когда Партия не совпадает.

Ну у далее настраиваете порядок результата ПРИОРИТЕТ по УБЫВАНИЮ, а партия в зависимости от ФИФО или ЛИФО.

Ну и далее собственно делаем движения аналогично задачи без приоритетной партии (надеюсь вы это уже умеете)
serverstar; Hogyoku; +2 Ответить
3. Dermidont 11 26.08.20 17:50 Сейчас в теме
Понятно, спасибо. Сейчас буду переделывать. Я скачал билеты с решениями, но в этих билетах нет самих билетов, только описание решения и само решение. А задачи решаю из задачника.
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот