Задача из сборника задач для подготовки к экзамену "1С:Специалист" по платформе "1С:Предприятие 8.3", редакция 2014 год.

Условие задачи:

Данный текст доступен только для авторизованных пользователей.

Решение.

Нам потребуются следующие объекты конфигурации:

  • Справочники: Склады, Номенклатура, Контрагенты;
  • Документы: ПриходнаяНакладная, РасходнаяНакладная.

Также создадим объекты:

  • Регистр сведений НаценкаПоСкладам (Измерение: Склад; Ресурс: ПроцентНаценки). В этом регистре будем хранить наценку по конкретному складу.
  • Регистр накопления ОстаткиИСебестоимость ( Измерения: Номенклатура, Склад; Ресурсы: Количество, Стоимость).

Код в модуле объекта документа ПриходнаяНакладная:

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

	КонецЦикла;

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

Код в модуле объекта документа РасходнаяНакладная:

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

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


Процедура РеализацияТовара(Отказ)
		
	ТорговаяТочка = Склад;
	ОтделЗакупок = Справочники.Склады.НайтиПоКоду("000000001");
	
	//ТаблицаЗначений для формирования документа перемещения, если потребуется
	ТЗДляНовогоДокумента = Новый ТаблицаЗначений;
			ТЗДляНовогоДокумента.Колонки.Добавить("Номенклатура",,"Номенклатура",);
			ТЗДляНовогоДокумента.Колонки.Добавить("Количество",,"Количество",);
			ТЗДляНовогоДокумента.Колонки.Добавить("Сумма",,"Сумма",);

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

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

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


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

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

Запрос для отчёта ДвижениеТоваров:

ВЫБРАТЬ
	ОстаткиИСебестоимостьОстаткиИОбороты.Номенклатура,
	ОстаткиИСебестоимостьОстаткиИОбороты.Склад,
	СУММА(ОстаткиИСебестоимостьОстаткиИОбороты.КоличествоНачальныйОстаток) КАК КоличествоНачальныйОстаток,
	СУММА(ОстаткиИСебестоимостьОстаткиИОбороты.КоличествоКонечныйОстаток) КАК КоличествоКонечныйОстаток,
	СУММА(ОстаткиИСебестоимостьОстаткиИОбороты.КоличествоПриход) КАК КоличествоПриход,
	СУММА(ОстаткиИСебестоимостьОстаткиИОбороты.КоличествоРасход) КАК КоличествоРасход,
	СУММА(ОстаткиИСебестоимостьОстаткиИОбороты.СтоимостьНачальныйОстаток) КАК СтоимостьНачальныйОстаток,
	СУММА(ОстаткиИСебестоимостьОстаткиИОбороты.СтоимостьКонечныйОстаток) КАК СтоимостьКонечныйОстаток,
	СУММА(ОстаткиИСебестоимостьОстаткиИОбороты.СтоимостьПриход) КАК СтоимостьПриход,
	СУММА(ОстаткиИСебестоимостьОстаткиИОбороты.СтоимостьРасход) КАК СтоимостьРасход
ИЗ
	РегистрНакопления.ОстаткиИСебестоимость.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, , , ) КАК ОстаткиИСебестоимостьОстаткиИОбороты

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

Комментарии   

0 #1 Altavista- 17.09.2018 20:51
Не бесспорное решение:
1. В регистр логичнее добавить 2й ресурс ("вТрансфертныхЦенах");
2. РС "Наценки"? Однозначно, нет. Это реквизит справочника;
3. Реквизита "Контрагент" в условии задачи тоже нет и не нужно его домысливать.
4. В "Подразделения" добавить булево "ТорговаяТочка", предопределённый элемент "ОтделЗакупок" там уже есть;
5. В расходной в реквизите "подразделение" задать параметр выбора "торговаяТочка"= Истина, добавить булево "этоперемещение". И танцы с бубном по определению типа значения и поиска по коду можно смело убирать;
6. В сообщении + Выборка.Номенклатура + на экзамене трактуется как ошибка запроса в цикле: нужно получать в запросе отдельно представление номенклатуры;
7. При добавлении * (1 + Выборка.ПроцентНаценки/100)), "проблема копеек" возвращается.
8. Блокировку нужно установить также и на подразделения: ОтделЗакупок или ОтделЗакупок + выбранная торговая точка.
Цитировать