Справочники.Валюты.ПустаяСсылка() в проводках у не валютных счетов или зависшие развернутые остатки по счетам

Публикация № 873005

Обработки - Обработка документов

обработка Справочники.Валюты.ПустаяСсылка Справочники.ПодразделенияОрганизации.ПустаяСсылка

2
Описана причина появление пустых ссылок валюты по невалютным счетам. Пример решения этой проблемы. Платформа - 8.3.10.2580. Конфигурация - БП 3.0.60.46.

Похожие статьи:

//infostart.ru/public/349891/

//infostart.ru/public/348852/

//infostart.ru/public/158661/

В этой статье даны пояснения причины и приведен более универсальный код.

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

Причина: если оборотки формировать с выводом валюты, тогда становится все понятно - у невалютных счетов вместо значения NULL появилась пустая ссылка валюты.

Что произошло? Оказалось, что перед этим выполнялась процедура поиска и замены. Именно она делает такой беспорядок.

Кто виноват? В типовом коде допущена ошибка:

Процедура ЗаменитьВКоллекцииСтрок(ВидКоллекции, ИмяКоллекции, Объект, Коллекция, Знач СписокПолей, Знач ПарыЗамен)
	РабочаяКоллекция = Коллекция.Выгрузить();
	Модифицировано = Ложь;
	
	Для Каждого Строка Из РабочаяКоллекция Цикл
		
		Для Каждого КлючЗначение Из СписокПолей Цикл
			Имя = КлючЗначение.Ключ;
			ЦелеваяСсылка = ПарыЗамен[ Строка[Имя] ];
			Если ЦелеваяСсылка <> Неопределено Тогда
				ЗарегистрироватьФактЗамены(Объект, Строка[Имя], ЦелеваяСсылка, ВидКоллекции, ИмяКоллекции, РабочаяКоллекция.Индекс(Строка), Имя);
				Строка[Имя] = ЦелеваяСсылка;
				Модифицировано = Истина;
			КонецЕсли;
		КонецЦикла;
		
	КонецЦикла;
	
	Если Модифицировано Тогда
		Коллекция.Загрузить(РабочаяКоллекция);
	КонецЕсли;
КонецПроцедуры

Проблема в параметре "Коллекция", там сидит набор записей. У набора записей, если у валюты стоит NULL, то в момент выгрузки в таблицу значения вместо NULL будет Справочники.Валюта.ПустаяСсылка. ВАЖНО! Такое поведение будет только если поиск и замену выполнять в режиме ОбменДанными.Загрузка = Истина!! То есть, если набор записей записать в обычном режиме, то проблемы не будет.

Но почему такое поведение? Логика платформы ясна: если данные приходят в режиме обмена данными, то значит проверять ничего не надо, ведь по идее такие же данные должны быть в другом узле и мы не может допустить рассинхронизацию. Но в данном случае это конечно ошибка платформы. Возможно в более новых версиях эту ошибку устранили.

 Как исправить? 

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

Как защититься от этой проблемы? Либо помнить чем грозит поиск и замена в режиме обмена данными, либо в процедуре "ПередЗаписью" регистра бухгалтерии добавить проверку, обмен конечно немного замедлится, но так точно больше проблем на возникнет (вдруг еще какой сюрприз притаился):

	Если ОбменДанными.Загрузка Тогда
		//<-- Wadus
		Для каждого Проводка из ЭтотОбъект Цикл
			Если НЕ (ЗначениеЗаполнено(Проводка.СчетДт) И Проводка.СчетДт.Валютный) Тогда
				Проводка.ВалютаДт = NULL;
			КонецЕсли;
			Если НЕ (ЗначениеЗаполнено(Проводка.СчетКт) И Проводка.СчетКт.Валютный) Тогда
				Проводка.ВалютаКт = NULL;
			КонецЕсли;
			
			Если НЕ (ЗначениеЗаполнено(Проводка.СчетДт) И Проводка.СчетДт.УчетПоПодразделениям) Тогда
				Проводка.ПодразделениеДт = NULL;
			КонецЕсли;
			Если НЕ (ЗначениеЗаполнено(Проводка.СчетКт) И Проводка.СчетКт.УчетПоПодразделениям) Тогда
				Проводка.ПодразделениеКт = NULL;
			КонецЕсли;
			
			
			//для забалансовых, иначе по незаполненному счету будут пустые ссылки
			//некритично, но не по фэн-шую
			Если Не ЗначениеЗаполнено(Проводка.СчетДт) Тогда
				Проводка.ВалютаДт = NULL;
				Проводка.ПодразделениеДт = NULL;
			КонецЕсли;
			
			Если Не ЗначениеЗаполнено(Проводка.СчетКт) Тогда
				Проводка.ВалютаКт = NULL;
				Проводка.ПодразделениеКт = NULL;
			КонецЕсли;
		КонецЦикла;
		//--> Wadus
		Возврат;
	КонецЕсли;

Либо изменить функцию в модулях поиска и замены. Пример приводить уже не буду.

Если помог - смело ставь + ! Буду благодарен )

Спасибо фирме 1С за такие интересные задачки! ))

 

P.S. добавил еще подразделения.

P.S.S. добавил забалансовые счета для обработки

2

Скачать файлы

Наименование Файл Версия Размер
Ремонт валюты/подразделений в проводках
.epf 6,52Kb
24.07.18
2
.epf 6,52Kb 2 Скачать

См. также

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Древо
1. ZOMI 415 23.07.18 17:50 Сейчас в теме
Баян, и баян недоделанный. Там еще обычно каша по счетам со счетами где нет учета по подразделениям начинается.

В комментах к теме https://infostart.ru/public/158661/ правильные причины возникновения такой проблемы
3. Wadus161 15 23.07.18 20:22 Сейчас в теме
(1)Могли бы Вы пояснить почему баян "недоделанный"? Статья на которую Вы ссылаетесь не объясняет причину, а я объяснил. Статья на которую Вы ссылаетесь вообще не приводит пример кода, а я весь код выложил. Вообще я нигде не нашел объяснения, поэтому и решил поделиться с сообществом.
5. ZOMI 415 23.07.18 20:39 Сейчас в теме
(3) "недоделанный" в смысле, что обычно проблема и с валютой и с подразделением...
Причины как я и указал в (1) озвучены в комментах - ваше объяснение неполное тк данная проблема есть в базах, которые вообще ни с кем не обмениваются данными...
6. Wadus161 15 23.07.18 21:09 Сейчас в теме
(5) Согласен, с подразделениями такая же история. Сейчас дополню. Что касается обмена данными, скорее всего Вас смутила фраза "Такое поведение будет только если поиск и замену выполнять в режиме ОбменДанными.Загрузка = Истина". Обмен данных тут не причем. Имеется ввиду следующее:
Прикрепленные файлы:
2. MSK_Step 20 23.07.18 19:25 Сейчас в теме
Я делал проще,
ДвиженияДокумента = о.Движения.Хозрасчетный;
ДвиженияДокумента.Прочитать();
	
ДвиженияДокумента.Записать();

все встает на свои места

в запросе только искал на <> null
4. Wadus161 15 23.07.18 20:33 Сейчас в теме
(2)Ваш способ не подойдет в том случае если надо сделать запись в режиме ОбменДанными.Загрузка = Истина, В этом режиме лучше писать для скорости, чтобы пропустить обработчики события в модуле объекта регистра бухгалтерии.
7. MSK_Step 20 24.07.18 12:02 Сейчас в теме
(4) Ваш не подойдет в других случаев, когда тип Неопределенно. а не ссылка, так же когда подразделение,а не валюта.
Мой способ универсальный и простой, подойдет всем, насчет скорости - думаю ошибок не так много
А так данная ошибка возникает из за того,что в таблице значений нет типа NULL, если сделать ТЗ = о.Движения.Хозрасчетный.выгрузить() а потом Движения.Загрузить(ТЗ) у вас вознинут такие ошибки. Это ошибка платформы.
код
РабочаяКоллекция = Коллекция.Выгрузить();

в этом месте как раз ошибка
8. Wadus161 15 24.07.18 13:51 Сейчас в теме
(7) В валюте и подразделении Неопределенно не может быть, значение неопределенно устанавливается только у составных типов.

Мне кажется Вы невнимательно прочитали эту публикацию, я как раз и написал что проблема в Коллекция.Выгрузить()

Тут нюанс в следующем: Вы правильно подметили, что у ТаблицыЗначения NULL не может быть. Когда выгружается набор записей регистра бухгалтерии, у которого в валюте и в подразделении сидит NULL, то NULL превратиться в пустую ссылку. Главная изюминка , если написать так:
ДвиженияДокумента = о.Движения.Хозрасчетный;
ДвиженияДокумента.Прочитать();
    
ДвиженияДокумента.Записать();

то платформа сама пустую ссылку валюты и подразделения преобразует в NULL если по счету не ведется валютный учет и учет по подразделению, а если написать так:
ДвиженияДокумента = о.Движения.Хозрасчетный;
ДвиженияДокумента.Прочитать();
    
ДвиженияДокумента.ОбменДанными.Загрузка = Истина;
ДвиженияДокумента.Записать();

то платформа оставить пустые ссылки.
9. dspdsp 22.05.19 11:15 Сейчас в теме
Платформа 8.3.13.1644, бух 3.0.70.50
Проблема осталась, цветет и пахнет, код исправления работает
Оставьте свое сообщение