Защита регистров бухгалтерии при замене ссылок и доводка SQL-генератора#4
Защита регистров бухгалтерии при замене ссылок и доводка SQL-генератора#4
Conversation
There was a problem hiding this comment.
Pull request overview
PR дополняет механизм замены ссылок при удалении дублей: защищает движения регистров бухгалтерии от некорректной перезаписи через Выгрузить()/Загрузить() и добавляет генерацию SQL-скрипта для довыполнения замены в PostgreSQL / MS SQL Server, а также улучшает UX (SQL и лог выводятся в журнал формы, включая шаг “неудачные замены”).
Changes:
- В пути замены “Объект” добавлен skip для регистров бухгалтерии с накоплением пар замен в
ЗаменыТребующиеSQLи последующей генерацией SQL. - Доработан
СгенерироватьSQLСкриптЗамены: определение DBMS по строке соединения, корректное преобразование ссылок в hex, пропуск итоговых/служебных таблиц, TRY/CATCH (MS SQL) и DO/EXCEPTION (PG). - В форме “Поиск и удаление дублей” SQL-скрипт больше не показывается модальным сообщением: он дописывается в конец журнала; на шаге неудачных замен добавлено поле для показа лога.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
src/Инструменты/src/CommonModules/УИ_ОбщегоНазначения/Module.bsl |
Защита движений РБ в пути “Объект” + генератор SQL для PG/MS SQL + преобразование ссылок в hex. |
src/Инструменты/src/DataProcessors/УИ_ПоискИУдалениеДублей/Forms/ПоискДублей/Module.bsl |
Сбор SQL-скрипта в текстовый параметр, дописывание в журнал, изменение критерия “успешности” с учётом ТребуетсяSQL*. |
src/Инструменты/src/DataProcessors/УИ_ПоискИУдалениеДублей/Forms/ПоискДублей/Form.form |
Поле журнала на шаге “неудачные замены” для показа лога/SQL пользователю. |
Issues found (need fixes):
- В генераторе PostgreSQL DO-блок закрывается строкой
END $$;. Для PL/pgSQL нуженEND;(точка с запятой послеEND) и затем закрытие тела$$;. В текущем виде сгенерированный PG-скрипт будет падать с синтаксической ошибкой на каждомDO $$ .... - В
ИзмененныеОбъектыПриЗаменеВОбъектепеременная циклаДля Каждого МестоИспользования Из ОбрабатываемыеСтрокипереиспользует имя входного параметраМестоИспользования, затирая его значение (в 1С это одна и та же переменная). Это ухудшает читаемость и повышает риск регрессий при будущих правках — лучше переименовать переменную цикла (например,СтрокаИспользования).
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit c59d68a. Configure here.
c59d68a to
5932976
Compare
Исправление транзакционной логики замены ссылок: - Убран внутренний Попытка/Исключение в первом проходе записи, который приводил к ошибке "В данной транзакции уже происходили ошибки" и блокировал запись всех объектов батча - Убран первый проход записи (проверочный блок) как избыточный — проверка циклических ссылок уже выполняется в ЗаписатьОбъектПриЗаменеСсылок Дедупликация ключей регистров сведений: - Добавлена процедура УдалитьДубликатыКлючейРегистраСведений — после замены ссылок в движениях удаляет записи с дублирующимися ключевыми полями (Период + все Измерения), предотвращая ошибку "Запись с такими ключевыми полями существует" Журнал удаления дублей на форме: - Добавлено поле лога на страницу удаления (ЖурналУдаления) — многострочное, на всю ширину, только чтение, с автопрокруткой вниз - Прогресс пишется в Журнал Регистрации (событие "Поиск и удаление ссылок.Прогресс") с режимом Независимая — записи не теряются при откате транзакций - Клиент читает ЖР при каждом опросе прогресса, отображает полный лог с коррекцией на клиентское время (смещение клиент-сервер) - По каждому дублю пишется итоговая запись (✓ успех / ✗ ошибка) - По каждому месту использования пишется запись с именем дубля и объекта - Счётчик "обработано X из Y" в заголовке считает итоговые записи из ЖР - Лог сохраняется на странице успешного удаления с итогом в конце - Скрыт старый SpreadsheetDocument и отдельная надпись результата Отмена фонового задания: - Кнопка "Прервать" теперь реально отменяет фоновое задание через УИ_ДлительныеОперации.ОтменитьВыполнениеЗадания, а не просто закрывает форму - Идентификатор задания сохраняется в реквизите формы Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Дополнение к c40603f — устранение критического бага с ОСВ после удаления дублей в Бухгалтерии Казахстана и доведение SQL-генератора до рабочего состояния для PostgreSQL и MS SQL Server. Корневая причина бага с ОСВ: - В пути "Объект" функция ИзмененныеОбъектыПриЗаменеВОбъекте обрабатывала движения регистров бухгалтерии через Выгрузить → модификация → Загрузить → Записать(). Для регистра с составными субконто (3 уровня Дт+Кт) Выгрузить включает виртуальные поля ВидСубконтоДт*/Кт*, а Записать() выполняет DELETE+INSERT. Платформа некорректно восстанавливает виртуальные типы при INSERT, что перераспределяет субконто на другой объект того же типа - Аналогичная защита УЖЕ БЫЛА в пути "КлючЗаписи" (ПроизвестиЗаменуВНаборе, стр. 3855), но отсутствовала в пути "Объект" - Симптом: по счёту 1310 одна номенклатура показывала Дт=359380 Кт=566742 сальдо=-207362, общий итог при этом сходился — записи остались, но Субконто Дт1 перераспределилось Защита регистров бухгалтерии в пути "Объект" (УИ_ОбщегоНазначения/Module.bsl, ИзмененныеОбъектыПриЗаменеВОбъекте): - Сигнатура расширена параметром Результат (для накопления ЗаменыТребующиеSQL) - Построение ПарыЗамен перенесено до цикла чтения движений - Для каждого ОписаниеДвижения проверяется тип регистра: если регистр бухгалтерии — помечаем флагом ПропуститьИзЗаРБ, накапливаем пары через НакопитьЗаменуДляSQL, пишем информационную запись в Журнал Регистрации. Набор записей не читается и не модифицируется - Во всех трёх последующих циклах по ОписаниеДвижений добавлен skip-фильтр по флагу ПропуститьИзЗаРБ. Замена выполняется SQL-скриптом после операции SQL-генератор замены ссылок (СгенерироватьSQLСкриптЗамены): - Автоопределение СУБД через парсинг СтрокаСоединенияИнформационнойБазы() по подстроке DBMS=POSTGRESQL / DBMS=MSSQLSERVER. Если определилось — выводится только нужная секция, иначе обе, но MS SQL предваряется префиксом "-- ", чтобы запуск всего файла в PG-клиенте не падал на синтаксисе BEGIN TRY - Корректный порядок байт UUID при формировании decode/0x литералов (СсылкаВHex). 1С хранит ссылки в bytea PG / varbinary(16) MS SQL с полным реверсом сегментов UUID v1: stored = clock_seq(2) + node(6) + timestamp_hi+ver(2) + timestamp_mid(2) + timestamp_low(4), что в hex даёт перестановку chars[17..32] + chars[13..16] + chars[9..12] + chars[1..8]. Подтверждено сравнением реального содержимого _RecorderRRef в БД с XMLString ссылки документа. Без свопа UPDATE даёт 0 affected rows - Пропуск итоговых и служебных таблиц регистров бухгалтерии и накопления (Назначение содержит "ИТОГ" или "НАСТРОЙК": _AccRgAT*, _AccRgCT*, _AccRgOpt*, _AccumRgT*, _AccumRgOpt*). UPDATE по ним вызывает конфликты UNIQUE constraint (когда у Дубля и Оригинала совпадают остальные ключевые поля) и не имеет смысла — итоги пересчитываются автоматически - Каждый UPDATE обёрнут в DO-блок с EXCEPTION (PG) и BEGIN TRY / BEGIN CATCH (MS SQL). При несовместимости типов (например _KindDt*/_KindCt* фактически NUMERIC, а не bytea) или конфликте уникальности скрипт логирует пропуск через RAISE NOTICE / PRINT и продолжает выполнение, не откатывая транзакцию - В шапку SQL добавлено напоминание о необходимости запустить Пересчёт итогов в 1С после применения скрипта Вывод SQL-скрипта в форму лога вместо модального попапа (Forms/ПоискДублей/Module.bsl): - ЗаполнитьРезультатыУдаленияДублей: добавлен out-параметр ТекстSQLСкрипта, удалён вызов Сообщить() — SQL собирается в параметр и дописывается в ЖурналУдаления вызывающим кодом, не показывается всплывающим окном - Логика ЗавершеноБезОшибок теперь игнорирует ошибки с типом ТребуетсяSQL_Итог и ТребуетсяSQL: операция считается успешной, если других (реальных) ошибок не возникло. До этого фикса форма после защиты РБ всегда уходила на ШагНеудачныеЗамены даже для штатно отработавших замен - Обработчик завершения фонового задания дописывает SQL в конец ЖурналУдаления с разделителями "=== SQL-СКРИПТ ДЛЯ ДОВЫПОЛНЕНИЯ ЗАМЕН ===" Поле лога на шаге неудачных замен (Forms/ПоискДублей/Form.form): - На шаг ШагНеудачныеЗамены добавлено поле ЖурналУдаленияНеудача (InputField, multiLine, readOnly), биндится к реквизиту ЖурналУдаления — тому же что и ЖурналУдаленияУспех на шаге успеха - До этого при реальных ошибках лог и SQL-скрипт были скрыты от пользователя: виден был только список необработанных дублей Инструкция по применению: 1. "Поиск и удаление дублей" → выбрать пары → "Удалить" 2. Скопировать SQL-скрипт из ЖурналУдаления (PG/MS SQL секция выводится автоматически в зависимости от текущей СУБД) 3. Выполнить SQL в клиенте СУБД (DataGrip, psql, SSMS) 4. В 1С запустить Пересчёт итогов (Все функции → Стандартные → Управление итогами или РегистрыБухгалтерии.<Имя>.ПересчитатьИтоги() в коде) 5. Запустить "Удаление помеченных объектов" для физического удаления дублей Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
5932976 to
438b4aa
Compare

Дополнение к c40603f — устранение критического бага с ОСВ после удаления дублей в Бухгалтерии и доведение SQL-генератора до рабочего состояния для PostgreSQL и MS SQL Server.
Корневая причина бага с ОСВ:
Защита регистров бухгалтерии в пути "Объект"
(УИ_ОбщегоНазначения/Module.bsl, ИзмененныеОбъектыПриЗаменеВОбъекте):
SQL-генератор замены ссылок (СгенерироватьSQLСкриптЗамены):
Вывод SQL-скрипта в форму лога вместо модального попапа (Forms/ПоискДублей/Module.bsl):
Поле лога на шаге неудачных замен (Forms/ПоискДублей/Form.form):
Инструкция по применению:
Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
Note
High Risk
Changes core link-replacement/delete-duplicates flow, including special-casing accounting registers and generating SQL UPDATE scripts, which can directly impact financial register data integrity if incorrect.
Overview
Protects accounting registers during duplicate cleanup by skipping platform-based link replacement for
РегистрыБухгалтерии, recording affected pairs intoЗаменыТребующиеSQL, and surfacing a synthesizedТребуетсяSQL_Итогentry with a generated SQL script.Adds an SQL generator (
СгенерироватьSQLСкриптЗамены) that inspects DB storage structure, detects PostgreSQL vs MS SQL, and emits resilient per-field UPDATEs (with TRY/CATCH or EXCEPTION handling) while skipping totals/settings tables; also adds cleanup for post-replacement key collisions in information registers.Improves UX and operability in the “Поиск и удаление дублей” form: adds “check/uncheck all” commands, streams deletion progress from the registration log into a new
ЖурналУдаленияfield (including SQL script), and allows canceling the running background job from the wizard.Reviewed by Cursor Bugbot for commit 438b4aa. Bugbot is set up for automated code reviews on this repo. Configure here.