Перейти к основному содержимому

Сущность / агрегат: PropertyObjectTypeConfig

Уровень «тип объекта недвижимости» экономической модели доходности. Тип объекта недвижимости = группа планировок (LayoutGroup) из контекста chessboard.

Назначение

PropertyObjectTypeConfig — nullable-оверрайды платформенных коэффициентов EconomicModelConfig для конкретной группы планировок («Стандарт», «Комфорт», «Люкс», «Президентский люкс» и т.д.). Заполненное поле замещает платформенное значение; null — «наследовать от платформы». Является средним уровнем разрешения коэффициентов: PropertyObjectTypeMonthOverridePropertyObjectTypeConfigEconomicModelConfig → дефолты кода. Агрегат владеет дочерней коллекцией помесячных оверрайдов PropertyObjectTypeMonthOverride.

Настройка типа удаляется физически (soft-delete не применяется): расчёт по объектам этой группы откатывается к платформенному уровню, история изменений — через Version и audit-события.

Классификация

ПолеЗначение
Контекстinvest-analytics
Kindагрегат (граница: PropertyObjectTypeConfig + коллекция PropertyObjectTypeMonthOverride); натуральный ключ — внешний id группы планировок
Source of truthкоэффициенты — invest-analytics; сам справочник групп планировок — chessboard (реплика Talent)
Таблицаinvest_analytics.property_object_type_config
Tenant isolationне tenanted — платформенная настройка (ADR-0052 п.3)

Поля

Все коэффициенты-оверрайды nullable: null = «взять значение из EconomicModelConfig». Семантика и единицы каждого коэффициента — economic-model-config.md (здесь только дельта: nullable + натуральный ключ). Диапазоны заполненных значений те же (INV-MC2).

ПолеТипОбязательностьОграничения (PK/FK/index/constraint)ИсточникОписание
Id (GroupId)longДаPK (натуральный, не generated)chessboard (id LayoutGroup)Группа планировок, к которой относится настройка. FK-констрейнта нет — справочник живёт в другом контексте; существование проверяется на уровне команды через chessboard (правило границ).
NamestringДаvarchar(128), not nulladmin API / chessboardОтображаемое имя типа («Стандарт», «Люкс»…); заполняется из группы планировок, админ может переименовать.
MarketPremiumdecimal?Нетnumeric(9,6); check как INV-MC2 при not nulladmin APIОверрайд надбавки к прайсу.
PriceGrowthMonthlydecimal?Нетnumeric(9,6)admin APIОверрайд месячного роста цены.
DailyRentM2decimal?Нетnumeric(12,2)admin APIОверрайд ставки аренды руб/м²/сутки.
RentGrowthMonthlydecimal?Нетnumeric(9,6)admin APIОверрайд месячного роста аренды.
ExpenseSharedecimal?Нетnumeric(9,6)admin APIОверрайд доли расходов.
AppreciationTaxMonthlydecimal?Нетnumeric(9,6)admin APIЛегаси-оверрайд (не участвует в расчёте — см. дом поля).
EbitdaTaxMonthlydecimal?Нетnumeric(9,6)admin APIЛегаси-оверрайд (не участвует в расчёте).
Occupancydecimal?Нетnumeric(9,6)admin APIОверрайд заполняемости.
HorizonMonthsint?Нетcheck >= 1 AND <= 360 при not nulladmin APIОверрайд горизонта прогноза.
VersionlongДа>= 1appРевизии настройки типа.
CreatedAt / UpdatedAtDateTimeOffsetДаappШтампы.
CreatedByUserId / UpdatedByUserIdGuid?Нетidentity-contextАктор правки.

Оптимистичная блокировка: конкурентные правки в админке не должны затирать друг друга (см. «Индексы, хранение, безопасность» → 409 INVEST_ANALYTICS_PROPERTY_OBJECT_TYPE_CONFLICT).

Связи

СвязьТипКлючПравило загрузкиDelete behavior
PropertyObjectTypeMonthOverrideколлекция агрегатаGroupId (composite PK ребёнка)при расчёте — все месяцы типа по GroupId без пагинации; в админке — вместе с родителемcascade (удаление типа удаляет его помесячные оверрайды)
LayoutGroup (chessboard)replica-reference (логическая, без FK)Id = GroupIdпроверка существования — запрос в chessboard на команде создания
EconomicModelConfigreference (логическая, без FK)well-known Idотдельная загрузка при расчёте

Инварианты и переходы состояний

ИнвариантУсловиеГде проверяетсяОшибка
INV-LT1 GroupExistsGroupId существует как группа планировок в chessboardпроверка при admin-upsert (запрос в chessboard)INVEST_ANALYTICS_PROPERTY_OBJECT_TYPE_GROUP_NOT_FOUND
INV-LT2 RangesЗаполненные (not null) коэффициенты — в диапазонах INV-MC2валидация + check-constraintsValidationError
INV-LT3 FiniteNumbersЗаполненные значения — конечные числа (запрет NaN/Infinity)тип numeric + валидацияValidationError
INV-LT4 NameNotEmptyName непустое после trim, ≤ 128 символоввалидацияValidationError

Доменные и интеграционные события

СобытиеТипКогдаSnapshot/поля
PropertyObjectTypeConfigUpsertedEventдоменноеСоздание/обновление настройки типаGroupId, Version, UpdatedByUserId — audit-лог
PropertyObjectTypeConfigDeletedEventдоменноеУдаление настройки типа (возврат к платформенным значениям)GroupId, UpdatedByUserId

Интеграционное событие: upsert/delete настройки типа (PropertyObjectTypeConfigUpsertedEvent/ PropertyObjectTypeConfigDeletedEvent) публикует EconomicModelChangedKafkaEvent (pin.invest-analytics.model-changed.v1, ChangeScope = PropertyObjectType, GroupId) через outbox — internal recompute job пересчитывает метрики доходности объектов недвижимости этого типа и переиздаёт pin.invest-analytics.property-object-metrics.v1 (../events/model-changed.md). Коэффициенты в payload не уходят (подписчик читает модель напрямую).

Окно согласованности и промежуточное состояние

Правка/удаление настройки типа не пересчитывает витрину синхронно:

  1. Upsert/delete коммитится атомарно с outbox-записью model-changed (ChangeScope = PropertyObjectType, GroupId).
  2. Расчёт investor-series по объектам этого GroupId читает уровни вживую — новые (или откатившиеся к платформенным после удаления) коэффициенты действуют со следующего запроса.
  3. Витринные метрики объектов этого типа пересчитываются асинхронно recompute job-ом (окно до 15 мин); в этом окне карточки каталога затронутых объектов недвижимости могут ещё показывать прежние бейджи.

Конкурентность: upsert и delete одной и той же настройки типа сериализуются оптимистичной блокировкой по Version — проигравший получает 409 INVEST_ANALYTICS_PROPERTY_OBJECT_TYPE_CONFLICT и перечитывает актуальное состояние. Удаление типа с настроенными помесячными оверрайдами каскадно удаляет их (дочерняя коллекция) — объекты недвижимости группы целиком возвращаются к платформенному уровню.

Индексы, хранение, безопасность

АспектЗначение
ИндексыPK (Id); дополнительные не нужны — таблица маленькая (единицы–десятки типов), выборки по PK
Партиционирование / retentionнет — справочная таблица
Concurrencyоптимистичная блокировка → 409 INVEST_ANALYTICS_PROPERTY_OBJECT_TYPE_CONFLICT; Version — ревизии
Permissions / PIIЧтение — внутреннее (расчёт) + admin invest-analytics.property-object-types.view; запись — admin invest-analytics.property-object-types.manage (ADR-0053). PII нет
Auditactor-stamping + Version + доменные события

Обратные ссылки

Автоссылки: где используется этот документ.

Связанные документы