Слияние и перенос ссылок

Материал из Eludia
Перейти к: навигация, поиск

Практика показывает, что для жизнеспособности информационной системы необходимо давать операторам возможность дополнять и редактировать практически любые справочные данные. Вы можете импортировать с кадровую систему высочайше утверждённый актуальный классификатор специальностей, но будте готовы к тому, что придётся оформлять на работу сотрудника, который получал образование 50 лет назад в совершенно другом государстве. Не стоит сильно удивляться, если вы наткнётесь на неведомые воинские звания, группы крови и тому подобное. И чем самому лезть в БД в каждом таком случае, гораздо эффективнее дать оператору кнопку "Добавить".

Та же самая практика свидетельствует, что немалое число пользователей способны увидеть строку в справочнике только после того, как они введут её туда лично. При том, что требуемая запись там присутствует уже во множестве копий. Тут возможны всякие ухищрения, например, при нажатии "Добавить" без предварительного поиска выдавать сообщение: "Ну что же вы? Это нехорошо!" – они могут несколько замедлить засорение БД дубликатами, однако неспособны остановить его. С чего бы это всем допускать одинаковые опечатки при вводе и поиске данных? А почему вы думаете, что разные люди называют одну и ту же вещь похожими словами ("Больница №1" / "Первая ГКБ")? То-то...

Серьёзная информационная система должна предоставлять не просто возможность ввода и распечатки данных, но содержать ещё и инструменты для выверки и коррекции информации. Наивно рассчитывать, что один оператор сделает всё правильно от начала до конца (тем более, что все всегда будут безупречны), и не надо так думать, и именно поэтому находить и исправлять заведомые ошибки должно быть удобно и быстро.

Вернёмся к более узкой теме дублей в справочниках. Допустим, всё в той же таблице users имеется две записи, обозначающие одного и того же человека. И на ту, и на другую ссылается множество записей из различных таблиц. Если один из дублей удалить (DELETE), очевидно, будет нарушена целостность данных. Если воспользоваться мягким удалением (SET fake = -1), то таких тяжёлых последствий не возникнет, однако некоторые несоответствия останутся. В частности, документы, ссылающиеся на удалённого двойника, не будут находиться в контексте того, кто остался в актуальном состоянии, а в статистических выборках будут наблюдаться либо провалы (при наличии fake-фильтра), либо опять-таки дубли.

Корректная обработка сдвоенных записей включает в себя перенос всех ссылок с удаляемой записи на актуальную. Процедура sql_do_relink осуществляет это действие автоматически: достаточно лишь указать таблицу и номера записей. То есть, скажем, сколько есть полей id_user во всевозможных других таблицах, все они будут обновлены. И поля id_executor, если у users прописан псевдоним executors. И все поля, как бы они ни назывались, если для них указана опция ref => 'users'. Далее процедура мягко удаляет тот дубликат, на который больше никто не ссылается и проставляет на нём самом ссылку на актуальную запись – поле is_merged_to.

Более того, все пустые поля актуальной записи обновляются соответствующими значениями из записи-дубликата. Что весьма удобно: ведь очень часто оказывается, что, скажем, банковские координаты были внесены в один дубликат, а адресные данные – в другой. Слияние затрагивает не только ссылки, но и скалярные поля.

Шаблоны StEludio содержат всё необходимое для того, чтобы реализовать поиск и слияние дубликатов. А именно: в шаблоне процедуры get_item_of есть запрос на дубликаты по началу наименования:

unless ($_REQUEST {first}) {
 $_REQUEST {first} = length $item -> {label};
 $_REQUEST {first} = 4 if $_REQUEST {first} > 4;
}

$item -> {clones} = sql_select_all (<<EOS, $item -> {label}, {fake => '__TYPE__'});
 SELECT
  __TYPE__.*
 FROM
  __TYPE__
 WHERE
  LEFT(__TYPE__.label, $_REQUEST{first}) = LEFT(?, $_REQUEST{first})
 ORDER BY
  __TYPE__.label
EOS

шаблон draw_item_of отрисовываеет соответствующую таблицу с галочками и кнопкой "слить выделенные", а действие add обрабатывается следующим образом (do_add):

foreach my $id_clone (get_ids ('clone')) {
 sql_do_relink ('__TYPE__', $id_clone => $_REQUEST {id});
 sql_do (
  'UPDATE __TYPE__ SET fake = -1, is_merged_to = ? WHERE id = ?', 
  $_REQUEST {id}, 
  $id_clone
 );
}
Персональные инструменты
Пространства имён

Варианты
Действия
Навигация
Разработчику
Администратору
Инструменты