Ситуация, когда из-за неосторожных действий пользователей в информационной базе «поехали» данные за прошлые периоды, встречается в практике администраторов и программистов 1С довольно часто. Особенно критично это для кадрового учета, где изменение графика работы в старом документе Прием на работу или Кадровый перевод влечет за собой каскадные изменения в регистрах сведений и, как следствие, некорректное начисление заработной платы. Если у нас есть архивная копия базы двухмесячной давности, мы можем восстановить справедливость, сопоставив данные и выявив ошибки. Рассмотрим детально, как это сделать наиболее эффективно.
Разберем самый надежный способ сопоставления ссылочных объектов (документов, справочников) между двумя базами. УИД (Уникальный Идентификатор) — это 128-битное число, которое присваивается объекту в момент его создания. При создании копии базы (например, средствами SQL или через выгрузку/загрузку .dt) все идентификаторы сохраняются. Это означает, что один и тот же документ в рабочей базе и в копии будет иметь идентичный УИД.
Проанализируем, как получить УИД в запросе или программно. В консоли запросов мы можем использовать функцию:
ВЫБРАТЬ
Ссылка.УникальныйИдентификатор() КАК УИД,
Номер,
Дата,
Сотрудник
ИЗ
Документ.ПриемНаРаботу
Выясним причину, по которой это важно: даже если пользователь изменил номер или дату документа, его УИД останется неизменным. Это позволяет нам однозначно связать «испорченный» документ в живой базе с его «здоровым» прототипом в архиве.
Если прямого доступа между базами нет, воспользуемся методом выгрузки. Посмотрим на алгоритм действий:
ГрафикРаботыСотрудников).Рассмотрим пример кода для поиска расхождений, если мы загрузили данные из файла в таблицу значений ТаблицаИзКопии:
Для Каждого СтрокаКопии Из ТаблицаИзКопии Цикл
// Пытаемся найти документ в текущей базе по сохраненному УИД
СсылкаОбъект = Документы.ПриемНаРаботу.ПолучитьСсылку(Новый УникальныйИдентификатор(СтрокаКопии.УИД_Строкой));
Если СсылкаОбъект.Пустая() Тогда
Сообщить("Документ не найден в рабочей базе: " + СтрокаКопии.Номер);
Продолжить;
КонецЕсли;
// Сравниваем реквизит "ГрафикРаботы"
Если СсылкаОбъект.ГрафикРаботы <> СтрокаКопии.ГрафикРаботы Тогда
Сообщить("Обнаружено расхождение в документе " + СсылкаОбъект + ". Старый график: " + СтрокаКопии.ГрафикРаботы);
КонецЕсли;
КонецЦикла;
Наиболее технологичный подход — программное подключение из одной базы к другой «на лету». Это избавляет от необходимости возиться с промежуточными файлами. Проанализируем, как настроить такое соединение:
ПараметрыСоединения = "Srvr=""ИмяСервера"";Ref=""ИмяБазыКопии"";Usr=""Админ"";Pwd=""Пароль"";";
V83Connector = Новый COMОбъект("V83.COMConnector");
Попытка
СоединениеСКопией = V83Connector.Connect(ПараметрыСоединения);
Исключение
Сообщить("Не удалось подключиться к копии: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
Теперь мы можем выполнять запросы к базе-копии прямо из контекста рабочей базы. Разберем пример получения данных из регистра сведений через COM:
ЗапросКопия = СоединениеСКопией.NewObject("Запрос");
ЗапросКопия.Текст =
"ВЫБРАТЬ
| Графики.Сотрудник.Наименование КАК СотрудникИмя,
| Графики.ГрафикРаботы.Наименование КАК ГрафикИмя,
| Графики.Регистратор.УникальныйИдентификатор() КАК УИД_Рег
|ИЗ
| РегистрСведений.ГрафикРаботыСотрудников КАК Графики";
РезультатКопии = ЗапросКопия.Execute().Unload();
Важно помнить, что при COM-соединении мы получаем COM-объекты. Для корректного сравнения ссылочных данных лучше передавать их в виде строк (УИД, Наименование, Код) и сопоставлять их уже в основной базе.
Если задача стоит не только в сравнении, но и в быстром переносе «как было», можно использовать механизм СериализаторXDTO. Рассмотрим, как это работает:
мы можем выгрузить объект из копии в XML-строку и прочитать её в рабочей базе. Это гарантирует, что все реквизиты объекта примут ровно те значения, которые были в архивной копии.
Пример записи объекта в XML:
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, СсылкаНаОбъект);
XMLСтрокаОбъекта = ЗаписьXML.Закрыть();
В рабочей базе этот объект можно прочитать и применить его свойства к существующему документу. Однако будьте осторожны: простое перезаписывание документа может инициировать перерасчеты зарплаты за закрытые периоды.
Прежде чем приступать к сложным манипуляциям с копиями баз, проверим, не включен ли в конфигурации стандартный механизм платформы История данных. Если он активен для документов Прием на работу или Кадровый перевод, то копия нам может вообще не понадобиться.
Разберем, как это проверить:
Проанализируем специфику работы с регистрами сведений в 1С:ЗУП. Даже если мы программно исправим реквизит График работы в документе-регистраторе, записи в регистре График работы сотрудников могут не обновиться автоматически, либо обновятся не полностью.
Рекомендация: после программного восстановления реквизитов документов, необходимо запустить процедуру перепроведения этих документов или использовать типовые обработки по исправлению записей регистров. Также обратите внимание на регистр Перерасчет зарплаты. Любое изменение «задним числом» создаст там записи, которые заставят бухгалтерию пересчитывать прошлые месяцы. После восстановления данных из копии убедитесь, что вы очистили ненужные записи в регистрах перерасчетов, если это допустимо политикой учета организации.
Мы рассмотрели несколько способов решения проблемы: от простого сопоставления по УИД до использования COM-соединения и XML-сериализации. Выбор метода зависит от объема данных и ваших навыков программирования. Самым безопасным для новичка будет метод с выгрузкой в файл и визуальным сравнением, а для опытного разработчика — использование V83.COMConnector для автоматизированного поиска и исправления расхождений.