Похожие статьи:
В этой статье даны пояснения причины и приведен более универсальный код.
Столкнулся с проблемой у клиентов - неожиданно появились зависшие остатки, причем остатки развернутые. Долго не могли понять что происходит, грешили на итоги, но пересчет не помог.
Причина: если оборотки формировать с выводом валюты, тогда становится все понятно - у невалютных счетов вместо значения NULL появилась пустая ссылка валюты.
Что произошло? Оказалось, что перед этим выполнялась процедура поиска и замены. Именно она делает такой беспорядок.
Кто виноват? В типовом коде допущена ошибка:
Процедура ЗаменитьВКоллекцииСтрок(ВидКоллекции, ИмяКоллекции, Объект, Коллекция, Знач СписокПолей, Знач ПарыЗамен)
РабочаяКоллекция = Коллекция.Выгрузить();
Модифицировано = Ложь;
Для Каждого Строка Из РабочаяКоллекция Цикл
Для Каждого КлючЗначение Из СписокПолей Цикл
Имя = КлючЗначение.Ключ;
ЦелеваяСсылка = ПарыЗамен[ Строка[Имя] ];
Если ЦелеваяСсылка <> Неопределено Тогда
ЗарегистрироватьФактЗамены(Объект, Строка[Имя], ЦелеваяСсылка, ВидКоллекции, ИмяКоллекции, РабочаяКоллекция.Индекс(Строка), Имя);
Строка[Имя] = ЦелеваяСсылка;
Модифицировано = Истина;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Если Модифицировано Тогда
Коллекция.Загрузить(РабочаяКоллекция);
КонецЕсли;
КонецПроцедуры
Проблема в параметре "Коллекция", там сидит набор записей. У набора записей, если у валюты стоит NULL, то в момент выгрузки в таблицу значения вместо NULL будет Справочники.Валюта.ПустаяСсылка. ВАЖНО! Такое поведение будет только если поиск и замену выполнять в режиме ОбменДанными.Загрузка = Истина!! То есть, если набор записей записать в обычном режиме, то проблемы не будет.
Но почему такое поведение? Логика платформы ясна: если данные приходят в режиме обмена данными, то значит проверять ничего не надо, ведь по идее такие же данные должны быть в другом узле и мы не может допустить рассинхронизацию. Но в данном случае это конечно ошибка платформы. Возможно в более новых версиях эту ошибку устранили.
Как исправить?
&НаСервере
Процедура ИсправитьНаСервере()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВложенныйЗапрос.Регистратор КАК Регистратор
|ИЗ
| (ВЫБРАТЬ
| ХозрасчетныйДвиженияССубконто.Регистратор КАК Регистратор
| ИЗ
| РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(
| ,
| ,
| ПодразделениеДт = ЗНАЧЕНИЕ(Справочник.ПодразделенияОрганизаций.ПустаяСсылка)
| И СчетДт <> ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.ПустаяСсылка)
| И НЕ СчетДт.УчетПоПодразделениям,
| ,
| ) КАК ХозрасчетныйДвиженияССубконто
|
| СГРУППИРОВАТЬ ПО
| ХозрасчетныйДвиженияССубконто.Регистратор
|
| ОБЪЕДИНИТЬ ВСЕ
|
| ВЫБРАТЬ
| ХозрасчетныйДвиженияССубконто.Регистратор
| ИЗ
| РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(
| ,
| ,
| ПодразделениеКт = ЗНАЧЕНИЕ(Справочник.ПодразделенияОрганизаций.ПустаяСсылка)
| И СчетКт <> ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.ПустаяСсылка)
| И НЕ СчетКт.УчетПоПодразделениям,
| ,
| ) КАК ХозрасчетныйДвиженияССубконто
|
| СГРУППИРОВАТЬ ПО
| ХозрасчетныйДвиженияССубконто.Регистратор
|
| ОБЪЕДИНИТЬ ВСЕ
|
| ВЫБРАТЬ
| ХозрасчетныйДвиженияССубконто.Регистратор
| ИЗ
| РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(
| ,
| ,
| ВалютаДт = ЗНАЧЕНИЕ(Справочник.Валюты.ПустаяСсылка)
| И СчетДт <> ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.ПустаяСсылка)
| И НЕ СчетДт.Валютный,
| ,
| ) КАК ХозрасчетныйДвиженияССубконто
|
| СГРУППИРОВАТЬ ПО
| ХозрасчетныйДвиженияССубконто.Регистратор
|
| ОБЪЕДИНИТЬ ВСЕ
|
| ВЫБРАТЬ
| ХозрасчетныйДвиженияССубконто.Регистратор
| ИЗ
| РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(
| ,
| ,
| ВалютаКт = ЗНАЧЕНИЕ(Справочник.Валюты.ПустаяСсылка)
| И СчетКт <> ЗНАЧЕНИЕ(ПланСчетов.Хозрасчетный.ПустаяСсылка)
| И НЕ СчетКт.Валютный,
| ,
| ) КАК ХозрасчетныйДвиженияССубконто
|
| СГРУППИРОВАТЬ ПО
| ХозрасчетныйДвиженияССубконто.Регистратор) КАК ВложенныйЗапрос
|
|СГРУППИРОВАТЬ ПО
| ВложенныйЗапрос.Регистратор";
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
Набор = РегистрыБухгалтерии.Хозрасчетный.СоздатьНаборЗаписей();
Набор.Отбор.Регистратор.Установить(ВыборкаДетальныеЗаписи.Регистратор);
Набор.Прочитать();
Модифицирован = Ложь;
Для Каждого ЗаписьНабора Из Набор Цикл
Если НЕ (ЗначениеЗаполнено(ЗаписьНабора.СчетДт) И ЗаписьНабора.СчетДт.Валютный) Тогда
ЗаписьНабора.ВалютаДт = NULL;
КонецЕсли;
Если НЕ (ЗначениеЗаполнено(ЗаписьНабора.СчетКт) И ЗаписьНабора.СчетКт.Валютный) Тогда
ЗаписьНабора.ВалютаКт = NULL;
КонецЕсли;
Если НЕ (ЗначениеЗаполнено(ЗаписьНабора.СчетДт) И ЗаписьНабора.СчетДт.УчетПоПодразделениям) Тогда
ЗаписьНабора.ПодразделениеДт = NULL;
КонецЕсли;
Если НЕ (ЗначениеЗаполнено(ЗаписьНабора.СчетКт) И ЗаписьНабора.СчетКт.УчетПоПодразделениям) Тогда
ЗаписьНабора.ПодразделениеКт = NULL;
КонецЕсли;
КонецЦикла;
Набор.ОбменДанными.Загрузка = Истина;
Набор.Записать();
КонецЦикла;
КонецПроцедуры
Как защититься от этой проблемы? Либо помнить чем грозит поиск и замена в режиме обмена данными, либо в процедуре "ПередЗаписью" регистра бухгалтерии добавить проверку, обмен конечно немного замедлится, но так точно больше проблем на возникнет (вдруг еще какой сюрприз притаился):
Если ОбменДанными.Загрузка Тогда
//<-- Wadus
Для каждого Проводка из ЭтотОбъект Цикл
Если НЕ (ЗначениеЗаполнено(Проводка.СчетДт) И Проводка.СчетДт.Валютный) Тогда
Проводка.ВалютаДт = NULL;
КонецЕсли;
Если НЕ (ЗначениеЗаполнено(Проводка.СчетКт) И Проводка.СчетКт.Валютный) Тогда
Проводка.ВалютаКт = NULL;
КонецЕсли;
Если НЕ (ЗначениеЗаполнено(Проводка.СчетДт) И Проводка.СчетДт.УчетПоПодразделениям) Тогда
Проводка.ПодразделениеДт = NULL;
КонецЕсли;
Если НЕ (ЗначениеЗаполнено(Проводка.СчетКт) И Проводка.СчетКт.УчетПоПодразделениям) Тогда
Проводка.ПодразделениеКт = NULL;
КонецЕсли;
//для забалансовых, иначе по незаполненному счету будут пустые ссылки
//некритично, но не по фэн-шую
Если Не ЗначениеЗаполнено(Проводка.СчетДт) Тогда
Проводка.ВалютаДт = NULL;
Проводка.ПодразделениеДт = NULL;
КонецЕсли;
Если Не ЗначениеЗаполнено(Проводка.СчетКт) Тогда
Проводка.ВалютаКт = NULL;
Проводка.ПодразделениеКт = NULL;
КонецЕсли;
КонецЦикла;
//--> Wadus
Возврат;
КонецЕсли;
Либо изменить функцию в модулях поиска и замены. Пример приводить уже не буду.
Если помог - смело ставь + ! Буду благодарен )
Спасибо фирме 1С за такие интересные задачки! ))
P.S. добавил еще подразделения.
P.S.S. добавил забалансовые счета для обработки