# Слой необработанных данных

Слой Raw data содержит 3 различных схемы данных, каждая из которых обслуживает разные аспекты платформы телематики и бизнес-аналитики:

* [`raw_business_data`](#raw_business_data-structure) - содержит таблицы, атрибуты и значения, связанные с бизнес-информацией, такими как транспортные средства, сотрудники, геозоны, добавленные пользователями, и т.д.
* [`raw_telematics_data`](#raw_telematics_data-structure) - содержит таблицы, атрибуты и значения, связанные с телематическими данными, передаваемыми от устройств под мониторингом, такими как местоположения, входы, выходы и события.
* [`repo`](#repo-data-structure) - содержит таблицы для управления активами и инвентарём, включая настраиваемые типы активов, пользовательские поля, связи между активами и геопространственные данные для отслеживания ресурсов организации.

Каждая схема оптимизирована для своей доменной области данных и шаблонов доступа, обеспечивая всестороннее покрытие потребностей в операционном, телематическом и управлении активами.

## `raw_business_data` structure

Эта схема содержит более 40 тщательно отобранных таблиц для охвата различных бизнес-аспектов и вариантов использования. Эти таблицы представляют ваши основные бизнес-сущности, организационную структуру и операционные данные.

<figure><img src="https://1176408533-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoFNFEIINiGFbhi3Px3dE%2Fuploads%2FLxWgTRWILnl4LOQt1IZL%2Fraw_business_data.svg?alt=media&#x26;token=66789735-63b4-4328-911c-322cf3283b62" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Интерактивная диаграмма схемы raw\_business\_data доступна на **dbdiagram.io**: <https://dbdiagram.io/d/V3-bronze-layer-68ecfd1c2e68d21b4131089a>
{% endhint %}

Ниже приведены сведения о схеме raw\_business\_data.

{% code title="Схема raw\_business\_data" expandable="true" %}

```sql
Таблица "vehicle_service_tasks" {
  "record_added_at" timestamp [not null]
  "start_mileage" numeric
  "comment" "character varying(255)"
  "status" "character varying(10)" [not null]
  "completion_date" timestamp
  "start_engine_hours" numeric
  "service_task_id" integer [not null]
  "is_notification_push_enabled" boolean [not null]
  "date_notification_interval" interval
  "predicted_datetime" timestamp
  "cost" numeric [not null]
  "mileage_limit" numeric
  "notification_emails" text
  "is_unplanned" boolean [not null]
  "is_repeat" boolean [not null]
  "completion_engine_hours" integer
  "engine_hours_limit" numeric
  "mileage_repeat_interval" integer
  "vehicle_id" integer [not null]
  "engine_hours_notification_interval" integer
  "start_date" timestamp
  "mileage_notification_interval" integer
  "date_repeat_interval" interval
  "description" "character varying(255)"
  "notification_sms_phone_numbers" text
  "end_date" timestamp
  "engine_hours_repeat_interval" integer
  "completion_mileage" integer
}

Таблица "garages" {
  "record_added_at" timestamp [not null]
  "garage_id" integer [not null]
  "longitude" numeric
  "mechanic_name" "character varying(255)"
  "radius" integer [not null]
  "latitude" numeric
  "organization_label" "character varying(255)"
  "user_id" integer [not null]
  "dispatcher_name" "character varying(255)"
  "address" "character varying(255)"
}

Таблица "driver_history" {
  "server_datetime" timestamp [not null]
  "address" "character varying(255)"
  "updated_by" integer [not null]
  "object_id" integer
  "longitude" numeric
  "latitude" numeric
  "driver_history_id" integer [not null]
  "hardware_key" "character varying(64)"
  "new_employee_id" integer
  "changed_datetime" timestamp
  "record_added_at" timestamp [not null]
  "old_employee_id" integer
}

Таблица "departments" {
  "record_added_at" timestamp [not null]
  "department_label" "character varying(255)" [not null]
  "latitude" numeric
  "department_id" integer [not null]
  "address" "character varying(255)"
  "radius" integer [not null]
  "longitude" numeric
  "user_id" integer [not null]
}

Таблица "checkins" {
  "radius" integer [not null]
  "latitude" numeric [not null]
  "employee_id" integer [not null]
  "longitude" numeric [not null]
  "record_added_at" timestamp [not null]
  "actual_datetime" timestamp [not null]
  "user_id" integer [not null]
  "form_id" integer [not null]
  "address" "character varying(255)"
  "planned_datetime" timestamp [not null]
  "object_id" integer [not null]
  "checkin_id" integer [not null]
  "comment" text
}

Таблица "statuses" {
  "order_sort" integer [not null]
  "listing_id" integer [not null]
  "color" "character varying(6)" [not null]
  "status_id" integer [not null]
  "status_label" "character varying(200)" [not null]
  "record_added_at" timestamp [not null]
  "is_deleted" boolean [not null]
}

Таблица "places_linked_entity_fields" {
  "value" bigint [not null]
  "record_added_at" timestamp [not null]
  "place_id" integer [not null]
  "field_id" integer [not null]
}

Таблица "places_text_fields" {
  "place_id" integer [not null]
  "record_added_at" timestamp [not null]
  "value" text [not null]
  "field_id" integer [not null]
}

Таблица "users2zones" {
  "zone_id" integer [not null]
  "record_added_at" timestamp [not null]
  "user_id" integer [not null]
}

Таблица "objects" {
  "record_added_at" timestamp [not null]
  "create_datetime" timestamp [not null]
  "client_id" integer [not null]
  "group_id" integer
  "object_label" "character varying(100)"
  "model" "character varying(64)"
  "is_clone" boolean [not null]
  "is_deleted" boolean [not null]
  "device_id" integer [not null]
  "object_id" integer [not null]
}

Таблица "device_output_name" {
  "device_id" integer [not null]
  "record_added_at" timestamp [not null]
  "label" "character varying(100)" [not null]
  "number" integer [not null]
}

Таблица "geofence_points" {
  "longitude" numeric [not null]
  "number" integer [not null]
  "zone_id" integer [not null]
  "record_added_at" timestamp [not null]
  "latitude" numeric [not null]
}

Таблица "custom_fields" {
  "record_added_at" timestamp [not null]
  "entity_id" integer [not null]
  "is_required" boolean [not null]
  "custom_field_label" text [not null]
  "parameters" jsonb
  "custom_field_type" integer [not null]
  "description" text
  "custom_field_id" integer [not null]
}

Таблица "places_decimal_fields" {
  "field_id" integer [not null]
  "record_added_at" timestamp [not null]
  "place_id" integer [not null]
  "value" numeric [not null]
}

Таблица "task_history" {
  "task_id" integer [not null]
  "activity" integer [not null]
  "task_history_id" integer [not null]
  "record_added_at" timestamp [not null]
  "user_id" integer [not null]
  "event_datetime" timestamp [not null]
  "payload" text
}

Таблица "tags" {
  "tag_label" "character varying(64)" [not null]
  "color" "character varying(6)"
  "user_id" integer [not null]
  "record_added_at" timestamp [not null]
  "tag_id" integer [not null]
}

Таблица "places" {
  "description" text
  "custom_fields" jsonb
  "place_id" integer [not null]
  "external_id" "character varying(32)"
  "record_added_at" timestamp [not null]
  "user_id" integer
  "latitude" numeric
  "radius" integer
  "place_label" "character varying(256)"
  "assigned_datetime" timestamp
  "address" "character varying(256)"
  "longitude" numeric
}

Таблица "status_listings" {
  "user_id" integer [not null]
  "is_supervisor_controlled" boolean [not null]
  "is_deleted" boolean [not null]
  "status_listing_id" integer [not null]
  "is_employee_controlled" boolean [not null]
  "record_added_at" timestamp [not null]
  "status_listing_label" "character varying(200)" [not null]
}

Таблица "models" {
  "record_added_at" timestamp [not null]
  "model_id" integer [not null]
  "has_battery_level" boolean [not null]
  "alternative_label" "character varying(50)" [not null]
  "vendor" "character varying(30)" [not null]
  "is_clone" boolean
  "has_altitude" boolean [not null]
  "has_phone" boolean [not null]
  "type_output_control" "character varying(30)" [not null]
  "has_gsm_roaming" boolean [not null]
  "has_gsm_level" boolean [not null]
  "model" "character varying(255)" [not null]
  "type_special_control" "character varying(255)" [not null]
  "digital_amount" integer [not null]
  "has_detach_button" boolean [not null]
  "has_gsm_name" boolean [not null]
  "analog_amount" integer [not null]
  "outputs_amount" integer [not null]
}

Таблица "vehicle_trackers_history" {
  "vehicle_id" integer [not null]
  "record_added_at" timestamp [not null]
  "object_id" integer [not null]
  "changed_datetime" timestamp [not null]
  "vehicle_tracker_history_id" integer [not null]
}

Таблица "groups" {
  "group_id" integer [not null]
  "group_color" "character varying(6)" [not null]
  "group_label" "character varying(255)" [not null]
  "client_id" integer [not null]
  "record_added_at" timestamp [not null]
}

Таблица "sensor_description" {
  "record_added_at" timestamp [not null]
  "parameters" jsonb
  "input_id" integer [not null]
  "accuracy" numeric [not null]
  "sensor_units" "character varying(10)"
  "multiplier" doubleprecision [not null]
  "input_label" "character varying(64)"
  "sensor_label" "character varying(100)"
  "units_type" integer [not null]
  "divider" doubleprecision [not null]
  "group_id" integer [not null]
  "sensor_id" integer [not null]
  "device_id" integer [not null]
  "sensor_type" "character varying(45)" [not null]
  "group_type" integer [not null]
  "calibration_data" jsonb
}

Таблица "entities" {
  "entity_label" jsonb
  "record_added_at" timestamp [not null]
  "entity_id" integer [not null]
  "builtin_type" integer [not null]
  "user_id" integer [not null]
}

Таблица "zones" {
  "address" "character varying(255)"
  "radius" integer [not null]
  "zone_id" integer [not null]
  "circle_center_latitude" numeric [not null]
  "client_id" integer [not null]
  "zone_label" "character varying(100)"
  "color" "character varying(6)" [not null]
  "zone_type" "character varying(20)" [not null]
  "circle_center_longitude" numeric [not null]
  "latitude" numeric [not null]
  "record_added_at" timestamp [not null]
  "longitude" numeric [not null]
}

Таблица "vehicles" {
  "vehicle_id" integer [not null]
  "payload_length" numeric
  "vin" "character varying(20)"
  "free_insurance_policy_number" "character varying(50)"
  "vehicle_label" "character varying(100)"
  "payload_width" numeric
  "color" "character varying(6)"
  "trailer" "character varying(255)"
  "object_id" integer
  "vehicle_status_id" integer
  "liability_insurance_valid_till" timestamp
  "manufacture_year" integer
  "fuel_grade" "character varying(16)"
  "fuel_cost" numeric
  "fuel_tank_volume" numeric
  "model" "character varying(100)"
  "garage_id" integer
  "payload_height" numeric
  "max_speed" numeric
  "registration_number" "character varying(32)"
  "tyre_size" "character varying(50)"
  "passenger_capacity" integer
  "record_added_at" timestamp [not null]
  "trailer_reg_number" "character varying(32)"
  "free_insurance_valid_till_date" timestamp
  "gross_weight" numeric
  "standard_fuel_consumption" numeric
  "fuel_type" integer
  "payload_weight" numeric
  "additional_info" text
  "vehicle_subtype" "character varying(32)"
  "liability_insurance_policy_number" "character varying(50)"
  "frame_number" "character varying(32)"
  "user_id" integer [not null]
  "vehicle_type" integer [not null]
  "chassis_number" "character varying(32)"
  "tyres_number" integer
  "wheel_arrangement" "character varying(16)"
}

Таблица "tag_links" {
  "entity_id" integer [not null]
  "record_added_at" timestamp [not null]
  "entity_type" integer [not null]
  "ordinal" integer [not null]
  "tag_id" integer [not null]
}

Таблица "rules" {
  "rule_id" integer [not null]
  "object_id" integer [not null]
  "parameters" jsonb
  "alert_phone" "character varying(210)" [not null]
  "event_type" "character varying(100)" [not null]
  "client_id" integer [not null]
  "is_push_enabled" boolean [not null]
  "event_comment1" "character varying(255)" [not null]
  "event_label" "character varying(255)" [not null]
  "description" "character varying(255)" [not null]
  "record_added_at" timestamp [not null]
  "alert_sms" text [not null]
  "event_group" integer [not null]
  "created_at" timestamp [not null]
  "maximum" integer [not null]
  "is_deleted" boolean [not null]
  "alert_email" text [not null]
  "event_comment2" "character varying(255)" [not null]
}

Таблица "status_history" {
  "longitude" numeric
  "new_status_id" integer
  "status_history_id" integer [not null]
  "device_id" integer [not null]
  "updated_by" integer [not null]
  "address" "character varying(255)"
  "latitude" numeric
  "record_added_at" timestamp [not null]
  "server_datetime" timestamp [not null]
  "changed_datetime" timestamp
  "old_status_id" integer
}

Таблица "rules2zones" {
  "zone_id" integer [not null]
  "record_added_at" timestamp [not null]
  "rule_id" integer [not null]
}

Таблица "forms" {
  "object_id" integer [not null]
  "description" text
  "form_label" "character varying(255)" [not null]
  "fields" text
  "created_at" timestamp [not null]
  "submission_address" "character varying(255)"
  "submission_latitude" numeric
  "form_id" integer [not null]
  "submission_longitude" numeric
  "is_submission_in_zone" boolean [not null]
  "values" text
  "record_added_at" timestamp [not null]
  "task_id" integer
  "submitted_at" timestamp
}


Таблица "rules2objects" {
  "object_params" jsonb
  "param_group_number" integer [not null]
  "object_id" integer [not null]
  "record_added_at" timestamp [not null]
  "rule_id" integer [not null]
}

Таблица "tasks" {
  "time_from" timestamp
  "stay_duration_minutes" interval
  "external_id" "character varying(100)"
  "object_id" integer
  "task_type" integer
  "arrival_duration_minutes" interval
  "status" integer
  "arrival_datetime" timestamp
  "record_added_at" timestamp [not null]
  "task_id" integer [not null]
  "user_id" integer
  "status_change_datetime" timestamp
  "order_sort" integer
  "time_to" timestamp
  "max_delay_minuts" integer
  "is_stay_control_enabled" boolean
  "address" "character varying(255)"
  "task_label" "character varying(200)" [not null]
  "longitude" numeric
  "created_by" integer
  "description" text [not null]
  "radius" integer
  "latitude" numeric
  "stay_duration" integer
  "created_at" timestamp [not null]
  "custom_fields" jsonb
  "parent_task_id" integer
}

Таблица "places_bigint_fields" {
  "field_id" integer [not null]
  "value" bigint [not null]
  "place_id" integer [not null]
  "record_added_at" timestamp [not null]
}

Таблица "devices" {
  "is_sim_blocked" boolean [not null]
  "device_id" integer [not null]
  "device_imei" "character varying(64)" [not null]
  "network_label" "character varying(50)" [not null]
  "status_listing_id" integer [not null]
  "signal_level" numeric [not null]
  "phone" "character varying(32)" [not null]
  "has_roaming" boolean [not null]
  "created_at" timestamp [not null]
  "owner_id" integer [not null]
  "record_added_at" timestamp [not null]
}

Таблица "description_parameters" {
  "description" "character varying(150)"
  "record_added_at" timestamp [not null]
  "type" "character varying(100)" [not null]
  "key" integer [not null]
}

Таблица "users" {
  "company_label" "character varying(255)" [not null]
  "registration_datetime" timestamp
  "first_name" "character varying(100)" [not null]
  "master_id" integer
  "last_name" "character varying(100)" [not null]
  "birth_date" timestamp
  "timezone_label" "character varying(30)"
  "middle_name" "character varying(100)" [not null]
  "user_id" integer [not null]
  "locale" "character varying(10)" [not null]
  "record_added_at" timestamp [not null]
}

Таблица "counters" {
  "sensor_id" integer
  "multiplier" numeric [not null]
  "counter_id" integer [not null]
  "device_id" integer [not null]
  "counter_type" integer [not null]
  "record_added_at" timestamp [not null]
}

Таблица "employees" {
  "driver_license_valid_till" timestamp
  "record_added_at" timestamp [not null]
  "last_name" "character varying(100)"
  "department_id" integer
  "citizen_id_number" "character varying(32)"
  "first_name" "character varying(100)"
  "driver_license_categories" "character varying(32)"
  "user_id" integer [not null]
  "phone_number" "character varying(32)"
  "object_id" integer
  "is_deleted" boolean [not null]
  "driver_license_issue_date" boolean
  "hardware_key" "character varying(64)"
  "middle_name" "character varying(100)"
  "address" "character varying(255)"
  "latitude" numeric
  "employee_id" integer [not null]
  "personnel_number" "character varying(15)"
  "fuel_cost" doubleprecision
  "driver_license_number" "character varying(32)"
  "email" "character varying(100)"
  "fuel_consumption" doubleprecision
  "radius" integer [not null]
  "longitude" numeric
}

Таблица "places_longtext_fields" {
  "field_id" integer [not null]
  "value" text [not null]
  "record_added_at" timestamp [not null]
  "place_id" integer [not null]
}

Таблица "raw_device_data" {
  "device_id" integer
  "device_time" timestamp
  "created_at" timestamp
  "gps_fix_type" integer
  "longitude" integer
  "latitude" integer
  "altitude" integer
  "speed" integer
  "satellites" integer
  "hdop" integer
  "event_id" integer
  "inputs" jsonb
  "states" jsonb
}

Таблица "groups_objects" {
  "groups_client_id" integer
  "objects_client_id" integer

  Индексы {
    (groups_client_id, objects_client_id) [pk]
  }
}

Связь:"employees"."employee_id" < "checkins"."employee_id"

Связь:"objects"."object_id" < "checkins"."object_id"

Связь:"forms"."form_id" < "checkins"."form_id"

Связь:"sensor_description"."sensor_id" < "counters"."sensor_id"

Связь:"devices"."device_id" < "counters"."device_id"

Связь:"entities"."entity_id" < "custom_fields"."entity_id"

Связь:"departments"."department_id" < "employees"."department_id"

Связь:"users"."user_id" < "departments"."user_id"

Связь:"description_parameters"."key" < "counters"."counter_type"

Связь:"description_parameters"."key" < "custom_fields"."custom_field_type"

Связь:"description_parameters"."key" < "driver_history"."updated_by"

Связь:"description_parameters"."key" < "entities"."builtin_type"

Связь:"description_parameters"."key" < "sensor_description"."units_type"

Связь:"description_parameters"."key" < "status_history"."updated_by"

Связь:"description_parameters"."key" < "tasks"."status"

Связь:"description_parameters"."key" < "tasks"."created_at"

Связь:"description_parameters"."key" < "tasks"."task_type"

Связь:"description_parameters"."key" < "vehicles"."fuel_type"

Связь:"description_parameters"."key" < "task_history"."activity"

Связь:"description_parameters"."key" < "sensor_description"."group_type"

Связь:"devices"."device_id" < "device_output_name"."device_id"

Связь:"status_listings"."status_listing_id" < "devices"."status_listing_id"

Связь:"employees"."employee_id" < "driver_history"."new_employee_id"

Связь:"employees"."employee_id" < "driver_history"."old_employee_id"

Связь:"objects"."object_id" < "driver_history"."object_id"

Связь:"objects"."object_id" < "employees"."object_id"

Связь:"users"."user_id" < "employees"."user_id"

Связь:"users"."user_id" < "entities"."user_id"

Связь:"tasks"."task_id" < "forms"."task_id"

Связь:"objects"."object_id" < "forms"."object_id"

Связь:"objects"."object_id" < "tasks"."object_id"

Связь:"users"."user_id" < "garages"."user_id"

Связь:"groups"."client_id" < "groups_objects"."groups_client_id"

Связь:"objects"."client_id" < "groups_objects"."objects_client_id"

Связь:"models"."model" < "objects"."model"

Связь:"devices"."device_id" < "objects"."device_id"

Связь:"users"."user_id" < "places"."user_id"

Связь:"custom_fields"."custom_field_id" < "places_bigint_fields"."field_id"

Связь:"places"."place_id" < "places_bigint_fields"."place_id"

Связь:"custom_fields"."custom_field_id" < "places_decimal_fields"."field_id"

Связь:"places"."place_id" < "places_decimal_fields"."place_id"

Связь:"custom_fields"."custom_field_id" < "places_linked_entity_fields"."field_id"

Связь:"places"."place_id" < "places_linked_entity_fields"."place_id"

Связь:"custom_fields"."custom_field_id" < "places_longtext_fields"."field_id"

Связь:"places"."place_id" < "places_longtext_fields"."place_id"

Связь:"custom_fields"."custom_field_id" < "places_text_fields"."field_id"

Связь:"places"."place_id" < "places_text_fields"."place_id"

Связь:"rules"."rule_id" < "rules2zones"."rule_id"

Связь:"objects"."object_id" < "rules2objects"."object_id"

Связь:"rules"."rule_id" < "rules2objects"."object_id"

Связь:"zones"."zone_id" < "rules2zones"."zone_id"

Связь:"devices"."device_id" < "sensor_description"."device_id"

Связь:"statuses"."status_id" < "status_history"."new_status_id"

Связь:"statuses"."status_id" < "status_history"."old_status_id"

Связь:"devices"."device_id" < "status_history"."device_id"

Связь:"users"."user_id" < "status_listings"."user_id"

Связь:"status_listings"."status_listing_id" < "statuses"."listing_id"

Связь:"tags"."tag_id" < "tag_links"."tag_id"

Связь:"users"."user_id" < "tags"."user_id"

Связь:"tasks"."task_id" < "task_history"."task_id"

Связь:"users"."user_id" < "task_history"."user_id"

Связь:"tasks"."parent_task_id" < "tasks"."task_id"

Связь:"users"."user_id" < "tasks"."user_id"

Связь:"users"."master_id" < "users"."user_id"

Связь:"users"."user_id" < "users2zones"."user_id"

Связь:"zones"."zone_id" < "users2zones"."zone_id"

Связь:"vehicles"."vehicle_id" < "vehicle_service_tasks"."vehicle_id"

Связь:"objects"."object_id" < "vehicle_trackers_history"."object_id"

Ref:"vehicles"."vehicle_id" < "vehicle_trackers_history"."vehicle_id"

Ref:"garages"."garage_id" < "vehicles"."garage_id"

Ref:"objects"."object_id" < "vehicles"."object_id"

Ref:"users"."user_id" < "vehicles"."user_id"

Ref:"zones"."zone_id" < "geofence_points"."zone_id"

Ref:"devices"."device_id" < "raw_device_data"."device_id"

Ref:"users"."user_id" < "devices"."owner_id"

Ref:"users"."user_id" < "objects"."client_id"

```

{% endcode %}

### Частота обновления

Данные в этой схеме синхронизируются с основной БД. Обновления происходят инкрементально по мере изменений в исходной базе данных MySQL, как правило, менее чем через 5 минут после изменения в источнике.

### `description_parameters`

Система включает справочные данные для стандартизации значений по всей базе данных:

<table><thead><tr><th width="167.1817626953125">Тип справочника</th><th width="173.9090576171875">Описание</th><th>Примеры значений</th></tr></thead><tbody><tr><td>Определения типов</td><td>Стандартные типы сущностей</td><td><code>vehicle_type: car, truck, bus</code></td></tr><tr><td>Коды статусов</td><td>Значения статусов задач и системы</td><td><code>tasks_status: unassigned, assigned, done</code></td></tr><tr><td>Определения единиц</td><td>Единицы измерения для датчиков</td><td><code>units_type: liter, gallon, celsius</code></td></tr><tr><td>Классификации сущностей</td><td>Категории бизнес-сущностей</td><td><code>entities_type: place, task, customer</code></td></tr></tbody></table>

### Ключевые таблицы по категориям

Таблицы в **`raw_business_data`** схеме организованы по функциональным категориям для облегчения навигации. В таблице ниже приведены ключевые таблицы по их делевому назначению:

Основные бизнес-сущности

<details>

<summary><strong><code>users</code></strong></summary>

**Описание**: Учетные записи пользователей, содержащие информацию профиля, принадлежность к компании, настройки локализации (часовой пояс, локаль) и иерархические связи через master\_id для многоуровневых структур аккаунтов

<table><thead><tr><th width="145">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>user_id</code> - Уникальный идентификатор пользователя<br>- <code>company_label</code> - Название компании, связанной с пользователем<br>- <code>first_name</code> - Имя пользователя<br>- <code>last_name</code> - Фамилия пользователя<br>- <code>middle_name</code> - Отчество пользователя<br>- <code>locale</code> - Настройки языка пользователя<br>- <code>timezone_label</code> - Часовой пояс в формате IANA<br>- <code>master_id</code> - Идентификатор основного пользователя (если текущий является подчиненным)<br>- <code>registration_datetime</code> - Дата регистрации в системе<br>- <code>birth_date</code> - Дата рождения пользователя</td></tr><tr><td><strong>Связи</strong></td><td>Родительский пользователь через <code>master_id</code>, связанный с <code>employees</code>, <code>departments</code>, <code>places</code>, <code>tasks</code> через <code>user_id</code></td></tr><tr><td><strong>Особые замечания</strong></td><td>Центральная сущность, связывающая организационные данные; <code>master_id</code> обеспечивает иерархии пользователей для многоуровневых структур аккаунтов</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>employees</code></strong></summary>

**Описание**: Записи сотрудников и водителей, используемые для представления людей, работающих в организации, включая личную информацию, данные о правах, назначения в отделы, аппаратные ключи для идентификации iButton/RFID и данные местоположения с поддержкой геозон

<table><thead><tr><th width="143">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>employee_id</code> - Идентификатор сущности сотрудника<br>- <code>user_id</code> - Идентификатор сущности пользователя<br>- <code>object_id</code> - Идентификатор сущности объекта<br>- <code>department_id</code> - Идентификатор отдела, в который назначен сотрудник<br>- <code>first_name</code> - Атрибут first_name таблицы employees<br>- <code>last_name</code> - Атрибут last_name таблицы employees<br>- <code>middle_name</code> - Атрибут middle_name таблицы employees<br>- <code>driver_license_number</code> - Номер водительского удостоверения<br>- <code>driver_license_categories</code> - Категории водительского удостоверения<br>- <code>driver_license_issue_date</code> - Дата выдачи водительского удостоверения<br>- <code>driver_license_valid_till</code> - Дата истечения срока действия водительского удостоверения<br>- <code>hardware_key</code> - Аппаратный ключ<br>- <code>email</code> - Электронная почта сотрудника<br>- <code>phone_number</code> - Телефон сотрудника без знака "+"<br>- <code>address</code> - Адрес местоположения<br>- <code>personnel_number</code> - Табельный/персональный номер сотрудника/водителя<br>- <code>citizen_id_number</code> - Номер социального страхования<br>- <code>latitude</code> - Местоположение, связанное с этим сотрудником<br>- <code>longitude</code> - Местоположение, связанное с этим сотрудником<br>- <code>radius</code> - Местоположение, связанное с этим сотрудником в метрах<br>- <code>fuel_consumption</code> - Атрибут fuel_consumption таблицы employees<br>- <code>fuel_cost</code> - Атрибут fuel_cost таблицы employees<br>- <code>is_deleted</code> - Атрибут is_deleted таблицы employees</td></tr><tr><td><strong>Связи</strong></td><td>Связи с <code>users</code>, <code>departments</code>, <code>objects</code> (назначенный трекер), отслеживается в <code>driver_history</code> и <code>checkins</code></td></tr><tr><td><strong>Особые замечания</strong></td><td>Аппаратный ключ обеспечивает идентификацию водителя через iButton или RFID; поддерживает геозоны с <code>latitude</code>, <code>longitude</code>, <code>radius</code> поля</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>departments</code></strong></summary>

**Описание**: Организационные подразделения с данными геолокации (широта, долгота, радиус), обеспечивающие аналитику на основе геозон для отчетности по отделам и связывания местоположения сотрудников

<table><thead><tr><th width="156">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>department_id</code> - Идентификатор сущности отдела<br>- <code>user_id</code> - Идентификатор сущности пользователя<br>- <code>department_label</code> - Атрибут department_label таблицы departments<br>- <code>latitude</code> - Местоположение, связанное с этим отделом<br>- <code>longitude</code> - Местоположение, связанное с этим отделом<br>- <code>radius</code> - Размер геолокации в метрах<br>- <code>address</code> - Атрибут address таблицы departments</td></tr><tr><td><strong>Связи</strong></td><td>Связывает сотрудников с организационной структурой через <code>department_id</code></td></tr><tr><td><strong>Особые замечания</strong></td><td>Поля местоположения поддерживают аналитику на основе геозон для отчетности по отделам</td></tr></tbody></table>

</details>

Отслеживание и мониторинг

<details>

<summary><strong><code>devices</code></strong></summary>

**Описание**: Реестр физических трекинговых устройств с аппаратными идентификаторами (IMEI), информацией о SIM-карте, статусом сетевого подключения (уровень сигнала, роуминг, оператор) и назначениями статусов для управления жизненным циклом устройства

<table><thead><tr><th width="138">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>device_id</code> - Идентификатор устройства<br>- <code>owner_id</code> - Идентификатор владельца устройства в аккаунте, в котором был добавлен маяк<br>- <code>device_imei</code> - IMEI устройства<br>- <code>phone</code> - Номер SIM-карты устройства<br>- <code>status_listing_id</code> - Идентификатор статуса устройства<br>- <code>network_label</code> - Название сети, к которой подключена SIM-карта<br>- <code>signal_level</code> - Уровень сигнала устройства<br>- <code>has_roaming</code> - Флаг доступности роуминга<br>- <code>is_sim_blocked</code> - Флаг блокировки SIM-карты<br>- <code>created_at</code> - Дата и время создания записи</td></tr><tr><td><strong>Связи</strong></td><td>Основная сущность, связывающая с <code>objects</code>, <code>models</code>, <code>sensor_description</code>, <code>counters</code>; <code>owner_id</code> references <code>users.user_id</code></td></tr><tr><td><strong>Особые замечания</strong></td><td>Вся телематическая информация в <code>raw_telematics_data</code> схеме ссылается на эту таблицу через <code>device_id</code></td></tr></tbody></table>

</details>

<details>

<summary><strong><code>objects</code></strong></summary>

**Описание**: Центральный реестр контролируемых объектов (транспортные средства, активы, персонал), связывающий физические устройства с организационной структурой через client\_id и group\_id, представляющий "отслеживаемую единицу" с одним активным объектом на устройство

<table><thead><tr><th width="148">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>object_id</code> - Идентификатор сущности объекта<br>- <code>client_id</code> - Идентификатор сущности клиента<br>- <code>device_id</code> - Идентификатор сущности устройства<br>- <code>object_label</code> - Название объекта<br>- <code>model</code> - Модель устройства<br>- <code>group_id</code> - Идентификатор группы сущностей<br>- <code>create_datetime</code> - Дата и время создания новой строки на сервере<br>- <code>is_deleted</code> - Атрибут is_deleted таблицы objects<br>- <code>is_clone</code> - Признак клона</td></tr><tr><td><strong>Связи</strong></td><td>Центральный узел, связывающий устройства с пользователями (<code>client_id</code>), деталями транспортного средства, историей трекинга, задачами и правилами</td></tr><tr><td><strong>Особые замечания</strong></td><td>Представляет "отслеживаемую единицу" в системе; по одному объекту на устройство в активном использовании</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>models</code></strong></summary>

**Описание**: Центральный реестр контролируемых объектов (транспортные средства, активы, персонал), связывающий физические устройства с организационной структурой через client\_id и group\_id, представляющий "отслеживаемую единицу" с одним активным объектом на устройство

<table><thead><tr><th width="135">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>model_id</code> - Идентификатор модели сущности<br>- <code>model</code> - Атрибут model таблицы models<br>- <code>vendor</code> - Название компании-производителя трекера<br>- <code>alternative_label</code> - Атрибут alternative_label таблицы models<br>- <code>analog_amount</code> - Количество аналоговых входов трекера<br>- <code>digital_amount</code> - Количество дискретных входов трекера<br>- <code>outputs_amount</code> - Количество дискретных выходов трекера<br>- <code>has_battery_level</code> - Определяет, передаёт ли трекер показания заряда батареи<br>- <code>has_altitude</code> - Определяет, передаёт ли трекер высоту над уровнем моря<br>- <code>has_phone</code> - Есть ли SIM-карта?<br>- <code>has_gsm_level</code> - Может ли трекер передавать уровень GSM-сигнала?<br>- <code>has_gsm_name</code> - Может ли трекер передавать название GSM-сети или код оператора (MCC + MNC)?<br>- <code>has_gsm_roaming</code> - Может ли трекер передавать статус роуминга?<br>- <code>has_detach_button</code> - Есть ли у трекера датчик отсоединения?<br>- <code>type_output_control</code> - Профиль управления выходами трекера<br>- <code>type_special_control</code> - Содержит специализированные настройки и функциональные модули для отдельных моделей устройств, такие как режим опасного вождения (hbm_telfm) для оборудования Teltonika<br>- <code>is_clone</code> - Является ли модель клоном другой модели?</td></tr><tr><td><strong>Содержимое</strong></td><td>Булевы флаги возможностей указывают, какие поля данных доступны для данного типа устройства</td></tr><tr><td><strong>Особые замечания</strong></td><td>Используйте флаги возможностей для определения допустимых датчиков и входов при запросе телематических данных</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>sensor_description</code></strong></summary>

**Описание**: Всесторонняя конфигурация датчиков, связывающая входы устройства с бизнес-логикой, включая отображения входов, единицы измерения, коэффициенты преобразования (множитель/делитель), таблицы калибровки для датчиков топлива, пороги точности и логику группировки для агрегированных показаний датчиков

<table><thead><tr><th width="142">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>sensor_id</code> - Идентификатор сущности датчика<br>- <code>device_id</code> - Идентификатор сущности устройства<br>- <code>sensor_label</code> - Название датчика для интерфейса<br>- <code>input_label</code> - Название поля сообщения (атрибут), из которого берутся данные датчика. Если равно "input_status", то это дискретный датчик<br>- <code>sensor_type</code> - Тип датчика<br>- <code>units_type</code> - Единицы измерения<br>- <code>multiplier</code> - Множитель — число, на которое умножается значение поля. Только для измерительных датчиков<br>- <code>divider</code> - Делитель — число, на которое делится значение поля. Только для измерительных датчиков<br>- <code>accuracy</code> - Указанный процент для расчёта абсолютной погрешности объёма бака. Эта погрешность используется для определения заправок или сливов. Применяется только для датчиков топлива<br>- <code>calibration_data</code> - Атрибут calibration_data таблицы sensor_description<br>- <code>input_id</code> - Номер входа для дискретного датчика<br>- <code>group_id</code> - Датчики одного типа с одинаковыми group_id и source_id считаются принадлежащими одной группе. Их данные суммируются или усредняются в зависимости от значения group_type. Это требуется для агрегированных датчиков. Используется в измерительных датчиках<br>- <code>group_type</code> - 0 — суммировать значения датчиков в группе, 1 — усреднять<br>- <code>sensor_units</code> - Название единицы, введённое пользователем, если units_type=0 (пользовательская)<br>- <code>parameters</code> - Дополнительный объект с параметрами parent_ids — необязательный массив parent_ids для составного датчика. volume — double. Необязательно. Объём для составного датчика. parent_ids — необязательный. Массив int. Массив parent_ids для составного датчика. volume — необязательный. Double. Объём для составного датчика. min — необязательный. Double. Минимальное допустимое необработанное значение для датчика. max — необязательный. Double. Максимальное допустимое необработанное значение для датчика. max_lowering_by_time — необязательный. Double. Максимальное допустимое снижение значения в час. max_lowering_by_mileage — необязательный. Double. Максимальное допустимое снижение значения на 100 км. ignore_drains_in_move — необязательный. Boolean. По умолчанию false. Если true, сливы топлива не будут обнаруживаться во время движения. ignore_refuels_in_move — необязательный. Boolean. По умолчанию false. Если true, заправки не будут обнаруживаться во время движения. refuel_gap_minutes — необязательный. Integer. По умолчанию 5. Время в минутах после начала движения, в течение которого заправки будут обнаружены во время движения. custom_field_name — необязательный. Boolean. По умолчанию false. Параметр определяет, было ли поле input_name введено пользователем как пользовательское значение. Это имеет смысл только если модель трекера поддерживает функцию has_custom_fields</td></tr><tr><td><strong>Связи</strong></td><td>Связывает входы устройства (из <code>raw_telematics_data.inputs</code>) с бизнес-логикой через <code>device_id</code> и <code>input_label</code> matching</td></tr><tr><td><strong>Особые замечания</strong></td><td><code>calibration_data</code> (JSONB) хранит специфические для датчика таблицы калибровки для датчиков уровня топлива; <code>multiplier</code> и <code>divider</code> преобразовывать необработанные значения в единицы</td></tr></tbody></table>

</details>

Управление активами

<details>

<summary><strong><code>vehicles</code></strong></summary>

**Описание**: Всесторонний реестр транспортных средств, содержащий спецификации (габариты, вес, грузоподъёмность), документацию (VIN, регистрация, страховка), эксплуатационные параметры (расход топлива, объём бака) и текущее назначение трекера через object\_id для управления парком и отслеживания соответствия требованиям

<table><thead><tr><th width="144">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>vehicle_id</code> - Идентификатор сущности транспортного средства<br>- <code>user_id</code> - Идентификатор сущности пользователя<br>- <code>object_id</code> - Идентификатор сущности объекта<br>- <code>garage_id</code> - Идентификатор сущности гаража<br>- <code>vehicle_label</code> - Атрибут vehicle_label таблицы vehicles<br>- <code>registration_number</code> - Регистрационный номер/номерной знак транспортного средства<br>- <code>vin</code> - Атрибут vin таблицы vehicles<br>- <code>manufacture_year</code> - Атрибут manufacture_year таблицы vehicles<br>- <code>fuel_type</code> - Атрибут fuel_type таблицы vehicles<br>- <code>fuel_cost</code> - Атрибут fuel_cost таблицы vehicles<br>- <code>fuel_tank_volume</code> - Атрибут fuel_tank_volume таблицы vehicles<br>- <code>max_speed</code> - Атрибут max_speed таблицы vehicles<br>- <code>model</code> - Атрибут model таблицы vehicles<br>- <code>color</code> - Атрибут color таблицы vehicles<br>- <code>trailer</code> - Атрибут trailer таблицы vehicles<br>- <code>additional_info</code> - Атрибут additional_info таблицы vehicles<br>- <code>vehicle_type</code> - Атрибут vehicle_type таблицы vehicles<br>- <code>vehicle_subtype</code> - Атрибут vehicle_subtype таблицы vehicles<br>- <code>vehicle_status_id</code> - Идентификатор статуса транспортного средства<br>- <code>chassis_number</code> - Атрибут chassis_number таблицы vehicles<br>- <code>frame_number</code> - Атрибут frame_number таблицы vehicles<br>- <code>trailer_reg_number</code> - Атрибут trailer_reg_number таблицы vehicles<br>- <code>payload_weight</code> - Атрибут payload_weight таблицы vehicles<br>- <code>payload_height</code> - Атрибут payload_height таблицы vehicles<br>- <code>payload_length</code> - Атрибут payload_length таблицы vehicles<br>- <code>payload_width</code> - Атрибут payload_width таблицы vehicles<br>- <code>passenger_capacity</code> - Максимальное количество пассажиров<br>- <code>gross_weight</code> - Атрибут gross_weight таблицы vehicles<br>- <code>standard_fuel_consumption</code> - Обычный средний расход топлива в литрах на 100 км<br>- <code>fuel_grade</code> - Атрибут fuel_grade таблицы vehicles<br>- <code>wheel_arrangement</code> - Атрибут wheel_arrangement таблицы vehicles<br>- <code>tyre_size</code> - Размеры автомобиля: габариты и размер колёс<br>- <code>tyres_number</code> - Количество колёс<br>- <code>liability_insurance_policy_number</code> - Атрибут liability_insurance_policy_number таблицы vehicles<br>- <code>liability_insurance_valid_till</code> - Дата, до которой действует гражданская страховка<br>- <code>free_insurance_policy_number</code> - Атрибут free_insurance_policy_number таблицы vehicles<br>- <code>free_insurance_valid_till_date</code> - Дата, до которой действует бесплатная страховка</td></tr><tr><td><strong>Связи</strong></td><td>Связи с <code>objects</code> (текущий трекер), <code>garages</code> (место обслуживания), <code>vehicle_service_tasks</code>; отслеживается в <code>vehicle_trackers_history</code></td></tr><tr><td><strong>Особые замечания</strong></td><td>Поля физических размеров (<code>payload_length</code>, <code>payload_width</code>, <code>payload_height</code>, <code>gross_weight</code>) поддерживают аналитику планирования загрузки; даты страховки обеспечивают отслеживание соблюдения требований</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>garages</code></strong></summary>

**Описание**: Места обслуживания и техобслуживания с географическими координатами (широта, долгота, радиус), контактной информацией для механиков и диспетчеров, обеспечивающие обнаружение посещений обслуживания на основе геозон и анализ близости

<table><thead><tr><th width="135">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>garage_id</code> - Идентификатор сущности гаража<br>- <code>user_id</code> - Идентификатор сущности пользователя<br>- <code>latitude</code> - Объект местоположения<br>- <code>longitude</code> - Объект местоположения<br>- <code>radius</code> - Размер геолокации в метрах<br>- <code>address</code> - Объект местоположения<br>- <code>organization_label</code> - Идентификатор депо<br>- <code>mechanic_name</code> - Имя механика<br>- <code>dispatcher_name</code> - Имя диспетчера</td></tr><tr><td><strong>Связи</strong></td><td>Ссылается <code>vehicles.garage_id</code> для назначения места обслуживания</td></tr><tr><td><strong>Особые замечания</strong></td><td>Поля местоположения позволяют обнаруживать посещения обслуживания на основе геозон и выполнять анализ близости</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>vehicle_service_tasks</code></strong></summary>

**Описание**: Отслеживание графика обслуживания и истории с множеством типов триггеров (по дате, по пробегу, по моточасам), периодическими интервалами задач, многоканальными уведомлениями (email, SMS, push) и разделением запланированных (is\_repeat) и незапланированных событий обслуживания

<table><thead><tr><th width="132">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>service_task_id</code> - Идентификатор сущности сервисной задачи<br>- <code>vehicle_id</code> - Идентификатор сущности транспортного средства<br>- <code>description</code> - Атрибут description таблицы vehicle_service_tasks<br>- <code>status</code> - Значение атрибута status<br>- <code>cost</code> - Атрибут cost таблицы vehicle_service_tasks<br>- <code>start_date</code> - Дата и время, связанные с атрибутом start_date<br>- <code>end_date</code> - Дата и время, связанные с атрибутом end_date<br>- <code>completion_date</code> - Дата и время, связанные с атрибутом completion_date<br>- <code>predicted_datetime</code> - Дата и время, связанные с атрибутом predicted_datetime<br>- <code>mileage_limit</code> - Атрибут mileage_limit таблицы vehicle_service_tasks<br>- <code>engine_hours_limit</code> - Атрибут engine_hours_limit таблицы vehicle_service_tasks<br>- <code>start_mileage</code> - Атрибут start_mileage таблицы vehicle_service_tasks<br>- <code>start_engine_hours</code> - Атрибут start_engine_hours таблицы vehicle_service_tasks<br>- <code>mileage_notification_interval</code> - Атрибут mileage_notification_interval таблицы vehicle_service_tasks<br>- <code>engine_hours_notification_interval</code> - Атрибут engine_hours_notification_interval таблицы vehicle_service_tasks<br>- <code>date_notification_interval</code> - Преобразование целого N в N дней<br>- <code>mileage_repeat_interval</code> - Атрибут mileage_repeat_interval таблицы vehicle_service_tasks<br>- <code>engine_hours_repeat_interval</code> - Атрибут engine_hours_repeat_interval таблицы vehicle_service_tasks<br>- <code>date_repeat_interval</code> - Преобразование целого N в N дней<br>- <code>notification_emails</code> - Атрибут notification_emails таблицы vehicle_service_tasks<br>- <code>notification_sms_phone_numbers</code> - Атрибут notification_sms_phone_numbers таблицы vehicle_service_tasks<br>- <code>is_notification_push_enabled</code> - Атрибут is_notification_push_enabled таблицы vehicle_service_tasks<br>- <code>completion_mileage</code> - Атрибут completion_mileage таблицы vehicle_service_tasks<br>- <code>completion_engine_hours</code> - Атрибут completion_engine_hours таблицы vehicle_service_tasks<br>- <code>is_repeat</code> - Атрибут is_repeat таблицы vehicle_service_tasks<br>- <code>is_unplanned</code> - Атрибут is_unplanned таблицы vehicle_service_tasks<br>- <code>comment</code> - Атрибут comment таблицы vehicle_service_tasks</td></tr><tr><td><strong>Содержимое</strong></td><td>Поддерживает три типа триггеров: по дате, по пробегу, по моточасам; настройки уведомлений для email, SMS, push</td></tr><tr><td><strong>Особые замечания</strong></td><td><code>is_repeat</code> и поля интервалов позволяют задавать периодические графики обслуживания; <code>is_unplanned</code> различает плановое и реактивное обслуживание</td></tr></tbody></table>

</details>

Местоположение и маршрутизация

<details>

<summary><strong><code>zones</code></strong></summary>

**Описание**: Геозоны, определяющие виртуальные периметры с использованием кругов или полигонов для мониторинга событий въезда и выезда транспортного средства/актива, поддерживающие автоматизацию на основе правил и аналитику местоположения с цветовой маркировкой для визуального различения

<table><thead><tr><th width="150">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>zone_id</code> - Идентификатор сущности зоны<br>- <code>client_id</code> - Идентификатор сущности клиента<br>- <code>zone_label</code> - Атрибут zone_label таблицы zones<br>- <code>zone_type</code> - Атрибут zone_type таблицы zones<br>- <code>latitude</code> - Необязательный объект, ограничивающий прямоугольник, который может полностью содержать возвращаемый результат<br>- <code>longitude</code> - Необязательный объект, ограничивающий прямоугольник, который может полностью содержать возвращаемый результат<br>- <code>circle_center_latitude</code> - Атрибут circle_center_latitude таблицы zones<br>- <code>circle_center_longitude</code> - Атрибут circle_center_longitude таблицы zones<br>- <code>radius</code> - Размер геолокации в метрах<br>- <code>address</code> - Атрибут address таблицы zones<br>- <code>color</code> - Атрибут color таблицы zones</td></tr><tr><td><strong>Содержимое</strong></td><td>Типы зон включают circle, polygon (определяется через <code>geofence_points</code>), и специальные классификации областей</td></tr><tr><td><strong>Связи</strong></td><td>Ссылается <code>rules2zones</code>, <code>users2zones</code>; вершины полигона хранятся в <code>geofence_points</code></td></tr><tr><td><strong>Особые замечания</strong></td><td>Функции PostGIS можно использовать для проверки принадлежности точки многоугольнику для сложного анализа геозон</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>places</code></strong></summary>

**Описание**: Точки интереса с географическими координатами, определением радиуса и расширяемой поддержкой пользовательских полей для хранения контактной информации клиентов и бизнес-данных, позволяя интеграцию с CRM/ERP через external\_id и формирование отчетов на основе местоположения

<table><thead><tr><th width="129">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>place_id</code> - Идентификатор сущности place<br>- <code>user_id</code> - Идентификатор сущности пользователя<br>- <code>place_label</code> - Атрибут place_label таблицы places<br>- <code>latitude</code> - Объект местоположения<br>- <code>longitude</code> - Объект местоположения<br>- <code>radius</code> - Размер геолокации в метрах<br>- <code>address</code> - Атрибут address таблицы places<br>- <code>description</code> - Атрибут description таблицы places<br>- <code>external_id</code> - Идентификатор для интеграции с внешними системами (CRM)<br>- <code>custom_fields</code> - Дополнительные поля<br>- <code>assigned_datetime</code> - Дата и время назначения точки интереса пользователю</td></tr><tr><td><strong>Связи</strong></td><td>Расширяется значениями пользовательских полей через <code>places_text_fields</code>, <code>places_decimal_fields</code>, <code>places_bigint_fields</code>, <code>places_longtext_fields</code>, <code>places_linked_entity_fields</code></td></tr><tr><td><strong>Особые замечания</strong></td><td><code>custom_fields</code> JSONB обеспечивает быстрый доступ; связанные таблицы позволяют фильтровать и сортировать по пользовательским атрибутам</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>geofence_points</code></strong></summary>

**Описание**: Упорядоченные координаты вершин (поле number определяет последовательность), задающие границы полигона для сложных форм геозон, позволяющие точные географические периметры в дополнение к простым круговым зонам, используются совместно с PostGIS ST\_MakePolygon для геометрических операций

<table><thead><tr><th width="133">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>zone_id</code> - ID зоны, к которой прикреплена эта форма<br>- <code>number</code> - Порядковый номер<br>- <code>latitude</code> - Местоположение<br>- <code>longitude</code> - Местоположение</td></tr><tr><td><strong>Связи</strong></td><td>Несколько записей для <code>zone_id</code> определяют границы полигона; <code>number</code> поле определяет порядок вершин</td></tr><tr><td><strong>Особые замечания</strong></td><td>Запрос с <code>ORDER BY number</code> для восстановления пути полигона; используйте совместно с PostGIS ST_MakePolygon для геометрических операций</td></tr></tbody></table>

</details>

Управление задачами и рабочими процессами

<details>

<summary><strong><code>tasks</code></strong></summary>

**Описание**: Назначения заказов на работу с проверкой местоположения (latitude, longitude, radius), временными окнами (time\_from, time\_to), требованиями по продолжительности визита (stay\_duration\_minutes, arrival\_duration\_minutes), иерархической структурой через parent\_task\_id и отслеживанием статуса для управления полевыми сервисами и доставкой

<table><thead><tr><th width="130">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>task_id</code> - Идентификатор сущности task<br>- <code>user_id</code> - Идентификатор сущности пользователя<br>- <code>object_id</code> - Идентификатор сущности объекта<br>- <code>parent_task_id</code> - Идентификатор родительской задачи<br>- <code>task_label</code> - Атрибут task_label таблицы tasks<br>- <code>status</code> - Значение атрибута status<br>- <code>task_type</code> - Тип задачи: task, route или checkpoint<br>- <code>latitude</code> - Атрибут latitude таблицы tasks<br>- <code>longitude</code> - Атрибут longitude таблицы tasks<br>- <code>radius</code> - Размер геолокации в метрах<br>- <code>arrival_datetime</code> - Когда трекер прибывает в область задачи. ИГНОРИРУЕТСЯ при создании/обновлении<br>- <code>created_at</code> - Атрибут created_at таблицы tasks<br>- <code>status_change_datetime</code> - Дата и время обновления задачи<br>- <code>time_from</code> - Дата и время, связанные с атрибутом time_from<br>- <code>time_to</code> - Дата и время, связанные с атрибутом time_to<br>- <code>stay_duration</code> - Атрибут stay_duration таблицы tasks<br>- <code>stay_duration_minutes</code> - Продолжительность визита. Время, которое мобильный сотрудник должен провести на месте назначения, чтобы успешно завершить задачу. Несколько визитов суммируются<br>- <code>arrival_duration_minutes</code> - Игнорировать случайные визиты короче указанной длительности. При расчете минимальной продолжительности визиты короче указанной будут игнорированы<br>- <code>max_delay_minuts</code> - Допустимая опоздание. Максимальное время, на которое сотрудник может опоздать. Любая задача, завершенная в этот период, будет помечена как «опоздавшая»<br>- <code>is_stay_control_enabled</code> - Атрибут is_stay_control_enabled таблицы tasks<br>- <code>address</code> - Атрибут address таблицы tasks<br>- <code>description</code> - Атрибут description таблицы tasks<br>- <code>custom_fields</code> - Атрибут custom_fields таблицы tasks<br>- <code>external_id</code> - Идентификатор внешней сущности<br>- <code>order_sort</code> - Атрибут order_sort таблицы tasks<br>- <code>created_by</code> - Источник созданной задачи</td></tr><tr><td><strong>Содержимое</strong></td><td>Поддерживает иерархические задачи через <code>parent_task_id</code>; временные окна, определяемые через <code>time_from</code>/<code>time_to</code>; проверка геозоны с местоположением и радиусом</td></tr><tr><td><strong>Связи</strong></td><td>Связи с <code>forms</code> (сбор данных), <code>task_history</code> (изменения статуса), <code>objects</code> (назначенный трекер)</td></tr><tr><td><strong>Особые замечания</strong></td><td><code>stay_duration</code> и <code>arrival_duration_minutes</code> включают мониторинг соответствия для задач доставки и сервиса</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>forms</code></strong></summary>

**Описание**: Конфигурируемые формы сбора данных для фиксации структурированной информации при выполнении задачи или при отметках в мобильном приложении, с полями и значениями, хранящимися в формате JSON, опционной проверкой местоположения (is\_submission\_in\_zone) и обязательными требованиями к отправке при прикреплении к задачам

<table><thead><tr><th width="141">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>form_id</code> - Идентификатор сущности form<br>- <code>task_id</code> - ID задачи, к которой прикреплена эта форма<br>- <code>object_id</code> - Идентификатор сущности объекта<br>- <code>form_label</code> - Метка формы, заданная пользователем<br>- <code>поля</code> - Если true, форма может быть отправлена только в зоне задачи<br>- <code>values</code> - Отображение с ID полей в качестве ключей и объектами field_value в качестве значений. Ключ используется для связывания поля и его соответствующего значения<br>- <code>submitted_at</code> - Дата последней отправки значений формы<br>- <code>submission_latitude</code> - Местоположение, в котором значения формы были отправлены в последний раз<br>- <code>submission_longitude</code> - Местоположение, в котором значения формы были отправлены в последний раз<br>- <code>submission_address</code> - Местоположение, в котором значения формы были отправлены в последний раз<br>- <code>is_submission_in_zone</code> - Если true, форма может быть отправлена только в зоне задачи<br>- <code>description</code> - Дата создания этой формы (или прикрепления к задаче)<br>- <code>created_at</code> - Дата создания этой формы (или прикрепления к задаче)</td></tr><tr><td><strong>Содержимое</strong></td><td><code>поля</code> определяет структуру формы (JSON); <code>values</code> содержит отправленные данные (JSON)</td></tr><tr><td><strong>Связи</strong></td><td>Связи с <code>tasks</code> (связанный work order), <code>objects</code> (отправитель), ссылается в <code>checkins</code></td></tr><tr><td><strong>Особые замечания</strong></td><td>Флаг проверки местоположения <code>is_submission_in_zone</code> включает правила отправки форм на основе геозон</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>checkins</code></strong></summary>

**Описание**: Записи о посещениях и активности на основе местоположения, отправляемые через мобильное приложение, отслеживающие запланированное и фактическое время прибытия (planned\_datetime vs actual\_datetime) с географическими координатами и измерениями точности местоположения (radius) для отчетности по пунктуальности

<table><thead><tr><th width="129">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>checkin_id</code> - Идентификатор сущности checkin<br>- <code>employee_id</code> - Идентификатор сущности сотрудника, также является идентификатором водителей<br>- <code>object_id</code> - Устройство сотрудника<br>- <code>form_id</code> - Идентификатор сущности form<br>- <code>user_id</code> - Пользователь-сотрудник<br>- <code>planned_datetime</code> - Время устройства, когда был выполнен чек-ин<br>- <code>actual_datetime</code> - Время сервера, когда запрос/сообщение было обработано<br>- <code>latitude</code> - Местоположение, в котором были отправлены чек-ины<br>- <code>longitude</code> - Местоположение, в котором были отправлены чек-ины<br>- <code>radius</code> - Ошибка позиционирования в метрах<br>- <code>address</code> - Адрес чек-ина<br>- <code>comment</code> - Атрибут comment таблицы checkins</td></tr><tr><td><strong>Связи</strong></td><td>Соединяет сотрудников с формами и местоположениями; отслеживает отклонения от запланированного расписания</td></tr><tr><td><strong>Особые замечания</strong></td><td>Временное отклонение между <code>planned_datetime</code> и <code>actual_datetime</code> позволяет формировать отчеты о пунктуальности; радиус определяет допустимую погрешность местоположения</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>task_history</code></strong></summary>

**Описание**: Полный аудиторский след событий жизненного цикла задачи, фиксирующий все изменения статусов, назначения, обновления и модификации полей с отметками времени (event\_datetime), указанием пользователя и типами активности (create, update, assign, status\_change), хранящимися в поле payload для целей соответствия и анализа рабочих процессов

<table><thead><tr><th width="137">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>task_history_id</code> - Идентификатор сущности истории задач<br>- <code>task_id</code> - Идентификатор сущности task<br>- <code>user_id</code> - Идентификатор сущности пользователя<br>- <code>activity</code> - Операция, которая произошла. Может быть "create", "update", "assign" или "status_change"<br>- <code>event_datetime</code> - Дата и время события<br>- <code>payload</code> - Зависит от операции. Обычно содержит поля, которые были изменены в ходе операции</td></tr><tr><td><strong>Содержимое</strong></td><td>Типы активности определены в <code>description_parameters</code>; <code>payload</code> содержит детали, специфичные для события (текст)</td></tr><tr><td><strong>Особые замечания</strong></td><td>Необходимо для анализа выполнения задач, отчетности по переходам статусов и отслеживания активности пользователей</td></tr></tbody></table>

</details>

Правила и автоматизация

<details>

<summary><strong><code>rules</code></strong></summary>

**Описание**: Правила обнаружения событий с настраиваемыми условиями срабатывания (превышение скорости, нарушения геозоны, пороги датчиков, время простоя), хранящиеся в parameters (JSONB), и мультиканальными настройками уведомлений (alert\_email, alert\_sms, alert\_phone, is\_push\_enabled) для автоматического мониторинга и оповещений на основе данных устройства и сервера

<table><thead><tr><th width="131">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>rule_id</code> - Идентификатор сущности rule<br>- <code>object_id</code> - Идентификатор сущности объекта<br>- <code>client_id</code> - Идентификатор сущности клиента<br>- <code>event_type</code> - Атрибут event_type таблицы rules<br>- <code>event_label</code> - Атрибут event_label таблицы rules<br>- <code>event_group</code> - Атрибут event_group таблицы rules<br>- <code>description</code> - Атрибут description таблицы rules<br>- <code>parameters</code> - Параметры события. Для более подробной информации о доступных параметрах смотрите <a href="https://www.navixy.com/docs/navixy-api/user-api/backend-api/resources/tracking/tracker/rules/rule_types/">Navixy API docs</a>.<br>- <code>alert_email</code> - Почта для уведомлений<br>- <code>alert_sms</code> - Телефоны для SMS-уведомлений<br>- <code>alert_phone</code> - Телефоны для голосовых звонков<br>- <code>is_push_enabled</code> - Если true, доступны push-уведомления<br>- <code>created_at</code> - Атрибут created_at таблицы rules<br>- <code>is_deleted</code> - Атрибут is_deleted таблицы rules<br>- <code>maximum</code> - Ограничения, применяемые к различным правилам. Например, для правила времени простоя с работающим двигателем в минутах<br>- <code>event_comment1</code> - Атрибут event_comment1 таблицы rules<br>- <code>event_comment2</code> - Атрибут event_comment2 таблицы rules</td></tr><tr><td><strong>Содержимое</strong></td><td>Параметры правила (JSONB) определяют условия срабатывания; поддерживаются уведомления по email, SMS, телефону и push</td></tr><tr><td><strong>Связи</strong></td><td>Связи с объектами через <code>rules2objects</code>, зоны через <code>rules2zones</code></td></tr><tr><td><strong>Особые замечания</strong></td><td><code>event_type</code> определяет конкретный сценарий мониторинга (превышение скорости, нарушение геозоны, порог датчика); <code>maximum</code> поле позволяет агрегировать события для оповещений на основе порогов</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>rules2objects</code></strong></summary>

**Описание**: Отношение «многие ко многим», связывающее правила с мониторируемыми объектами с возможностью настройки параметров для каждого объекта через object\_params (JSONB), позволяя задать различные пороговые значения (например, скоростные лимиты) для каждого транспортного средства или актива в рамках одного правила

<table><thead><tr><th width="140">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>rule_id</code> - Идентификатор сущности rule<br>- <code>object_id</code> - Идентификатор сущности объекта<br>- <code>param_group_number</code> - Атрибут param_group_number таблицы rules2objects<br>- <code>object_params</code> - Атрибут object_params таблицы rules2objects</td></tr><tr><td><strong>Содержимое</strong></td><td><code>object_params</code> (JSONB) позволяет настраивать правило для каждого объекта (например, разные скоростные лимиты для разных транспортных средств)</td></tr><tr><td><strong>Особые замечания</strong></td><td>Отношение «многие ко многим» позволяет одному правилу мониторить несколько объектов с разными параметрами</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>rules2zones</code></strong></summary>

**Описание**: Отношение «многие ко многим», связывающее правила с геозонами, что позволяет одному правилу отслеживать события входа/выхода в нескольких географических областях для сложных сценариев пространственного мониторинга

<table><thead><tr><th width="144">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>rule_id</code> - Идентификатор сущности rule<br>- <code>zone_id</code> - Идентификатор сущности зоны</td></tr><tr><td><strong>Особые замечания</strong></td><td>Отношение «многие ко многим» позволяет мониторить несколько зон для одного правила (например, оповестить при входе в любую из нескольких запрещенных зон)</td></tr></tbody></table>

</details>

Статус и категоризация

<details>

<summary><strong><code>statuses</code></strong></summary>

**Описание**: Пользовательские определения статусов в списках статусов, включая свойства отображения (color для отображения на сайте, order\_sort для позиционирования), используемые для представления состояний устройства или сотрудника с поддержкой мягкого удаления через флаг is\_deleted

<table><thead><tr><th width="128">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>status_id</code> - Идентификатор сущности status<br>- <code>listing_id</code> - Идентификатор сущности listing<br>- <code>status_label</code> - Значение атрибута status_label<br>- <code>color</code> - Цвет, используемый для отображения на сайте<br>- <code>order_sort</code> - Позиция сортировки в списке статусов<br>- <code>is_deleted</code> - Атрибут is_deleted таблицы statuses</td></tr><tr><td><strong>Связи</strong></td><td>Группы статусов, организованные через <code>listing_id</code> (ссылается на <code>status_listings</code>); используется в <code>status_history</code></td></tr><tr><td><strong>Особые замечания</strong></td><td><code>order_sort</code> определяет последовательность отображения; цвет позволяет визуально дифференцировать в отчетах</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>status_listings</code></strong></summary>

**Описание**: Наборы статусов, контролирующие, какие значения статусов доступны для устройств или сотрудников, с флагами разрешений (is\_supervisor\_controlled, is\_employee\_controlled), определяющими, могут ли сменить статус супервайзеры, сотрудники или оба

<table><thead><tr><th width="144">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>status_listing_id</code> - Идентификатор сущности списка статусов<br>- <code>user_id</code> - Идентификатор сущности пользователя<br>- <code>status_listing_label</code> - Значение атрибута status_listing_label<br>- <code>is_supervisor_controlled</code> - Если true, супервайзеры могут менять рабочий статус, например, используя мобильное приложение мониторинга<br>- <code>is_employee_controlled</code> - Если true, сотрудники могут менять свой рабочий статус, например, используя мобильное приложение отслеживания<br>- <code>is_deleted</code> - Атрибут is_deleted таблицы status_listings</td></tr><tr><td><strong>Связи</strong></td><td>Ссылается <code>devices.status_listing_id</code> и <code>statuses.listing_id</code></td></tr><tr><td><strong>Особые замечания</strong></td><td>Флаги управления определяют, кто может менять статусы: только супервайзер, самообслуживание сотрудника или оба</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>status_history</code></strong></summary>

**Описание**: Аудиторский след всех переходов статусов устройств с отметками времени (changed\_datetime на устройстве, server\_datetime на сервере), указанием пользователя (updated\_by) и захватом местоположения (latitude, longitude, address), что позволяет проводить географический анализ изменений статусов и отчетность о местах начала/окончания рабочего дня

<table><thead><tr><th width="143">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>status_history_id</code> - Идентификатор сущности истории статусов<br>- <code>device_id</code> - Идентификатор сущности устройства<br>- <code>old_status_id</code> - Идентификатор старого статуса<br>- <code>new_status_id</code> - Идентификатор нового статуса<br>- <code>updated_by</code> - Дата и время, связанные с атрибутом updated_by<br>- <code>changed_datetime</code> - Дата и время присвоения нового статуса на устройстве<br>- <code>server_datetime</code> - Дата и время присвоения нового статуса на сервере<br>- <code>latitude</code> - Определение местоположения устройств при смене статусов<br>- <code>longitude</code> - Определение местоположения устройств при смене статусов<br>- <code>address</code> - Определение местоположения устройств при смене статусов</td></tr><tr><td><strong>Связи</strong></td><td>Связи с <code>devices</code>, <code>statuses</code> (старый и новый), <code>description_parameters</code> (для <code>updated_by</code> role)</td></tr><tr><td><strong>Особые замечания</strong></td><td>Фиксация местоположения позволяет проводить географический анализ переходов статусов; полезно для отчетности о местах начала/окончания рабочего дня</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>tags</code></strong></summary>

**Описание**: Метки категоризации, задаваемые пользователем, с цветовой кодировкой, которые позволяют быстро фильтровать и искать по нескольким типам сущностей (places, geofences, employees, tasks, trackers, vehicles) для гибкой организации

<table><thead><tr><th width="149">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>tag_id</code> - Идентификатор сущности тега<br>- <code>user_id</code> - Идентификатор сущности пользователя<br>- <code>tag_label</code> - Атрибут tag_label таблицы tags<br>- <code>color</code> - Атрибут color таблицы tags</td></tr><tr><td><strong>Связи</strong></td><td>Применяется к сущностям через <code>tag_links</code>; область действия определяется пользователем</td></tr><tr><td><strong>Особые замечания</strong></td><td>Гибкая система категоризации, поддерживающая несколько тегов на одну сущность</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>tag_links</code></strong></summary>

**Описание**: Полиморфная таблица отношений, связывающая теги с любым типом сущности через entity\_type и entity\_id, с полем ordinal для управления порядком отображения, обеспечивая гибкую многосущностную маркировку

<table><thead><tr><th width="127">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>tag_id</code> - Идентификатор сущности тега<br>- <code>entity_type</code> - Атрибут entity_type таблицы tag_links<br>- <code>entity_id</code> - Идентификатор сущности<br>- <code>ordinal</code> - Атрибут ordinal таблицы tag_links</td></tr><tr><td><strong>Содержимое</strong></td><td><code>entity_type</code> идентифицирует таблицу (vehicle, employee, task и т.д.); <code>ordinal</code> определяет порядок отображения</td></tr><tr><td><strong>Особые замечания</strong></td><td>Полиморфная связь позволяет маркировать разные типы сущностей</td></tr></tbody></table>

</details>

Группы и иерархии

<details>

<summary><strong><code>groups</code></strong></summary>

**Описание**: Структура организационного группирования для трекеров, позволяющая визуальную организацию в пользовательском интерфейсе с настраиваемыми цветами (group\_color) и иерархическим управлением, подобным папкам, в настоящее время выполняет чисто визуальную функцию

<table><thead><tr><th width="148">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>group_id</code> - Группа трекеров (связана через objects.group_id). Разделение на группы видно, например, в списке маячков<br>- <code>client_id</code> - Идентификатор сущности клиента<br>- <code>group_label</code> - Название группы, задаваемое пользователем, от 1 до 60 печатных символов, например "Employees"<br>- <code>group_color</code> - Цвет группы в веб-формате (без #), например "FF6DDC". Определяет цвет маркеров трекеров на карте</td></tr><tr><td><strong>Связи</strong></td><td>Ссылается <code>objects.group_id</code>; право собственности клиента через <code>client_id</code> (ссылается на <code>users</code>)</td></tr><tr><td><strong>Особые замечания</strong></td><td>Позволяет организовывать сущности мониторинга в виде папок для отчетности и управления правами</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>groups_objects</code></strong></summary>

**Описание**: Отношение «многие ко многим» между группами и объектами с использованием составного первичного ключа (groups\_client\_id, objects\_client\_id), позволяющее объектам одновременно принадлежать нескольким группам для гибкой организации

<table><thead><tr><th width="135">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>groups_client_id</code> - Идентификатор клиента для групп<br>- <code>objects_client_id</code> - Идентификатор клиента для объектов</td></tr><tr><td><strong>Особые замечания</strong></td><td>Позволяет объектам одновременно принадлежать нескольким группам; запрос выполняется по обоим <code>client_id</code> значениям членства в группе</td></tr></tbody></table>

</details>

Пользовательские поля и сущности

<details>

<summary><strong><code>entities</code></strong></summary>

**Описание**: Реестр типов сущностей, определяющий, какие бизнес-сущности поддерживают пользовательские поля и структуру их расположения (sections, field\_order), хранящуюся в entity\_label (JSONB), позволяя динамическое расширение схемы для places, tasks и других сущностей без изменений в базе данных

<table><thead><tr><th width="141">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>entity_id</code> - Идентификатор сущности<br>- <code>user_id</code> - Идентификатор сущности пользователя<br>- <code>entity_label</code> - id - int. Идентификатор сущности. type - enum. В настоящее время поддерживается только "place". layout - объект, описывающий расположение полей для сущности. sections - массив объектов. Каждый раздел может содержать одно или несколько полей. В макете должен присутствовать как минимум один раздел. label - строка. Название раздела. field_order - массив строк. Встроенные поля и идентификаторы пользовательских полей (как строки)<br>- <code>builtin_type</code> - Атрибут builtin_type таблицы entities</td></tr><tr><td><strong>Связи</strong></td><td>Ссылается <code>custom_fields</code> для определения, какие пользовательские поля применимы к каким типам сущностей</td></tr><tr><td><strong>Особые замечания</strong></td><td><code>builtin_type</code> связан с <code>description_parameters</code> для системно определенных классификаций сущностей</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>custom_fields</code></strong></summary>

**Описание**: Определения пользовательских полей, позволяющие динамически расширять схему для типов сущностей, с настраиваемыми типами полей (custom\_field\_type), правилами валидации и опциями в parameters (JSONB), а также флагами обязательности (is\_required) для гибкого сбора данных по places, tasks и другим сущностям

<table><thead><tr><th width="146">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>custom_field_id</code> - Идентификатор сущности пользовательского поля<br>- <code>entity_id</code> - Идентификатор сущности<br>- <code>custom_field_label</code> - Название поля<br>- <code>custom_field_type</code> - Тип данных в поле<br>- <code>description</code> - Описание поля<br>- <code>is_required</code> - Обязательно ли это поле?<br>- <code>parameters</code> - Параметры поля</td></tr><tr><td><strong>Содержимое</strong></td><td><code>parameters</code> (JSONB) хранит конфигурацию, специфичную для типа поля (правила валидации, варианты выпадающего списка и т.д.)</td></tr><tr><td><strong>Связи</strong></td><td>Определяет доступные пользовательские атрибуты для сущностей; тип поля связан с <code>description_parameters</code></td></tr><tr><td><strong>Особые замечания</strong></td><td>Позволяет динамически расширять схему без изменений в базе данных; широко используется в <code>places</code> и <code>tasks</code></td></tr></tbody></table>

</details>

Историческое отслеживание

<details>

<summary><strong><code>driver_history</code></strong></summary>

**Описание**: Полный аудиторский след назначений сотрудников на транспортные средства с течением времени, отслеживающий переходы от old\_employee\_id к new\_employee\_id с отметками времени (changed\_datetime, server\_datetime), данными о местоположении (latitude, longitude, address), информацией о аппаратных ключах и указанием пользователя (updated\_by), что позволяет проводить аналитику, специфичную для водителей, когда они меняют транспортные средства

<table><thead><tr><th width="146">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>driver_history_id</code> - Идентификатор сущности истории водителей<br>- <code>object_id</code> - Идентификатор сущности объекта<br>- <code>old_employee_id</code> - Идентификатор предыдущего сотрудника<br>- <code>new_employee_id</code> - Идентификатор нового сотрудника<br>- <code>hardware_key</code> - Атрибут hardware_key таблицы driver_history<br>- <code>changed_datetime</code> - Дата и время, когда были внесены изменения в устройство<br>- <code>server_datetime</code> - Дата и время изменений на сервере<br>- <code>updated_by</code> - Дата и время, связанные с атрибутом updated_by<br>- <code>latitude</code> - Атрибут latitude таблицы driver_history<br>- <code>longitude</code> - Атрибут longitude таблицы driver_history<br>- <code>address</code> - Атрибут address таблицы driver_history</td></tr><tr><td><strong>Связи</strong></td><td>Отслеживает назначения водителей на транспортные средства с течением времени; связано с <code>employees</code> и <code>objects</code></td></tr><tr><td><strong>Особые замечания</strong></td><td>Необходимо для отчетности по водителям при смене транспортных средств; фиксация местоположения позволяет анализировать место изменения назначения</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>vehicle_trackers_history</code></strong></summary>

**Описание**: Аудиторский след, отслеживающий, какие GPS-устройства (object\_id) были установлены в какие транспортные средства (vehicle\_id) с течением времени с отметками изменений (changed\_datetime), обеспечивая точное историческое приписывание данных и расчет пробега при переносе трекеров между транспортными средствами

<table><thead><tr><th width="144">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>vehicle_tracker_history_id</code> - Идентификатор сущности истории трекеров в автомобилях<br>- <code>vehicle_id</code> - Идентификатор сущности транспортного средства<br>- <code>object_id</code> - Идентификатор сущности объекта<br>- <code>changed_datetime</code> - Дата и время, связанные с атрибутом changed_datetime</td></tr><tr><td><strong>Связи</strong></td><td>Отслеживает, какое GPS-устройство было установлено в какое транспортное средство с течением времени</td></tr><tr><td><strong>Особые замечания</strong></td><td>Критично для исторического анализа данных при переносе трекеров между транспортными средствами; позволяет точно приписывать пробег и использование</td></tr></tbody></table>

</details>

Справочные и справочно-поисковые данные

<details>

<summary><strong><code>description_parameters</code></strong></summary>

**Описание**: Справочные данные системы, предоставляющие человекочитаемые метки (description) для перечисляемых целочисленных значений (key), используемых по всей базе данных, организованные по полю type (например, task\_status, fuel\_type, counter\_type, entity\_classification) для согласованного перевода значений в отчетах и интерфейсе

<table><thead><tr><th width="146">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>key</code> - Возможное значение атрибута<br>- <code>type</code> - Составной атрибут, состоящий из имени таблицы, за которым следует нижнее подчеркивание и имя атрибута в таблице<br>- <code>description</code> - Подразумеваемое значение атрибута</td></tr><tr><td><strong>Содержимое</strong></td><td>Предоставляет человекочитаемые метки для кодированных значений по всей базе данных (статус задачи, типы топлива, типы счетчиков и т.д.)</td></tr><tr><td><strong>Связи</strong></td><td>Ссылается через внешние ключи из нескольких таблиц для стандартизированной категоризации</td></tr><tr><td><strong>Особые замечания</strong></td><td>Необходимо для преобразования целочисленных кодов в читаемые значения в отчетах; <code>type</code> группы полей связанные перечисления</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>counters</code></strong></summary>

**Описание**: Конфигурации одометра и счетчика моточасов, связывающие показания датчиков устройства (sensor\_id) с измерениями расстояния или времени с коэффициентами умножения для преобразования единиц (км, мили, часы) и counter\_type из description\_parameters, определяющего тип измерения

<table><thead><tr><th width="140">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>counter_id</code> - Внутренний ID<br>- <code>device_id</code> - Идентификатор сущности устройства<br>- <code>counter_type</code> - Тип счетчика<br>- <code>sensor_id</code> - Идентификатор сущности датчика<br>- <code>multiplier</code> - Коэффициент для преобразования значений в одну из метрик (км, л и т.д.)</td></tr><tr><td><strong>Связи</strong></td><td>Связывает устройства с показаниями датчиков, представляющими счётчики расстояния или времени</td></tr><tr><td><strong>Особые замечания</strong></td><td><code>multiplier</code> преобразует импульсы датчика в реальные единицы (км, мили, часы); <code>counter_type</code> from <code>description_parameters</code> определяет тип измерения</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>device_output_name</code></strong></summary>

**Описание**: Пользовательские метки для каналов вывода устройства, сопоставляющие числовые идентификаторы выходов (number) с именами, заданными пользователем (label), такими как "Door Lock" или "Engine Block" для читаемых отчетов и анализа команд и состояний выходов устройства

<table><thead><tr><th width="140">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td>- <code>device_id</code> - Идентификатор сущности устройства<br>- <code>number</code> - Атрибут number таблицы device_output_name<br>- <code>label</code> - Атрибут label таблицы device_output_name</td></tr><tr><td><strong>Содержимое</strong></td><td>Сопоставляет номера каналов вывода с именами, заданными пользователем (например, "Door Lock", "Engine Block")</td></tr><tr><td><strong>Особые замечания</strong></td><td>Обеспечивает читаемые отчеты при анализе команд и состояний выходов устройства</td></tr></tbody></table>

</details>

## `raw_telematics_data` structure

Схема **`raw_telematics_data`** содержит три основных типа таблиц, которые совместно обеспечивают всесторонние данные устройства.

<figure><img src="https://1176408533-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoFNFEIINiGFbhi3Px3dE%2Fuploads%2FiTtEgzFgyJKTIl0ZCq7E%2Fv1%20schema%20telematics%20bd.svg?alt=media&#x26;token=b298bab4-ca28-41f8-919b-0948bb436614" alt="Bronze layer raw telematics data ERD"><figcaption><p>ERD слоя Bronze для необработанных телематических данных</p></figcaption></figure>

{% hint style="info" %}
Интерактивная диаграмма схемы raw\_telematics\_data доступна на **dbdiagram.io**: <https://dbdiagram.io/d/v1-schema-telematics-bd-67a0acef263d6cf9a0d8e750>
{% endhint %}

Ниже приведены сведения о схеме raw telematics data.

{% code title="Схема raw\_telematics\_data" expandable="true" %}

```sql
Таблица tracking_data_core {

  device_id integer [primary key]

  device_time timestampz [primary key]

  platform_time timestampz

  record_added_at timestampz [default: `now()`]

  latitude integer

  longitude integer

  speed integer

  altitude integer

  satellites integer

  event_id integer

  gps_fix_type integer

  hdop integer

  

  indexes {(device_id, device_time)}

}

  

Таблица inputs {

  event_id integer [primary key]

  device_id integer [primary key]

  record_added_at timestampz [default: `now()`]

  device_time timestampz [primary key]

  sensor_name text [primary key]

  value text

  indexes {(device_id, device_time)}

}

  

Таблица states {

  event_id integer [primary key]

  device_id serial [primary key]

  record_added_at timestampz [default: `now()`]

  device_time timestampz [primary key]

  state_name text [primary key]

  value text

  indexes {(device_id, device_time)}

}

  

Ref: inputs.(device_id, device_time) > tracking_data_core.(device_id, device_time)

Ref: states.(device_id, device_time) > tracking_data_core.(device_id, device_time)
```

{% endcode %}

### Ключевые таблицы по категориям

Каждая таблица служит определенной цели при фиксации разных аспектов информации об устройстве:

<details>

<summary><code>tracking_data_core</code></summary>

**Назначение**: Основные данные о местоположении и движении

<table><thead><tr><th width="181.20001220703125">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td><code>device_id</code>, <code>device_time</code>, <code>platform_time</code>, <code>latitude</code>, <code>longitude</code>, <code>speed</code>, <code>altitude</code>, <code>satellites</code>, <code>hdop</code>, <code>event_id</code></td></tr><tr><td><strong>Индексация</strong></td><td>Оптимизировано с индексом на (<code>device_id</code>, <code>device_time</code>)</td></tr><tr><td><strong>Особые замечания</strong></td><td>Данные о местоположении (широта и долгота) используют целочисленный формат с точностью 10⁷ для оптимальной производительности TimescaleDB<br><br>Скорость также хранится в целочисленном формате, поэтому её нужно делить на 100</td></tr></tbody></table>

</details>

<details>

<summary><code>inputs</code></summary>

**Назначение**: Показания датчиков от устройств

<table><thead><tr><th width="182">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td><code>input_id</code>, <code>device_id</code>, <code>device_time</code>, <code>sensor_name</code>, <code>value</code></td></tr><tr><td><strong>Содержимое</strong></td><td>Аналоговые показания (уровень топлива, температура, напряжение), вычисляемые значения (обороты двигателя)</td></tr><tr><td><strong>Связи</strong></td><td><pre data-overflow="wrap"><code>FROM raw_telematics_data.inputs AS i
JOIN raw_business_data.sensor_description AS sd
    ON i.device_id = sd.device_id AND i.sensor_name = sd.input_label
JOIN raw_telematics_data.tacking_data_core AS tdc
    ON i.device_id = tdc.device_id AND i.device_time = tdc.device_time
</code></pre></td></tr></tbody></table>

</details>

<details>

<summary><code>states</code></summary>

**Назначение**: Индикаторы состояния устройства и режимы работы

<table><thead><tr><th width="174.800048828125">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td><code>state_id</code>, <code>device_id</code>, <code>device_time</code>, <code>state_name</code>, <code>value</code></td></tr><tr><td><strong>Содержимое</strong></td><td>Индикаторы режимов работы (работа, простои, выключено), состояния компонентов (зажигание, двери)</td></tr><tr><td><strong>Формат значения</strong></td><td>Булевы значения (1/0) или специальные коды состояния</td></tr></tbody></table>

</details>

Данные в этой схеме поступают непосредственно от устройств с минимальной задержкой (как правило — секунды). Схема оптимизирована для временных рядов с использованием TimescaleDB для эффективного хранения и выборки.

## Дополнительная информация

### Валидация данных

База данных обеспечивает целостность данных посредством нескольких механизмов:

* **CHECK ограничения** проверяют, что значения находятся в допустимых пределах
* **Внешние ключи** обеспечивают согласованность связей между таблицами
* **NOT NULL ограничения** гарантируют, что обязательные поля всегда имеют значения
* **Значения по умолчанию** обеспечивают запасной вариант, когда данные не предоставлены явно

### Оптимизация запросов

Таблицы организованы со специфическими стратегиями индексирования:

* Во всех таблицах присутствуют **индексы по времени** по `record_added_at`
* Колонки внешних ключей имеют выделенные индексы для ускорения объединений
* Часто используемые комбинации колонок имеют **составные индексы**
* TimescaleDB предоставляет специализированные индексы для запросов по временным рядам

## `repo` структура данных

{% hint style="warning" %}
**Эта схема в настоящее время находится в разработке.** Если вы заинтересованы в раннем доступе или у вас есть вопросы по этой функциональности, пожалуйста, свяжитесь с <iotquery@navixy.com>.
{% endhint %}

Схема `repo` схема предоставляет всестороннюю основу для управления организационными структурами, активами, устройствами и их отношениями в многопользовательских средах. Построенная на PostgreSQL 14+ с расширением ltree, схема поддерживает иерархические организации, определения пользовательских полей для любых типов сущностей, ролевой доступ с ограничениями на уровне объектов и полные журналы аудита с отслеживанием изменений на уровне полей. Все сущности могут быть расширены без модификации схемы, локализованы для международных развертываний и связаны через гибкие полиморфные отношения.

Схема решает сложные сценарии управления данными, включая иерархии активов автопарка на разных уровнях организации, многопользовательские SaaS-платформы, требующие изоляции данных, операции, требующие соответствия с подробными требованиями аудита, и системы, нуждающиеся в динамических моделях данных, адаптируемых через пользовательские поля вместо миграций базы данных.

<figure><img src="https://1176408533-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FoFNFEIINiGFbhi3Px3dE%2Fuploads%2FOiyhgXkaS0x3wzKquynf%2FNavixy%20Repo%20data%20schema.svg?alt=media&#x26;token=b3148ca9-9b38-4d7a-b246-01d9bc718ae2" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Интерактивная диаграмма`repo` схемы данных доступна на **dbdiagram.io**: <https://dbdiagram.io/d/Navixy-Repo-data-schema-68ad788c1e7a611967a0930e>
{% endhint %}

Найдите `repo` подробности схемы ниже.

{% code title="repo data schema" expandable="true" %}

```sql
// ============================================
// Новая схема DataHub - Путь клиента
// PostgreSQL 14+ с расширением ltree
// Версия: 2.0 (Концепция)
// ============================================

// ============================================
// БАЗОВЫЕ ТАБЛИЦЫ ССЫЛОЧНЫХ ДАННЫХ (иерархия ci_base)
// ============================================

Table ci_base {
  id uuid [primary key]
  code text [not null]
  title_en text [not null]
  order int
  is_system boolean [not null, default: false]
  discriminator text [not null]
  catalog_id uuid
  organization_id uuid
  parent_id uuid
  path ltree
  is_hierarchical boolean [default: false]
  extra jsonb
  created_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  updated_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  deleted_at timestamptz
  
  indexes {
    (parent_id) [name: 'idx_ci_parent']
    (path) [type: gist, name: 'idx_ci_path_gist']
    (catalog_id) [name: 'idx_ci_catalog']
    (organization_id) [name: 'idx_ci_org']
    (discriminator) [name: 'idx_ci_discriminator']
    (code) [unique, name: 'uq_ci_code_per_type']
    (organization_id, code) [unique, name: 'uq_ci_org_code']
  }
}

Table ci_module {
  id uuid [primary key]
}

Table ci_catalog_category {
  id uuid [primary key]
}

Table ci_country {
  id uuid [primary key]
}

Table ci_role {
  id uuid [primary key]
}

Table ci_entity_type {
  id uuid [primary key]
}

Table ci_device_status {
  id uuid [primary key]
}

Table ci_permission_scope {
  id uuid [primary key]
  module_id uuid
  entity_type_id uuid
  category text
}

Table ci_device_type {
  id uuid [primary key]
}

Table ci_asset_type {
  id uuid [primary key]
  category_id uuid
}

Table ci_asset_type_category {
  id uuid [primary key]
}

Table ci_inventory_type {
  id uuid [primary key]
}

Table ci_organization_type {
  id uuid [primary key]
}

Table ci_user_type {
  id uuid [primary key]
}

Table ci_asset_group_type {
  id uuid [primary key]
  max_items int
  color text
  icon text
  allowed_asset_type_id uuid
}

Table ci_device_relation_type {
  id uuid [primary key]
}

Table ci_tag {
  id uuid [primary key]
  entity_type_id uuid
  color text
}

// ============================================
// БАЗОВАЯ СУЩНОСТЬ С ПОДДЕРЖКОЙ ПОЛЕЙ ПО УМОЛЧАНИЮ
// ============================================

Table customizable_entity {
  id uuid [primary key]
  entity_type_id uuid [not null]
  cf_data jsonb
  created_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  
  indexes {
    (entity_type_id) [name: 'idx_customizable_entity_type']
  }
}

// ============================================
// ОСНОВНЫЕ ДЕЛОВЫЕ СУЩНОСТИ
// ============================================

Table organization {
  id uuid [primary key]
  parent_id uuid
  path ltree
  organization_type_id uuid [not null]
  title_en text [not null]
  is_active boolean [not null, default: true]
  created_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  updated_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  deleted_at timestamptz
  deleted_by uuid
  
  indexes {
    (parent_id) [name: 'idx_org_parent']
    (path) [type: gist, name: 'idx_org_path_gist']
    (organization_type_id) [name: 'idx_org_type']
  }
}

Table catalog {
  id uuid [primary key]
  organization_id uuid [not null]
  module_id uuid
  category_id uuid
  title_en text [not null]
  is_system boolean [not null, default: false]
  created_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  updated_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  
  indexes {
    (organization_id) [name: 'idx_catalog_org']
    (module_id) [name: 'idx_catalog_module']
  }
}

Table user {
  id uuid [primary key]
  organization_id uuid [not null]
  user_type_id uuid [not null]
  identity_provider text [not null]
  identity_provider_id uuid [not null]
  full_name text [not null]
  is_active boolean [not null, default: true]
  created_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  updated_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  deleted_at timestamptz
  deleted_by uuid
  
  indexes {
    (organization_id) [name: 'idx_user_org']
    (user_type_id) [name: 'idx_user_type']
    (organization_id, identity_provider, identity_provider_id) [unique, name: 'uq_user_org_idp']
  }
}

// ============================================
// УПРАВЛЕНИЕ ДОСТУПОМ (ACL)
// ============================================

Table user_role {
  id uuid [primary key]
  user_id uuid [not null]
  role_id uuid [not null]
  assigned_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  assigned_by uuid
  
  indexes {
    (user_id) [name: 'idx_user_role_user']
    (role_id) [name: 'idx_user_role_role']
    (user_id, role_id) [unique, name: 'uq_user_role']
  }
}

Table acl_role_permission {
  id uuid [primary key]
  role_id uuid [not null]
  permission_scope_id uuid [not null]
  target_entity_id uuid
  actions int [not null]
  granted_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  granted_by uuid
  
  indexes {
    (role_id) [name: 'idx_acl_role_perm_role']
    (permission_scope_id) [name: 'idx_acl_role_perm_scope']
    (role_id, permission_scope_id, target_entity_id) [unique, name: 'uq_acl_role_permission']
  }
}

Table acl_user_scope {
  id uuid [primary key]
  user_id uuid [not null]
  permission_scope_id uuid [not null]
  target_entity_id uuid [not null]
  actions int [not null]
  
  indexes {
    (user_id, permission_scope_id) [name: 'idx_acl_user_scope_user']
    (user_id, permission_scope_id, target_entity_id) [unique, name: 'uq_acl_user_scope']
  }
}

// ============================================
// ДЕЛОВЫЕ СУЩНОСТИ
// ============================================

Table asset {
  id uuid [primary key]
  organization_id uuid [not null]
  asset_type_id uuid [not null]
  label text [not null]
  description text
  created_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  updated_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  deleted_at timestamptz
  deleted_by uuid
  
  indexes {
    (organization_id) [name: 'idx_asset_org']
    (asset_type_id) [name: 'idx_asset_type']
  }
}

Table inventory {
  id uuid [primary key]
  organization_id uuid [not null]
  inventory_type_id uuid [not null]
  code text [not null]
  created_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  updated_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  deleted_at timestamptz
  deleted_by uuid
  
  indexes {
    (organization_id) [name: 'idx_inventory_org']
    (inventory_type_id) [name: 'idx_inventory_type']
    (organization_id, code) [unique, name: 'uq_inventory_org_code']
  }
}

Table device {
  id uuid [primary key]
  organization_id uuid [not null]
  device_type_id uuid [not null]
  status_id uuid [not null]
  hw_id text
  label text [not null]
  created_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  updated_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  deleted_at timestamptz
  deleted_by uuid
  
  indexes {
    (organization_id) [name: 'idx_device_org']
    (device_type_id) [name: 'idx_device_type']
    (status_id) [name: 'idx_device_status']
    (hw_id) [name: 'idx_device_hw_id']
  }
}

Table device_asset_link {
  id uuid [primary key]
  device_id uuid [unique, not null]
  asset_id uuid [not null]
  linked_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  linked_by uuid
  
  indexes {
    (device_id) [unique, name: 'idx_device_asset_link_device']
    (asset_id) [name: 'idx_device_asset_link_asset']
  }
}

Table device_inventory_link {
  id uuid [primary key]
  device_id uuid [unique, not null]
  inventory_id uuid [not null]
  linked_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  linked_by uuid
  
  indexes {
    (device_id) [unique, name: 'idx_device_inventory_link_device']
    (inventory_id) [name: 'idx_device_inventory_link_inventory']
  }
}

Table device_relation {
  id uuid [primary key]
  master_id uuid [not null]
  slave_id uuid [not null]
  relation_type_id uuid [not null]
  
  indexes {
    (master_id) [name: 'idx_device_relation_master']
    (slave_id) [name: 'idx_device_relation_slave']
    (master_id, slave_id, relation_type_id) [unique, name: 'uq_device_relation']
  }
}

Table asset_group {
  id uuid [primary key]
  organization_id uuid [not null]
  group_type_id uuid [not null]
  title_en text [not null]
  description text
  created_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  updated_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  deleted_at timestamptz
  deleted_by uuid
  
  indexes {
    (organization_id) [name: 'idx_asset_group_org']
    (group_type_id) [name: 'idx_asset_group_type']
  }
}

Table asset_group_item {
  id uuid [primary key]
  group_id uuid [not null]
  asset_id uuid [not null]
  attached_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  detached_at timestamptz
  
  indexes {
    (group_id) [name: 'idx_asset_group_item_group']
    (asset_id) [name: 'idx_asset_group_item_asset']
    (group_id, asset_id, detached_at) [unique, name: 'uq_asset_group_item']
  }
}

Table entity_tag {
  id uuid [primary key]
  tag_id uuid [not null]
  entity_id uuid [not null]
  tagged_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  
  indexes {
    (tag_id) [name: 'idx_entity_tag_tag']
    (entity_id) [name: 'idx_entity_tag_entity']
    (tag_id, entity_id) [unique, name: 'uq_entity_tag']
  }
}

// ============================================
// ЛОКАЛИЗАЦИЯ
// ============================================

Table i18n_text {
  entity_id uuid [pk]
  field_code text [pk]
  locale text [pk]
  text_value text [not null]
  
  indexes {
    (entity_id) [name: 'idx_i18n_entity']
    (locale) [name: 'idx_i18n_locale']
  }
}

// ============================================
// ОПРЕДЕЛЕНИЯ ПОЛЕЙ (CUSTOM FIELDS)
// ============================================

Table custom_field_def {
  id uuid [primary key]
  organization_id uuid [not null]
  owner_entity_type_id uuid [not null]
  code text [not null]
  title_en text [not null]
  field_type text [not null]
  is_multi boolean [not null, default: false]
  is_required boolean [not null, default: false]
  order int
  ref_entity_type_id uuid
  ref_catalog_id uuid
  created_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  updated_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  
  indexes {
    (organization_id) [name: 'idx_cfd_org']
    (owner_entity_type_id) [name: 'idx_cfd_owner_type']
    (organization_id, owner_entity_type_id, code) [unique, name: 'uq_cfd_org_type_code']
  }
}

// ============================================
// ЗНАЧЕНИЯ ПОЛЕЙ (ПО ТИПУ)
// ============================================

Table custom_field_value_text {
  customizable_entity_id uuid [pk]
  field_def_id uuid [pk]
  value_index smallint [pk]
  value text [not null]
  
  indexes {
    (field_def_id, value) [name: 'idx_cfv_text_value']
  }
}

Table custom_field_value_number {
  customizable_entity_id uuid [pk]
  field_def_id uuid [pk]
  value_index smallint [pk]
  value numeric [not null]
  
  indexes {
    (field_def_id, value) [name: 'idx_cfv_number_value']
  }
}

Table custom_field_value_boolean {
  customizable_entity_id uuid [pk]
  field_def_id uuid [pk]
  value_index smallint [pk]
  value boolean [not null]
  
  indexes {
    (field_def_id, value) [name: 'idx_cfv_boolean_value']
  }
}

Table custom_field_value_date {
  customizable_entity_id uuid [pk]
  field_def_id uuid [pk]
  value_index smallint [pk]
  value date [not null]
  
  indexes {
    (field_def_id, value) [name: 'idx_cfv_date_value']
  }
}

Table custom_field_value_datetime {
  customizable_entity_id uuid [pk]
  field_def_id uuid [pk]
  value_index smallint [pk]
  value timestamptz [not null]
  
  indexes {
    (field_def_id, value) [name: 'idx_cfv_datetime_value']
  }
}

Table custom_field_value_entity {
  customizable_entity_id uuid [pk]
  field_def_id uuid [pk]
  value_index smallint [pk]
  ref_entity_id uuid [not null]
  
  indexes {
    (field_def_id, ref_entity_id) [name: 'idx_cfv_entity_value']
  }
}

Table custom_field_value_catalog {
  customizable_entity_id uuid [pk]
  field_def_id uuid [pk]
  value_index smallint [pk]
  ref_item_id uuid [not null]
  
  indexes {
    (field_def_id, ref_item_id) [name: 'idx_cfv_catalog_value']
  }
}

// ============================================
// АУДИТ
// ============================================

Table audit_event {
  id uuid [primary key]
  event_category text [not null]
  user_id uuid
  identity_provider_id uuid
  ip_address inet
  user_agent text
  aggregate_type text
  aggregate_id uuid
  event_type text [not null]
  event_data jsonb
  occurred_at timestamptz [not null, default: `CURRENT_TIMESTAMP`]
  
  indexes {
    (user_id, occurred_at) [name: 'idx_audit_event_user']
    (aggregate_type, aggregate_id, occurred_at) [name: 'idx_audit_event_aggregate']
    (event_category, occurred_at) [name: 'idx_audit_event_category']
    (event_type, occurred_at) [name: 'idx_audit_event_type']
  }
}

// ============================================
// ОТНОШЕНИЯ
// ============================================

Ref: ci_base.catalog_id > catalog.id
Ref: ci_base.organization_id > organization.id
Ref: ci_base.parent_id > ci_base.id

Ref: ci_module.id - ci_base.id
Ref: ci_catalog_category.id - ci_base.id
Ref: ci_country.id - ci_base.id
Ref: ci_role.id - ci_base.id
Ref: ci_entity_type.id - ci_base.id
Ref: ci_device_status.id - ci_base.id
Ref: ci_permission_scope.id - ci_base.id
Ref: ci_device_type.id - ci_entity_type.id
Ref: ci_asset_type.id - ci_entity_type.id
Ref: ci_asset_type_category.id - ci_base.id
Ref: ci_inventory_type.id - ci_entity_type.id
Ref: ci_organization_type.id - ci_entity_type.id
Ref: ci_user_type.id - ci_entity_type.id
Ref: ci_asset_group_type.id - ci_entity_type.id
Ref: ci_device_relation_type.id - ci_base.id
Ref: ci_tag.id - ci_base.id

Ref: ci_permission_scope.module_id > ci_module.id
Ref: ci_permission_scope.entity_type_id > ci_entity_type.id
Ref: ci_asset_type.category_id > ci_asset_type_category.id
Ref: ci_asset_group_type.allowed_asset_type_id > ci_asset_type.id
Ref: ci_tag.entity_type_id > ci_entity_type.id

Ref: customizable_entity.entity_type_id > ci_entity_type.id

Ref: organization.id - customizable_entity.id
Ref: organization.parent_id > organization.id
Ref: organization.organization_type_id > ci_organization_type.id
Ref: organization.deleted_by > user.id

Ref: catalog.organization_id > organization.id
Ref: catalog.module_id > ci_module.id
Ref: catalog.category_id > ci_catalog_category.id

Ref: user.id - customizable_entity.id
Ref: user.organization_id > organization.id
Ref: user.user_type_id > ci_user_type.id
Ref: user.deleted_by > user.id

Ref: user_role.user_id > user.id
Ref: user_role.role_id > ci_role.id
Ref: user_role.assigned_by > user.id

Ref: acl_role_permission.role_id > ci_role.id
Ref: acl_role_permission.permission_scope_id > ci_permission_scope.id
Ref: acl_role_permission.granted_by > user.id

Ref: acl_user_scope.user_id > user.id
Ref: acl_user_scope.permission_scope_id > ci_permission_scope.id

Ref: asset.id - customizable_entity.id
Ref: asset.organization_id > organization.id
Ref: asset.asset_type_id > ci_asset_type.id
Ref: asset.deleted_by > user.id

Ref: inventory.id - customizable_entity.id
Ref: inventory.organization_id > organization.id
Ref: inventory.inventory_type_id > ci_inventory_type.id
Ref: inventory.deleted_by > user.id

Ref: device.id - customizable_entity.id
Ref: device.organization_id > organization.id
Ref: device.device_type_id > ci_device_type.id
Ref: device.status_id > ci_device_status.id
Ref: device.deleted_by > user.id

Ref: device_asset_link.device_id - device.id
Ref: device_asset_link.asset_id > asset.id
Ref: device_asset_link.linked_by > user.id

Ref: device_inventory_link.device_id - device.id
Ref: device_inventory_link.inventory_id > inventory.id
Ref: device_inventory_link.linked_by > user.id

Ref: device_relation.master_id > device.id
Ref: device_relation.slave_id > device.id
Ref: device_relation.relation_type_id > ci_device_relation_type.id

Ref: asset_group.id - customizable_entity.id
Ref: asset_group.organization_id > organization.id
Ref: asset_group.group_type_id > ci_asset_group_type.id
Ref: asset_group.deleted_by > user.id

Ref: asset_group_item.group_id > asset_group.id
Ref: asset_group_item.asset_id > asset.id

Ref: entity_tag.tag_id > ci_tag.id

Ref: custom_field_def.organization_id > organization.id
Ref: custom_field_def.owner_entity_type_id > ci_entity_type.id
Ref: custom_field_def.ref_entity_type_id > ci_entity_type.id
Ref: custom_field_def.ref_catalog_id > catalog.id

Ref: custom_field_value_text.customizable_entity_id > customizable_entity.id
Ref: custom_field_value_text.field_def_id > custom_field_def.id

Ref: custom_field_value_number.customizable_entity_id > customizable_entity.id
Ref: custom_field_value_number.field_def_id > custom_field_def.id

Ref: custom_field_value_boolean.customizable_entity_id > customizable_entity.id
Ref: custom_field_value_boolean.field_def_id > custom_field_def.id

Ref: custom_field_value_date.customizable_entity_id > customizable_entity.id
Ref: custom_field_value_date.field_def_id > custom_field_def.id

Ref: custom_field_value_datetime.customizable_entity_id > customizable_entity.id
Ref: custom_field_value_datetime.field_def_id > custom_field_def.id

Ref: custom_field_value_entity.customizable_entity_id > customizable_entity.id
Ref: custom_field_value_entity.field_def_id > custom_field_def.id
Ref: custom_field_value_entity.ref_entity_id > customizable_entity.id

Ref: custom_field_value_catalog.customizable_entity_id > customizable_entity.id
Ref: custom_field_value_catalog.field_def_id > custom_field_def.id
Ref: custom_field_value_catalog.ref_item_id > ci_base.id

Ref: audit_event.user_id > user.id
```

{% endcode %}

### Частота обновления

Данные в `repo` схема синхронизируется в режиме реального времени с исходными системами. Обновления происходят немедленно по мере внесения изменений, а журналы аудита фиксируют все модификации для целей соответствия и исторического анализа.

### `ci_base`

Схема `repo` схема использует паттерн Single Table Inheritance для всех справочных данных через `ci_base` таблицу:

Схема `repo` схема использует **Single Table Inheritance** паттерн для всех справочных данных через `ci_base` таблицу. Этот подход объединяет системные словари, классификации и элементы справочников, определяемые пользователем, в единую структуру, обеспечивая согласованность и гибкость по всей схеме.

**Архитектура:**

Схема `ci_base` таблица служит основой для всех справочных данных, используя `discriminator` поле для идентификации конкретного типа справочной записи. Каждый тип справочника имеет соответствующую таблицу (например, `ci_device_type`, `ci_asset_type`) которая разделяет тот же `id` как `ci_base`, создавая типобезопасное отношение наследования.

**Как деловые сущности подключаются к ci\_base:**

Все деловые сущности в `repo` схеме ссылаются на `ci_base` подтипы для определения своей классификации и поведения:

* `organization` → ссылается на `ci_organization_type` (который наследует от `ci_entity_type` → `ci_base`)
* `user` → ссылается на `ci_user_type` (который наследует от `ci_entity_type` → `ci_base`)
* `device` → ссылается на `ci_device_type` и `ci_device_status` (оба наследуют от `ci_base`)
* `asset` → ссылается на `ci_asset_type` (который наследует от `ci_entity_type` → `ci_base`)
* `inventory` → ссылается на `ci_inventory_type` (который наследует от `ci_entity_type` → `ci_base`)
* `asset_group` → ссылается на `ci_asset_group_type` (который наследует от `ci_entity_type` → `ci_base`)

**Категории типов справочников:**

| Категория                       | Таблицы                                                                                                                                 | Назначение                                                                                  |
| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| **Конфигурация системы**        | `ci_module`, `ci_country`, `ci_role`                                                                                                    | Определяют модули системы, географические справочники и роли пользователей                  |
| **Определения типов сущностей** | `ci_entity_type`, `ci_device_type`, `ci_asset_type`, `ci_inventory_type`, `ci_organization_type`, `ci_user_type`, `ci_asset_group_type` | Классифицируйте все бизнес-сущности по типу                                                 |
| **Статус и классификация**      | `ci_device_status`, `ci_asset_type_category`                                                                                            | Отслеживайте состояния сущностей и группируйте типы в категории                             |
| **Контроль доступа**            | `ci_permission_scope`                                                                                                                   | Определяет, какие права могут быть предоставлены (связано с `ci_module` и `ci_entity_type`) |
| **Связи**                       | `ci_device_relation_type`                                                                                                               | Определяет типы отношений между устройствами (master-slave, резервирование и т.д.)          |
| **Категоризация**               | `ci_tag`, `ci_catalog_category`                                                                                                         | Обеспечивает гибкую систему тегирования и организацию каталогов                             |

<details>

<summary><strong>Примеры шаблонов запросов</strong></summary>

```sql
-- Получить все типы устройств для организации (системные + пользовательские)
SELECT cb.id, cb.code, cb.title_en, cb.is_system
FROM repo.ci_base cb
JOIN repo.ci_device_type dt ON dt.id = cb.id
WHERE cb.discriminator = 'device_type'
  AND (cb.is_system = true OR cb.organization_id = $org_id)
  AND cb.deleted_at IS NULL;

-- Получить тип актива с его категорией
SELECT 
  cb.code as asset_type_code,
  cb.title_en as asset_type_name,
  cat_cb.title_en as category_name
FROM repo.ci_base cb
JOIN repo.ci_asset_type at ON at.id = cb.id
LEFT JOIN repo.ci_asset_type_category cat ON cat.id = at.category_id
LEFT JOIN repo.ci_base cat_cb ON cat_cb.id = cat.id
WHERE cb.discriminator = 'asset_type'
  AND cb.deleted_at IS NULL;

-- Получить иерархическую структуру тегов
SELECT cb.id, cb.code, cb.title_en, cb.path, cb.parent_id
FROM repo.ci_base cb
JOIN repo.ci_tag t ON t.id = cb.id
WHERE cb.discriminator = 'tag'
  AND cb.deleted_at IS NULL
ORDER BY cb.path;
```

</details>

### Ключевые таблицы по категориям

Таблицы в `repo` схема организована по функциональным категориям. Описания ниже суммируют наиболее важные таблицы по их бизнес-назначению.

<details>

<summary><code>organization</code></summary>

**Назначение:** Управление иерархической организацией

<table><thead><tr><th width="139">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td><code>id</code>, <code>parent_id</code>, <code>path</code>, <code>organization_type_id</code>, <code>title_en</code>, <code>is_active</code>, <code>deleted_at</code></td></tr><tr><td><strong>Индексация</strong></td><td>GiST-индекс на <code>path</code> для иерархических запросов, индексы на <code>parent_id</code> и <code>organization_type_id</code></td></tr><tr><td><strong>Особые замечания</strong></td><td>Использует ltree для многоуровневых иерархий, наследуется от <code>customizable_entity</code> для поддержки пользовательских полей</td></tr></tbody></table>

</details>

<details>

<summary><code>user</code></summary>

**Назначение:** Учетные записи пользователей и аутентификация

<table><thead><tr><th width="139">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td><code>id</code>, <code>organization_id</code>, <code>user_type_id</code>, <code>identity_provider</code>, <code>identity_provider_id</code>, <code>full_name</code>, <code>is_active</code></td></tr><tr><td><strong>Индексация</strong></td><td>Уникальный индекс на (<code>organization_id</code>, <code>identity_provider</code>, <code>identity_provider_id</code>)</td></tr><tr><td><strong>Особые замечания</strong></td><td>Интеграция внешних провайдеров идентификации (Keycloak, Auth0, Okta), наследуется от <code>customizable_entity</code></td></tr></tbody></table>

</details>

<details>

<summary><code>device</code></summary>

**Назначение:** Физические трекинговые устройства

<table><thead><tr><th width="139">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td><code>id</code>, <code>organization_id</code>, <code>device_type_id</code>, <code>status_id</code>, <code>hw_id</code>, <code>label</code></td></tr><tr><td><strong>Индексация</strong></td><td>Индексы на <code>organization_id</code>, <code>device_type_id</code>, <code>status_id</code>, <code>hw_id</code></td></tr><tr><td><strong>Особые замечания</strong></td><td>Аппаратный идентификатор для трекинга устройства, наследуется от <code>customizable_entity</code> для пользовательских полей</td></tr></tbody></table>

</details>

<details>

<summary><code>asset</code></summary>

**Назначение:** Физические или виртуальные активы

<table><thead><tr><th width="139">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td><code>id</code>, <code>organization_id</code>, <code>asset_type_id</code>, <code>label</code>, <code>description</code></td></tr><tr><td><strong>Индексация</strong></td><td>Индексы на <code>organization_id</code> и <code>asset_type_id</code></td></tr><tr><td><strong>Особые замечания</strong></td><td>Наследуется от <code>customizable_entity</code>, связаны с устройствами через <code>device_asset_link</code></td></tr></tbody></table>

</details>

<details>

<summary><code>inventory</code></summary>

**Назначение:** Записи инвентаризации и складского учета

<table><thead><tr><th width="139">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td><code>id</code>, <code>organization_id</code>, <code>inventory_type_id</code>, <code>code</code></td></tr><tr><td><strong>Индексация</strong></td><td>Уникальный индекс на (<code>organization_id</code>, <code>code</code>)</td></tr><tr><td><strong>Особые замечания</strong></td><td>Уникальные коды внутри организации, связаны с устройствами через <code>device_inventory_link</code></td></tr></tbody></table>

</details>

<details>

<summary><code>asset_group</code></summary>

**Назначение:** Группировка активов с историческим отслеживанием

<table><thead><tr><th width="139">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td><code>id</code>, <code>organization_id</code>, <code>group_type_id</code>, <code>title_en</code>, <code>description</code></td></tr><tr><td><strong>Связи</strong></td><td><code>FROM repo.asset_group AS ag JOIN repo.asset_group_item AS agi ON agi.group_id = ag.id JOIN repo.asset AS a ON a.id = agi.asset_id WHERE agi.detached_at IS NULL</code></td></tr><tr><td><strong>Особые замечания</strong></td><td>Членство на основе времени через <code>asset_group_item</code>, запрос текущих членов с помощью <code>WHERE detached_at IS NULL</code></td></tr></tbody></table>

</details>

<details>

<summary><code>custom_field_def</code></summary>

**Назначение:** Определения пользовательских полей и метаданные

<table><thead><tr><th width="139">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td><code>id</code>, <code>organization_id</code>, <code>owner_entity_type_id</code>, <code>code</code>, <code>field_type</code>, <code>is_multi</code>, <code>is_required</code></td></tr><tr><td><strong>Содержимое</strong></td><td>Типы полей включают text, number, boolean, date, datetime, entity_ref, catalog_item_ref</td></tr><tr><td><strong>Особые замечания</strong></td><td>Обеспечивает гибкие пользовательские поля для любого типа сущности, значения хранятся в типо-специфичных <code>custom_field_value_*</code> таблицах</td></tr></tbody></table>

</details>

<details>

<summary><code>acl_role_permission</code></summary>

**Назначение:** Управление правами на основе ролей

<table><thead><tr><th width="139">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td><code>id</code>, <code>role_id</code>, <code>permission_scope_id</code>, <code>target_entity_id</code>, <code>actions</code></td></tr><tr><td><strong>Содержимое</strong></td><td>Битовая маска действий (READ=1, UPDATE=2, DELETE=4, CREATE=8), права специфичны для цели или для типа сущности в целом</td></tr><tr><td><strong>Связи</strong></td><td><code>FROM repo.user_role AS ur JOIN repo.acl_role_permission AS rp ON rp.role_id = ur.role_id WHERE ur.user_id = $user_id</code></td></tr><tr><td><strong>Особые замечания</strong></td><td>Работает совместно с <code>user_role</code> и <code>acl_user_scope</code> чтобы определить итоговые права пользователя</td></tr></tbody></table>

</details>

<details>

<summary><code>audit_event</code></summary>

**Назначение:** Унифицированный журнал аудита всех изменений в системе

<table><thead><tr><th width="139">Атрибут</th><th>Детали</th></tr></thead><tbody><tr><td><strong>Ключевые поля</strong></td><td><code>id</code>, <code>event_category</code>, <code>user_id</code>, <code>aggregate_type</code>, <code>aggregate_id</code>, <code>event_type</code>, <code>event_data</code>, <code>occurred_at</code></td></tr><tr><td><strong>Индексация</strong></td><td>Индексы на (<code>user_id</code>, <code>occurred_at</code>), (<code>aggregate_type</code>, <code>aggregate_id</code>, <code>occurred_at</code>), (<code>event_category</code>, <code>occurred_at</code>)</td></tr><tr><td><strong>Особые замечания</strong></td><td>Разделение по партициям по <code>occurred_at</code> (ежемесячно), две категории: <code>auth</code> (аутентификация) и <code>domain</code> (бизнес-события), сохраняет дельты изменений полей в <code>event_data</code> JSONB</td></tr></tbody></table>

</details>

### Связи данных

Схема `repo` схема реализует сложные шаблоны отношений для гибкого моделирования данных:

**Иерархические структуры**

* Организации используют пути ltree для эффективных запросов по дереву
* Элементы справочников (`ci_base`) поддерживают опциональные иерархии
* Автоматическое поддержание путей через триггеры базы данных

**Шаблоны наследования**

* Наследование таблиц: `customizable_entity` → бизнес-сущности (`organization`, `user`, `device`, `asset`, `inventory`, `asset_group`)
* Наследование ID: `ci_base` → таблицы типов справочников
* Различение типов через `entity_type_id` и `discriminator` поля

**Полиморфные связи**

Некоторые таблицы используют полиморфные ссылки без внешних ключей для максимальной гибкости:

* `acl_role_permission.target_entity_id` → любую `customizable_entity`
* `acl_user_scope.target_entity_id` → любую `customizable_entity`
* `entity_tag.entity_id` → любую `customizable_entity`

Эти связи проверяются на уровне приложения.

### Дополнительная информация

#### Валидация данных

Схема `repo` схема обеспечивает целостность данных посредством нескольких механизмов:

**Ограничения базы данных**

* ОГРАНИЧЕНИЯ UNIQUE с поддержкой мягкого удаления (частичные индексы WHERE `deleted_at` IS NULL)
* Ограничения CHECK (например, `device_relation` обеспечивает `master_id` ≠ `slave_id`)
* Ограничения NOT NULL для обязательных полей
* ЗНАЧЕНИЯ DEFAULT для временных меток и булевых флагов

**Проверки на уровне приложения**

* Проверка типа сущности для полиморфных ссылок
* Проверка каталога для ссылок пользовательских полей
* Валидация типов пользовательских полей
* Управление массивами для полей с множественными значениями

#### Оптимизация запросов

Таблицы организованы со специфическими стратегиями индексирования:

**Стандартные индексы:**

* Все внешние ключи имеют выделенные индексы
* Временные индексы на `created_at`, `updated_at`, `deleted_at`
* Составные индексы для часто объединяемых столбцов

**Специализированные индексы:**

* GiST-индексы на ltree-путях для иерархических запросов
* Частичные уникальные индексы, поддерживающие мягкое удаление
* Индексы значений пользовательских полей для фильтрации и сортировки
* Индексы событий аудита по времени + сущности для эффективного поиска

**Соображения по производительности:**

* Рекомендуется пул соединений (PgBouncer)
* Регулярное обслуживание VACUUM для больших таблиц
* Возможное будущее партиционирование для `device` таблицы по `organization_id`
* Материализованные представления для сложных вычислений контроля доступа
