Appearance
Уникальность номера лицевого счёта и мультитенантность (несколько УК)
Вопрос
Могут ли в разных управляющих компаниях (УК) существовать лицевые счета с одинаковым номером (например «1234567890»)? Вызовет ли это конфликт?
Вывод: да, конфликт возможен
В текущей архитектуре номер лицевого счёта (account_number) обязан быть уникальным в рамках всей системы, а не в рамках одной организации (УК). Поэтому две разные УК не могут завести лицевые счета с одним и тем же номером.
Как устроено сейчас
Модель данных
- PersonalAccount (core-service): поле
AccountNumberс тегомgorm:"uniqueIndex"— в таблицеpersonal_accountsна колонкуaccount_numberналожен глобальный уникальный индекс (на всю таблицу). - Связь с организацией не прямая: PersonalAccount → Room → House → Organization. То есть лицевой счёт принадлежит УК через цепочку «помещение → дом → организация», но в самой таблице
personal_accountsколонкиorganization_idнет.
Проверка при создании ЛС
В core-service/internal/handlers/personal_accounts.go при создании лицевого счёта:
- Если номер передан вручную — выполняется проверка:
db.Model(&models.PersonalAccount{}).Where("account_number = ?", accountNumber).Count(&count)
без какого‑либо фильтра по организации. - Если номер не передан — генерируется «уникальный» номер проверкой по всей таблице (
generateUniqueAccountNumber).
В обоих случаях уникальность проверяется по всей таблице personal_accounts. Поэтому:
- УК1 создала ЛС с номером «1234567890»;
- УК2 при попытке создать ЛС «1234567890» получит ошибку «accountNumber already exists» (или нарушение уникального индекса при прямой вставке в БД).
Доступ к данным
Список лицевых счетов обычно запрашивается с фильтром по houseId (или roomId). Дома привязаны к организации, поэтому каждая УК по факту видит только свои дома и свои ЛС. Но ограничение уникальности номера при этом остаётся глобальным: свободный в одной УК номер может быть уже занят в другой.
Когда это создаёт проблемы
- Несколько УК в одной инстансе (одна БД, мультитенантность по организациям).
- У разных УК совпадающие или похожие схемы нумерации (например, короткие номера 1, 2, 3… или общий формат из 10 цифр без префикса).
- Миграция из старых систем, где номера уникальны только внутри УК.
В таких случаях вторая УК при создании или импорте ЛС будет упираться в «accountNumber already exists».
Варианты решения
1. Уникальность в рамках организации (рекомендуется для мультитенантности)
Сделать номер лицевого счёта уникальным в пределах одной УК, а не глобально.
- Добавить в таблицу
personal_accountsколонкуorganization_id(или получать организацию через Room → House и использовать её в проверках и индексе). - Заменить глобальный уникальный индекс на составной:
(organization_id, account_number)UNIQUE. - При создании и обновлении ЛС проверять дубликат только в рамках своей организации (и при обновлении — исключать текущую запись по id).
- При генерации номера по умолчанию искать свободный номер тоже только в рамках организации.
Плюсы: разные УК могут использовать одни и те же номера (1234567890 у УК1 и 1234567890 у УК2). Минусы: миграция БД, заполнение organization_id для существующих записей (по цепочке Room → House → Organization), обновление API и, при необходимости, фронта.
2. Оставить глобальную уникальность и зафиксировать правила
Не менять схему, но явно зафиксировать в документации и в продукте:
- Номер лицевого счёта уникален в масштабе всей системы (все УК в одной БД).
- Рекомендация для УК: использовать схему нумерации с префиксом или кодом, чтобы избежать пересечений (например, префикс по организации или по региону/дому).
Подходит, если мультитенантность не планируется или номера всегда генерируются системой и не повторяются между УК.
3. Гибрид: префикс по организации при отображении
Оставить в БД глобально уникальный «внутренний» номер (или составной ключ organization_id + account_number), а в UI и в выгрузках показывать пользователю «внешний» номер с префиксом организации (например «УК1-1234567890»). Это не снимает ограничение в БД, но уменьшает путаницу и коллизии при ручном вводе, если префикс задаётся автоматически.
Рекомендация
Если в одной базе будут работать несколько УК, целесообразно перейти к уникальности пары (organization_id, account_number) (вариант 1): добавить organization_id в personal_accounts, завести составной уникальный индекс и проверять дубликаты только в рамках организации. Тогда одинаковые номера лицевых счетов в разных УК конфликтовать не будут.
Если мультитенантность не предполагается (одна УК на инстанс или одна БД на УК), текущей глобальной уникальности достаточно; при необходимости можно лишь задокументировать это и рекомендовать схему нумерации с префиксом (вариант 2).