Установка себестоимости при пробитии чека. Розница 3.0

Я уже ранее делал расчет себестоимости при пробитии чека для УТ 11.4. Почему-то 1С настойчиво избегает решать эту проблему.

Ну что же, сделал и для Розницы 3.0.

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

Если себестоимости нет, ставлю учетную цену.

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

В принципе, оказалось всё проще чем в УТ 11.4. Регистр Продажи уже заполнен, нужно только проставить себестоимость.

Вызов в чеке и чеке на возврат:

&После("ОбработкаПроведения")
Процедура M_ОбработкаПроведения(Отказ, РежимПроведения)
	дор_С.дор_ДополительныеДвиженияЧекаОбработкаПроведения(ЭтотОбъект, Отказ, РежимПроведения);
КонецПроцедуры

Код общего модуля:

Процедура дор_ДополительныеДвиженияЧекаОбработкаПроведения(Источник, Отказ, РежимПроведения) Экспорт
	//Осипов 2021-02-04 для УТ, адаптировано для Розницы 3.0 2023-04-27
	
	Если Отказ Тогда
		Возврат 
	КонецЕсли;
	
	//У архивных ничего не дописываем
	Если Источник.Архивный Тогда
		Возврат;
	КонецЕсли;    
	
	МД = Метаданные.НайтиПоТипу(ТипЗнч(Источник));
	
	Если МД = Метаданные.Документы.ЧекККМ Тогда
		ЭтоПродажа = Истина;
	Иначе
		ЭтоПродажа = Ложь;
	КонецЕсли;
	//Только по пробитым чекам для обычных чеков, для возврата статуса нет
	Если ЭтоПродажа И Источник.Статус <> Перечисления.СтатусыЧековККМ.Пробит Тогда
		Возврат;
	КонецЕсли;    

	
	//Отключаем контроль прав
	УстановитьПривилегированныйРежим(Истина);
	

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

	Для Каждого МЗ ИЗ НЗ Цикл
		
		ИскСтрока = ТЗПродажи.Найти(МЗ.Номенклатура, "Номенклатура");
		Если ИскСтрока = Неопределено Тогда
			Продолжить;
		КонецЕсли;     
		
		МЗ.Сумма = ИскСтрока.Себестоимость;
		МЗ.СуммаБезНДС = ИскСтрока.СебестоимостьБезНДС;
		
	КонецЦикла;
	
	НЗ.Записать();

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

UPD 2023-05-24: Добавил списание запасов, т.к. без этого происходило удорожание остатков — запасы списывались по количеству, не по сумме.

UPD 2023-04-29: заменил получение остатков на дату документа получением остатков на границу документа, т.к. иначе могут попасть в остатки движения по самому документу. И для ЧекаККМ возврат изменил логику, т.к. там нет статуса пробит.

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

С НДС не заморачивался, клиент на патенте, оставил код закомментированным.

Движения с себестоимостью по продаже:

Движения с себестоимостью по возврату:

Среда: 3.0.3.147 Объем: 1 час.

fixin

Программирую на 1С с 1999 года. В 1С просто Гений. В 2020 году ушел из офиса на вольные хлеба фриланса. Принимаю заказы.

Читайте также:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *