Оперативный учёт. Задача 1.1

Оперативный учёт. Задача 1.1

Объекты с которыми будем работать и их настройка

Справочник - Номенклатура.

В условии задачи сказано, что могут оказываться как услуги так и товары.
Чтобы отличать какая номенклатура является услугой, а какая товаром создадим у справочника реквизит “ВидНоменклатуры” с типом “ПеречислениеСсылка.ВидыНоменклатуры”. Перечисление “ВидыНоменклатуры” присутствует в каркасной конфигурации изначально.

01.png
02.png

Документ - ПриходнаяНакладная.

Если при продаже мы можем оказывать и товары и услуги (доставка, ремонт, установка), то при поступлении услуг быть не должно. Например, нельзя оприходовать услугу “ремонт” в количестве 3 штуки.

Для того чтобы в исключить в приходной накладной добавление услуги у реквизита табличной части “Номенклатура” установим параметр выбора:

  • Имя - отбор по реквизиту “ВидНоменклатуры” справочника “Номенклатура”
  • Значение - перечисление “ВидыНоменклатуры” а именно “Товар”

03.png
04.png
05.png

Документ - РасходнаяНакладная

Состав этого документа подходит для решения задачи.
Для обоих документов на закладке “Движения” указываем регистры которые будут формировать движения.

06.png
07.png

Регистры сведений - УчетнаяПолитика.

Для определения метода списания себестоимости создадим регистр.
Из постановки задачи следует что учетная политика действует год и может быть либо FIFO либо LIFO.

FIFO (First In, First Out – «Первым пришёл — первым ушёл») и LIFO (Last In, First Out – «последним пришёл — первым ушёл») — методы оценки товарно-материальных ценностей. При учёте запасов однородного товара, купленного в разное время по разной цене, приходится определять: что выдавать первым; и физически (на складе), и на бумаге (в бухгалтерских книгах). По методу FIFO первым выдаётся самый старый из пришедших товаров, по методу LIFO — самый новый.

Поскольку учетная политика действует год, периодичность нашего регистра тоже будет “в пределах года”

08.png

Описывать разрезы в которых мы будем хранить метод списания себестоимости нам не нужно, а значит измерения в этом регистре нам не нужны. Нам достаточно одного ресурса с типом “ПеречислениеСсылка.УчетнаяПолитика”.

Перечисление “УчетнаяПолитика” изначально присутствует в каркасной конфигурации.

09.png
10.png

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

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

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

Регистр присутствует в каркасной конфигурации изначально.

На закладке “Прочее” включим у регистра свойство “Разрешить разделение итогов” оно влияет на параллельность работы системы и в каркасной конфигурации по умолчанию выключено.

При создании нового регистра, данное свойство по умолчанию включено.

11.png

Посмотрев на отчет, становится понятно, что остатки должны быть в разрезе номенклатуры и партии, а значит измерения будет два:

  • Номенклатура - присутствует в каркасной конфигурации изначально
  • Партия - создаем измерение с типом “ДокументСсылка.ПриходнаяНакладная” поскольку партией является документ “ПриходнаяНакладная”
  • Состав ресурсов также определяется с помощью отчета:
    • Количество - присутствует в каркасной конфигурации изначально
    • Стоимость (или Себестоимость) - создаем ресурс с типом число, длина 12, точность 2 (как у реквизита “Сумма” в табличных частях документов “ПриходнаяНакладная” и “РасходнаяНакладная”

Прибыль - будет вычисляться при выводе отчета, поэтому в регистр не добавляем.
12.png
13.png
14.png
Продажи

Данный регистр отсутствует в каркасной конфигурации, его создаем сами. Необходимость этого регистра определяется с помощью отчета который требуется для решения задачи. Поскольку в заголовке отчета написано “Продажи с 01.01.2010 по 31.03.2010” мы с вами выбираем вид регистра “Обороты”.

Для того чтобы определить вид регистра, нужно выбрать один из подходящих ответов:

  • Сколько чего-то накоплено, на какой-то момент времени - значит вид регистра “Остатки”
  • Сколько чего-то накоплено, за какой-то период - значит вид регистра “Обороты”

15.png

Наличие ресурсов и измерений мы с вами уже научились определять (подсказкой является отчет).

16.png

Перечисления.

Перечисления УчетнаяПолитика и ВидыНоменклатуры в каркасной конфигурации присутствуют изначально и для решения задачи нет никакой необходимости их редактировать.

Отчеты.

По умолчанию отчетов в каркасной конфигурации нет, они создаются вручную. Создадим два отчета ПродажаТоваров и ОстаткиНоменклатуры Для каждого отчета создадим схему компоновки данных и пока на этом закончим.

17.png
18.png

Проведение документов “Приходная накладная” и “Расходная накладная”.

Приходная накладная

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

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

Расходная накладная

Для проведения этого документа, необходимо сначала определиться с выбором методики проведения. В этом нам поможет блок-схема представленная ниже.

19.png

Данных в самом документе нам недостаточно, поэтому использовать будем традиционную методику проведения.

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

Отчеты.

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

Продажа товаров

20.png
21.png
22.png
23.png
24.png

Остатки номенклатуры

25.png

Чтобы воспроизвести отчет из задачи необходимо партию привести к определенному формату. Если вывести номер партии через “Партия.Номер” то будут отображаться лидирующие нули, но в отчете из задачи лидирующих нулей нет. Для этого создаем общий модуль “НумерацияОбъектов” который будем использовать в выражении представления.

Функция НомерНаПечать(Стр) Экспорт
	Пока Лев(Стр, 1) = "0" Цикл
		Стр = Сред(Стр, 2);
	КонецЦикла;
	Возврат Стр;
КонецФункции
26.png
27.png
28.png
29.png
Ссылка на скачивание dt
{{ ELEMENTS.length }}
Наименование
Цена
Количество
Артикул : {{ item.MODEL }}
{{ item.STATUS }}
{{ item.PRICE }} руб.
{{ item.OLD_PRICE }} руб.
- +
Вы экономите: {{ DATA.TOTAL_DISCOUNT_SUM }} руб.
Итого: {{ DATA.TOTAL_SUM }} руб.
Вы можете вернуться в каталог и продожить покупки
Вернуться и продолжить покупки