# Couche de données brutes

La couche de données brutes contient 3 schémas de données distincts, chacun couvrant différents aspects de la plateforme de télématique et de business intelligence :

* [`raw_business_data`](#raw_business_data-structure) - contenant des tables, attributs et valeurs liés aux informations métier, telles que les véhicules, les employés, les géofences ajoutées par les utilisateurs, etc.
* [`raw_telematics_data`](#raw_telematics_data-structure) - contenant des tables, attributs et valeurs liés aux données de télématique transmises par les dispositifs sous surveillance, telles que les positions, les entrées, les sorties et les événements.
* [`repo`](#repo-data-structure) - contenant des tables pour la gestion des actifs et des stocks, y compris des types d'actifs configurables, des champs personnalisés, des relations entre actifs et des données géospatiales pour le suivi des ressources organisationnelles.

Chaque schéma est optimisé pour son domaine de données et ses modèles d'accès spécifiques, offrant une couverture complète des besoins opérationnels, télématiques et de gestion des actifs.

## `raw_business_data` structure

Ce schéma contient plus de 40 tables soigneusement sélectionnées pour couvrir divers aspects métier et cas d'utilisation. Ces tables représentent vos entités métier principales, la structure organisationnelle et les données opérationnelles.

<figure><img src="https://504457471-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" %}
Le diagramme interactif du schéma raw\_business\_data est disponible sur **dbdiagram.io**: <https://dbdiagram.io/d/V3-bronze-layer-68ecfd1c2e68d21b4131089a>
{% endhint %}

Vous trouverez ci-dessous les détails du schéma raw\_business\_data.

{% code title="schéma raw\_business\_data" expandable="true" %}

```sql
Table "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
}

Table "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)"
}

Table "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
}

Table "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]
}

Table "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
}

Table "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]
}

Table "places_linked_entity_fields" {
  "value" bigint [not null]
  "record_added_at" timestamp [not null]
  "place_id" integer [not null]
  "field_id" integer [not null]
}

Table "places_text_fields" {
  "place_id" integer [not null]
  "record_added_at" timestamp [not null]
  "value" text [not null]
  "field_id" integer [not null]
}

Table "users2zones" {
  "zone_id" integer [not null]
  "record_added_at" timestamp [not null]
  "user_id" integer [not null]
}

Table "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]
}

Table "device_output_name" {
  "device_id" integer [not null]
  "record_added_at" timestamp [not null]
  "label" "character varying(100)" [not null]
  "number" integer [not null]
}

Table "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]
}

Table "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]
}

Table "places_decimal_fields" {
  "field_id" integer [not null]
  "record_added_at" timestamp [not null]
  "place_id" integer [not null]
  "value" numeric [not null]
}

Table "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
}

Table "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]
}

Table "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
}

Table "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]
}

Table "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]
}

Table "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]
}

Table "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]
}

Table "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
}

Table "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]
}

Table "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]
}

Table "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)"
}

Table "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]
}

Table "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]
}

Table "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
}

Table "rules2zones" {
  "zone_id" integer [not null]
  "record_added_at" timestamp [not null]
  "rule_id" integer [not null]
}

Table "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
}


Table "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]
}

Table "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
}

Table "places_bigint_fields" {
  "field_id" integer [not null]
  "value" bigint [not null]
  "place_id" integer [not null]
  "record_added_at" timestamp [not null]
}

Table "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]
}

Table "description_parameters" {
  "description" "character varying(150)"
  "record_added_at" timestamp [not null]
  "type" "character varying(100)" [not null]
  "key" integer [not null]
}

Table "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]
}

Table "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]
}

Table "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
}

Table "places_longtext_fields" {
  "field_id" integer [not null]
  "value" text [not null]
  "record_added_at" timestamp [not null]
  "place_id" integer [not null]
}

Table "groups_objects" {
  "groups_client_id" integer
  "objects_client_id" integer

  Indexes {
    (groups_client_id, objects_client_id) [pk]
  }
}

Ref:"employees"."employee_id" < "checkins"."employee_id"

Ref:"objects"."object_id" < "checkins"."object_id"

Ref:"forms"."form_id" < "checkins"."form_id"

Ref:"sensor_description"."sensor_id" < "counters"."sensor_id"

Ref:"devices"."device_id" < "counters"."device_id"

Ref:"entities"."entity_id" < "custom_fields"."entity_id"

Ref:"departments"."department_id" < "employees"."department_id"

Ref:"users"."user_id" < "departments"."user_id"

Ref:"description_parameters"."key" < "counters"."counter_type"

Ref:"description_parameters"."key" < "custom_fields"."custom_field_type"

Ref:"description_parameters"."key" < "driver_history"."updated_by"

Ref:"description_parameters"."key" < "entities"."builtin_type"

Ref:"description_parameters"."key" < "sensor_description"."units_type"

Ref:"description_parameters"."key" < "status_history"."updated_by"

Ref:"description_parameters"."key" < "tasks"."status"

Ref:"description_parameters"."key" < "tasks"."created_at"

Ref:"description_parameters"."key" < "tasks"."task_type"

Ref:"description_parameters"."key" < "vehicles"."fuel_type"

Ref:"description_parameters"."key" < "task_history"."activity"

Ref:"description_parameters"."key" < "sensor_description"."group_type"

Ref:"devices"."device_id" < "device_output_name"."device_id"

Ref:"status_listings"."status_listing_id" < "devices"."status_listing_id"

Ref:"employees"."employee_id" < "driver_history"."new_employee_id"

Ref:"employees"."employee_id" < "driver_history"."old_employee_id"

Ref:"objects"."object_id" < "driver_history"."object_id"

Ref:"objects"."object_id" < "employees"."object_id"

Ref:"users"."user_id" < "employees"."user_id"

Ref:"users"."user_id" < "entities"."user_id"

Ref:"tasks"."task_id" < "forms"."task_id"

Ref:"objects"."object_id" < "forms"."object_id"

Ref:"objects"."object_id" < "tasks"."object_id"

Ref:"users"."user_id" < "garages"."user_id"

Ref:"groups"."client_id" < "groups_objects"."groups_client_id"

Ref:"objects"."client_id" < "groups_objects"."objects_client_id"

Ref:"models"."model" < "objects"."model"

Ref:"devices"."device_id" < "objects"."device_id"

Ref:"users"."user_id" < "places"."user_id"

Ref:"custom_fields"."custom_field_id" < "places_bigint_fields"."field_id"

Ref:"places"."place_id" < "places_bigint_fields"."place_id"

Ref:"custom_fields"."custom_field_id" < "places_decimal_fields"."field_id"

Ref:"places"."place_id" < "places_decimal_fields"."place_id"

Ref:"custom_fields"."custom_field_id" < "places_linked_entity_fields"."field_id"

Ref:"places"."place_id" < "places_linked_entity_fields"."place_id"

Ref:"custom_fields"."custom_field_id" < "places_longtext_fields"."field_id"

Ref:"places"."place_id" < "places_longtext_fields"."place_id"

Ref:"custom_fields"."custom_field_id" < "places_text_fields"."field_id"

Ref:"places"."place_id" < "places_text_fields"."place_id"

Ref:"rules"."rule_id" < "rules2zones"."rule_id"

Ref:"objects"."object_id" < "rules2objects"."object_id"

Ref:"rules"."rule_id" < "rules2objects"."object_id"

Ref:"zones"."zone_id" < "rules2zones"."zone_id"

Ref:"devices"."device_id" < "sensor_description"."device_id"

Ref:"statuses"."status_id" < "status_history"."new_status_id"

Ref:"statuses"."status_id" < "status_history"."old_status_id"

Ref:"devices"."device_id" < "status_history"."device_id"

Ref:"users"."user_id" < "status_listings"."user_id"

Ref:"status_listings"."status_listing_id" < "statuses"."listing_id"

Ref:"tags"."tag_id" < "tag_links"."tag_id"

Ref:"users"."user_id" < "tags"."user_id"

Ref:"tasks"."task_id" < "task_history"."task_id"

Ref:"users"."user_id" < "task_history"."user_id"

Ref:"tasks"."parent_task_id" < "tasks"."task_id"

Ref:"users"."user_id" < "tasks"."user_id"

Ref:"users"."master_id" < "users"."user_id"

Ref:"users"."user_id" < "users2zones"."user_id"

Ref:"zones"."zone_id" < "users2zones"."zone_id"

Ref:"vehicles"."vehicle_id" < "vehicle_service_tasks"."vehicle_id"

Ref:"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:"users"."user_id" < "devices"."owner_id"

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

```

{% endcode %}

### Fréquence de mise à jour

Les données de ce schéma sont synchronisées avec la base de données principale. Les mises à jour s'effectuent de manière incrémentale au fur et à mesure des modifications dans la base MySQL source, généralement avec un décalage de moins de 5 minutes par rapport à la modification source.

### `description_parameters`

Le système inclut des données de référence afin de standardiser les valeurs dans toute la base de données :

<table><thead><tr><th width="167.1817626953125">Type de référence</th><th width="173.9090576171875">Description</th><th>Valeurs d'exemple</th></tr></thead><tbody><tr><td>Définitions de types</td><td>Types d’entités standard</td><td><code>vehicle_type : voiture, camion, bus</code></td></tr><tr><td>Codes de statut</td><td>Valeurs de statut des tâches et du système</td><td><code>tasks_status : non attribuée, attribuée, terminée</code></td></tr><tr><td>Définitions d’unités</td><td>Unités de mesure pour les capteurs</td><td><code>units_type : litre, gallon, degré Celsius</code></td></tr><tr><td>Classifications d’entités</td><td>Catégories d’entités métier</td><td><code>entities_type : lieu, tâche, client</code></td></tr></tbody></table>

### Tables clés par catégorie

Les tables du **`raw_business_data`** schéma sont organisées en catégories fonctionnelles pour faciliter la navigation. Le tableau ci-dessous récapitule les tables clés selon leur finalité métier :

Entités métier principales

<details>

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

**Description**: Comptes utilisateurs contenant les informations de profil, l’affiliation à l’entreprise, les paramètres de localisation (fuseau horaire, locale) et les relations hiérarchiques via master\_id pour les structures de comptes multiniveaux

<table><thead><tr><th width="145">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>user_id</code> - Identifiant utilisateur unique<br>- <code>company_label</code> - Nom de l’entreprise associée à l’utilisateur<br>- <code>first_name</code> - Nom d’utilisateur<br>- <code>last_name</code> - Nom de famille de l’utilisateur<br>- <code>middle_name</code> - Patronyme de l’utilisateur<br>- <code>locale</code> - Paramètres linguistiques de l’utilisateur<br>- <code>timezone_label</code> - Fuseau horaire au format IANA<br>- <code>master_id</code> - ID de l’utilisateur principal (si le compte actuel est subordonné)<br>- <code>registration_datetime</code> - Date d’inscription dans le système<br>- <code>birth_date</code> - Date de naissance de l’utilisateur</td></tr><tr><td><strong>Relations</strong></td><td>Utilisateur parent via <code>master_id</code>, lié à <code>employés</code>, <code>départements</code>, <code>lieux</code>, <code>tâches</code> via <code>user_id</code></td></tr><tr><td><strong>Notes spéciales</strong></td><td>Entité centrale reliant les données organisationnelles ; <code>master_id</code> permet des hiérarchies d’utilisateurs pour les structures de comptes multiniveaux</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>employés</code></strong></summary>

**Description**: Enregistrements des employés et des conducteurs utilisés pour représenter les personnes travaillant pour l’organisation, y compris les informations personnelles, les détails du permis de conduire, les affectations aux départements, les clés matérielles pour l’identification iButton/RFID et les données de localisation avec prise en charge du géorepérage

<table><thead><tr><th width="143">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>employee_id</code> - Identifiant de l’entité employé<br>- <code>user_id</code> - Identifiant de l’entité utilisateur<br>- <code>object_id</code> - Identifiant de l’objet de l’entité<br>- <code>department_id</code> - ID du département auquel l’employé est affecté<br>- <code>first_name</code> - Attribut first_name de la table employees<br>- <code>last_name</code> - Attribut last_name de la table employees<br>- <code>middle_name</code> - Attribut middle_name de la table employees<br>- <code>driver_license_number</code> - Numéro de permis de conduire<br>- <code>driver_license_categories</code> - Catégories du permis de conduire<br>- <code>driver_license_issue_date</code> - Date de délivrance du permis de conduire<br>- <code>driver_license_valid_till</code> - Date de validité du permis de conduire<br>- <code>hardware_key</code> - Une clé matérielle<br>- <code>email</code> - E-mail de l’employé<br>- <code>phone_number</code> - Téléphone de l’employé sans le signe "+"<br>- <code>address</code> - Adresse du lieu<br>- <code>personnel_number</code> - Numéro de personnel de l’employé/du conducteur<br>- <code>citizen_id_number</code> - Numéro de sécurité sociale<br>- <code>latitude</code> - Lieu associé à cet employé<br>- <code>longitude</code> - Lieu associé à cet employé<br>- <code>radius</code> - Lieu associé à cet employé en mètres<br>- <code>fuel_consumption</code> - Attribut fuel_consumption de la table employees<br>- <code>fuel_cost</code> - Attribut fuel_cost de la table employees<br>- <code>is_deleted</code> - Attribut is_deleted de la table employees</td></tr><tr><td><strong>Relations</strong></td><td>Liens vers <code>users</code>, <code>départements</code>, <code>objects</code> (traceur attribué), suivi dans <code>driver_history</code> et <code>checkins</code></td></tr><tr><td><strong>Notes spéciales</strong></td><td>La clé matérielle permet l’identification du conducteur via iButton ou RFID ; prend en charge le géorepérage avec <code>latitude</code>, <code>longitude</code>, <code>radius</code> champs</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>départements</code></strong></summary>

**Description**: Unités organisationnelles avec des données de localisation géographique (latitude, longitude, rayon) permettant des analyses basées sur le géorepérage pour les rapports au niveau du département et l’association de la localisation des employés

<table><thead><tr><th width="156">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>department_id</code> - Identifiant de l’entité département<br>- <code>user_id</code> - Identifiant de l’entité utilisateur<br>- <code>department_label</code> - Attribut department_label de la table departments<br>- <code>latitude</code> - Lieu associé à ce département<br>- <code>longitude</code> - Lieu associé à ce département<br>- <code>radius</code> - Taille de la géolocalisation en mètres<br>- <code>address</code> - Attribut address de la table departments</td></tr><tr><td><strong>Relations</strong></td><td>Lie les employés à la structure organisationnelle via <code>department_id</code></td></tr><tr><td><strong>Notes spéciales</strong></td><td>Les champs de localisation prennent en charge des analyses basées sur le géorepérage pour les rapports au niveau du département</td></tr></tbody></table>

</details>

Suivi et surveillance

<details>

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

**Description**: Registre des dispositifs de suivi physiques avec identifiants matériels (IMEI), informations sur la carte SIM, état de connectivité réseau (puissance du signal, roaming, opérateur) et affectations de liste de statut pour la gestion du cycle de vie des appareils

<table><thead><tr><th width="138">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>device_id</code> - ID de l’appareil<br>- <code>owner_id</code> - ID du propriétaire de l’appareil sur le compte duquel la balise a été ajoutée<br>- <code>device_imei</code> - IMEI de l’appareil<br>- <code>phone</code> - Numéro de carte SIM de l’appareil<br>- <code>status_listing_id</code> - ID du statut de l’appareil<br>- <code>network_label</code> - Nom du réseau auquel la carte SIM est connectée<br>- <code>signal_level</code> - Puissance du signal de l’appareil<br>- <code>has_roaming</code> - Indicateur de disponibilité du roaming<br>- <code>is_sim_blocked</code> - Indicateur de verrouillage de la carte SIM<br>- <code>created_at</code> - Date et heure de création de l’entrée</td></tr><tr><td><strong>Relations</strong></td><td>Entité centrale reliant <code>objects</code>, <code>models</code>, <code>sensor_description</code>, <code>counters</code>; <code>owner_id</code> références <code>users.user_id</code></td></tr><tr><td><strong>Notes spéciales</strong></td><td>Toutes les données télématiques du <code>raw_telematics_data</code> schéma font référence à cette table via <code>device_id</code></td></tr></tbody></table>

</details>

<details>

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

**Description**: Registre central des entités surveillées (véhicules, actifs, personnel) reliant les dispositifs physiques à la structure organisationnelle via client\_id et group\_id, représentant l’« unité traçable » avec un objet actif par appareil

<table><thead><tr><th width="148">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>object_id</code> - Identifiant de l’objet de l’entité<br>- <code>client_id</code> - Identifiant de l’entité client<br>- <code>device_id</code> - Identifiant de l’entité appareil<br>- <code>object_label</code> - Nom de l’objet<br>- <code>model</code> - Modèle de l’appareil<br>- <code>group_id</code> - ID de groupe de l’entité<br>- <code>create_datetime</code> - Date et heure de création d’une nouvelle ligne sur le serveur<br>- <code>is_deleted</code> - Attribut is_deleted de la table objects<br>- <code>is_clone</code> - Indicateur de clone</td></tr><tr><td><strong>Relations</strong></td><td>Hub central reliant les appareils aux utilisateurs (<code>client_id</code>), aux détails des véhicules, à l’historique de suivi, aux tâches et aux règles</td></tr><tr><td><strong>Notes spéciales</strong></td><td>Représente l’« unité traçable » dans le système ; un objet par appareil en usage actif</td></tr></tbody></table>

</details>

<details>

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

**Description**: Registre central des entités surveillées (véhicules, actifs, personnel) reliant les dispositifs physiques à la structure organisationnelle via client\_id et group\_id, représentant l’« unité traçable » avec un objet actif par appareil

<table><thead><tr><th width="135">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>model_id</code> - Identifiant du modèle de l’entité<br>- <code>model</code> - Attribut model de la table models<br>- <code>vendor</code> - Nom de l’entreprise qui a publié le traceur<br>- <code>alternative_label</code> - Attribut alternative_label de la table models<br>- <code>analog_amount</code> - Nombre d’entrées analogiques du traceur<br>- <code>digital_amount</code> - Nombre d’entrées discrètes du traceur<br>- <code>outputs_amount</code> - Nombre de sorties discrètes du traceur<br>- <code>has_battery_level</code> - Détermine si le traceur transmet les relevés de charge de la batterie<br>- <code>has_altitude</code> - Détermine si le traceur transmet l’altitude<br>- <code>has_phone</code> - Y a-t-il une carte SIM ?<br>- <code>has_gsm_level</code> - Un traceur peut-il transmettre la puissance du signal GSM ?<br>- <code>has_gsm_name</code> - Le traceur peut-il transmettre le nom du réseau GSM ou le code opérateur (MCC + MNC) ?<br>- <code>has_gsm_roaming</code> - Le traceur peut-il transmettre l’état du roaming ?<br>- <code>has_detach_button</code> - Le traceur dispose-t-il d’un capteur de retrait ?<br>- <code>type_output_control</code> - Profil de contrôle des sorties du traceur<br>- <code>type_special_control</code> - Contient des paramètres spécialisés et des modules fonctionnels pour des modèles d’appareils individuels, tels que le mode de conduite dangereuse (hbm_telfm) pour les équipements Teltonika<br>- <code>is_clone</code> - Le modèle est-il un clone d’un autre modèle ?</td></tr><tr><td><strong>Contenu</strong></td><td>Les indicateurs booléens de capacité indiquent quels champs de données sont disponibles pour ce type d’appareil</td></tr><tr><td><strong>Notes spéciales</strong></td><td>Utilisez les indicateurs de capacité pour déterminer les capteurs et les entrées valides lors de l’interrogation des données télématiques</td></tr></tbody></table>

</details>

<details>

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

**Description**: Configuration complète des capteurs reliant les entrées de l’appareil à la logique métier, y compris les mappages d’entrées, les unités de mesure, les facteurs de conversion (multiplicateur/diviseur), les tables d’étalonnage pour les capteurs de carburant, les seuils de précision et la logique de regroupement pour les relevés de capteurs agrégés

<table><thead><tr><th width="142">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>sensor_id</code> - Identifiant de l’entité capteur<br>- <code>device_id</code> - Identifiant de l’entité appareil<br>- <code>sensor_label</code> - Nom du capteur pour l’interface<br>- <code>input_label</code> - Nom du champ du message (attribut) à partir duquel les données du capteur sont prises. S’il est égal à "input_status", il s’agit d’un capteur discret<br>- <code>sensor_type</code> - Type de capteur<br>- <code>units_type</code> - Unités de mesure<br>- <code>multiplier</code> - Multiplicateur - le nombre par lequel multiplier la valeur du champ. Pour les capteurs de mesure uniquement<br>- <code>divider</code> - Diviseur - le nombre par lequel diviser la valeur du champ. Pour les capteurs de mesure uniquement<br>- <code>accuracy</code> - Pourcentage spécifié pour calculer l’erreur absolue du volume du réservoir. Cette erreur est utilisée pour déterminer quand des remplissages ou des vidanges sont en cours. Cela est utilisé uniquement pour les capteurs de carburant<br>- <code>calibration_data</code> - Attribut calibration_data de la table sensor_description<br>- <code>input_id</code> - Numéro d’entrée pour capteur discret<br>- <code>group_id</code> - Les capteurs du même type avec le même group_id et source_id sont considérés comme appartenant au même groupe. Leurs données sont additionnées ou moyennées, selon la valeur de group_type. Ceci est requis pour les capteurs agrégés. C’est utilisé dans les capteurs de mesure<br>- <code>group_type</code> - 0 - additionner les valeurs des capteurs au sein d’un groupe, 1 - moyenne<br>- <code>sensor_units</code> - Nom d’unité saisi par l’utilisateur si units_type=0 (personnalisé)<br>- <code>parameters</code> - Objet facultatif avec des paramètres supplémentaires parent_ids - tableau facultatif de parent_ids pour un capteur composite. volume - double. Facultatif. Volume pour un capteur composite. parent_ids - facultatif. Tableau d’entiers. Tableau de parent_ids pour un capteur composite. volume - facultatif. Double. Volume pour un capteur composite. min - facultatif. Double. Valeur brute minimale acceptable pour un capteur. max - facultatif. Double. Valeur brute maximale acceptable pour un capteur. max_lowering_by_time - facultatif. Double. Baisse maximale légale de la valeur par heure. max_lowering_by_mileage - facultatif. Double. Baisse maximale légale de la valeur par 100 km. ignore_drains_in_move - facultatif. Booléen. La valeur par défaut est false. Si true, les vidanges de carburant ne seront pas détectées pendant le déplacement. ignore_refuels_in_move - facultatif. Booléen. La valeur par défaut est false. Si true, les ravitaillements ne seront pas détectés pendant le déplacement. refuel_gap_minutes - facultatif. Entier. La valeur par défaut est 5. Le délai en minutes après le début du déplacement pendant lequel les ravitaillements seront détectés pendant le déplacement. custom_field_name - facultatif. Booléen. La valeur par défaut est false. Le paramètre détermine si le champ input_name est une valeur personnalisée saisie par l’utilisateur. Cela n’a de sens que si le modèle de traceur dispose de la fonctionnalité has_custom_fields</td></tr><tr><td><strong>Relations</strong></td><td>Relie les entrées de l’appareil (depuis <code>raw_telematics_data.inputs</code>) à la logique métier via <code>device_id</code> et <code>input_label</code> correspondance</td></tr><tr><td><strong>Notes spéciales</strong></td><td><code>calibration_data</code> (JSONB) stocke des tables d’étalonnage spécifiques aux capteurs pour les capteurs de niveau de carburant ; <code>multiplier</code> et <code>divider</code> convertit les valeurs brutes en unités</td></tr></tbody></table>

</details>

Gestion des actifs

<details>

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

**Description**: Registre complet des véhicules contenant les spécifications (dimensions, poids, capacité), la documentation (VIN, immatriculation, assurance), les paramètres opérationnels (consommation de carburant, volume du réservoir) et l’affectation actuelle du traceur via object\_id pour la gestion de flotte et le suivi de conformité

<table><thead><tr><th width="144">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>vehicle_id</code> - Identifiant de l’entité véhicule<br>- <code>user_id</code> - Identifiant de l’entité utilisateur<br>- <code>object_id</code> - Identifiant de l’objet de l’entité<br>- <code>garage_id</code> - Identifiant de l’entité garage<br>- <code>vehicle_label</code> - Attribut vehicle_label de la table vehicles<br>- <code>registration_number</code> - Numéro d’immatriculation / plaque d’immatriculation d’un véhicule<br>- <code>vin</code> - Attribut vin de la table vehicles<br>- <code>manufacture_year</code> - Attribut manufacture_year de la table vehicles<br>- <code>fuel_type</code> - Attribut fuel_type de la table vehicles<br>- <code>fuel_cost</code> - Attribut fuel_cost de la table vehicles<br>- <code>fuel_tank_volume</code> - Attribut fuel_tank_volume de la table vehicles<br>- <code>max_speed</code> - Attribut max_speed de la table vehicles<br>- <code>model</code> - Attribut model de la table vehicles<br>- <code>color</code> - Attribut color de la table vehicles<br>- <code>trailer</code> - Attribut trailer de la table vehicles<br>- <code>additional_info</code> - Attribut additional_info de la table vehicles<br>- <code>vehicle_type</code> - Attribut vehicle_type de la table vehicles<br>- <code>vehicle_subtype</code> - Attribut vehicle_subtype de la table vehicles<br>- <code>vehicle_status_id</code> - Identifiant de l’entité statut du véhicule<br>- <code>chassis_number</code> - Attribut chassis_number de la table vehicles<br>- <code>frame_number</code> - Attribut frame_number de la table vehicles<br>- <code>trailer_reg_number</code> - Attribut trailer_reg_number de la table vehicles<br>- <code>payload_weight</code> - Attribut payload_weight de la table vehicles<br>- <code>payload_height</code> - Attribut payload_height de la table vehicles<br>- <code>payload_length</code> - Attribut payload_length de la table vehicles<br>- <code>payload_width</code> - Attribut payload_width de la table vehicles<br>- <code>passenger_capacity</code> - Nombre maximum de passagers<br>- <code>gross_weight</code> - Attribut gross_weight de la table vehicles<br>- <code>standard_fuel_consumption</code> - Consommation moyenne normale de carburant en litres par 100 km<br>- <code>fuel_grade</code> - Attribut fuel_grade de la table vehicles<br>- <code>wheel_arrangement</code> - Attribut wheel_arrangement de la table vehicles<br>- <code>tyre_size</code> - Taille du véhicule : dimensions et taille des roues<br>- <code>tyres_number</code> - Nombre de roues<br>- <code>liability_insurance_policy_number</code> - Attribut liability_insurance_policy_number de la table vehicles<br>- <code>liability_insurance_valid_till</code> - Date de validité de l’assurance responsabilité civile<br>- <code>free_insurance_policy_number</code> - Attribut free_insurance_policy_number de la table vehicles<br>- <code>free_insurance_valid_till_date</code> - Date de validité de l’assurance gratuite</td></tr><tr><td><strong>Relations</strong></td><td>Liens vers <code>objects</code> (traceur actuel), <code>garages</code> (lieu de service), <code>vehicle_service_tasks</code>; suivi dans <code>vehicle_trackers_history</code></td></tr><tr><td><strong>Notes spéciales</strong></td><td>Les champs de dimensions physiques (<code>payload_length</code>, <code>payload_width</code>, <code>payload_height</code>, <code>gross_weight</code>) prennent en charge les analyses de planification de charge ; les dates d’assurance permettent le suivi de conformité</td></tr></tbody></table>

</details>

<details>

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

**Description**: Emplacements des ateliers et de maintenance avec coordonnées géographiques (latitude, longitude, rayon), informations de contact pour les mécaniciens et les répartiteurs, permettant la détection des visites de service basée sur le géorepérage et l’analyse de proximité

<table><thead><tr><th width="135">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>garage_id</code> - Identifiant de l’entité garage<br>- <code>user_id</code> - Identifiant de l’entité utilisateur<br>- <code>latitude</code> - Objet lieu<br>- <code>longitude</code> - Objet lieu<br>- <code>radius</code> - Taille de la géolocalisation en mètres<br>- <code>address</code> - Objet lieu<br>- <code>organization_label</code> - ID du dépôt<br>- <code>mechanic_name</code> - Nom du mécanicien<br>- <code>dispatcher_name</code> - Nom du répartiteur</td></tr><tr><td><strong>Relations</strong></td><td>Référencé par <code>vehicles.garage_id</code> pour l’affectation du lieu de service</td></tr><tr><td><strong>Notes spéciales</strong></td><td>Les champs de localisation permettent la détection des visites de service basée sur le géorepérage et l’analyse de proximité</td></tr></tbody></table>

</details>

<details>

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

**Description**: Planification de maintenance et suivi de l’historique des interventions avec plusieurs types de déclencheurs (basé sur la date, le kilométrage, les heures moteur), intervalles de tâches récurrents, notifications multicanales (e-mail, SMS, push) et distinction entre les événements de maintenance planifiés (is\_repeat) et non planifiés

<table><thead><tr><th width="132">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>service_task_id</code> - Identifiant de l’entité tâche de service<br>- <code>vehicle_id</code> - Identifiant de l’entité véhicule<br>- <code>description</code> - Attribut description de la table vehicle_service_tasks<br>- <code>status</code> - Valeur du statut de l’attribut status<br>- <code>cost</code> - Attribut cost de la table vehicle_service_tasks<br>- <code>start_date</code> - Date et heure associées à l’attribut start_date<br>- <code>end_date</code> - Date et heure associées à l’attribut end_date<br>- <code>completion_date</code> - Date et heure associées à l’attribut completion_date<br>- <code>predicted_datetime</code> - Date et heure associées à l’attribut predicted_datetime<br>- <code>mileage_limit</code> - Attribut mileage_limit de la table vehicle_service_tasks<br>- <code>engine_hours_limit</code> - Attribut engine_hours_limit de la table vehicle_service_tasks<br>- <code>start_mileage</code> - Attribut start_mileage de la table vehicle_service_tasks<br>- <code>start_engine_hours</code> - Attribut start_engine_hours de la table vehicle_service_tasks<br>- <code>mileage_notification_interval</code> - Attribut mileage_notification_interval de la table vehicle_service_tasks<br>- <code>engine_hours_notification_interval</code> - Attribut engine_hours_notification_interval de la table vehicle_service_tasks<br>- <code>date_notification_interval</code> - Conversion d’un entier N en N jours<br>- <code>mileage_repeat_interval</code> - Attribut mileage_repeat_interval de la table vehicle_service_tasks<br>- <code>engine_hours_repeat_interval</code> - Attribut engine_hours_repeat_interval de la table vehicle_service_tasks<br>- <code>date_repeat_interval</code> - Conversion d’un entier N en N jours<br>- <code>notification_emails</code> - Attribut notification_emails de la table vehicle_service_tasks<br>- <code>notification_sms_phone_numbers</code> - Attribut notification_sms_phone_numbers de la table vehicle_service_tasks<br>- <code>is_notification_push_enabled</code> - Attribut is_notification_push_enabled de la table vehicle_service_tasks<br>- <code>completion_mileage</code> - Attribut completion_mileage de la table vehicle_service_tasks<br>- <code>completion_engine_hours</code> - Attribut completion_engine_hours de la table vehicle_service_tasks<br>- <code>is_repeat</code> - Attribut is_repeat de la table vehicle_service_tasks<br>- <code>is_unplanned</code> - Attribut is_unplanned de la table vehicle_service_tasks<br>- <code>comment</code> - Attribut comment de la table vehicle_service_tasks</td></tr><tr><td><strong>Contenu</strong></td><td>Prend en charge trois types de déclencheurs : basé sur la date, basé sur le kilométrage, basé sur les heures moteur ; paramètres de notification pour e-mail, SMS, push</td></tr><tr><td><strong>Notes spéciales</strong></td><td><code>is_repeat</code> et les champs d’intervalle permettent des plannings de maintenance récurrents ; <code>is_unplanned</code> distingue la maintenance planifiée de la maintenance réactive</td></tr></tbody></table>

</details>

Localisation et routage

<details>

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

**Description**: Zones géorepérées définissant des périmètres virtuels à l’aide de cercles ou de polygones pour surveiller les événements d’entrée et de sortie des véhicules/actifs, prenant en charge l’automatisation basée sur des règles et l’analyse de localisation avec un code couleur pour la différenciation visuelle

<table><thead><tr><th width="150">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>zone_id</code> - Identifiant de l’entité zone<br>- <code>client_id</code> - Identifiant de l’entité client<br>- <code>zone_label</code> - Attribut zone_label de la table zones<br>- <code>zone_type</code> - Attribut zone_type de la table zones<br>- <code>latitude</code> - Objet facultatif, la boîte englobante qui peut contenir entièrement le résultat renvoyé<br>- <code>longitude</code> - Objet facultatif, la boîte englobante qui peut contenir entièrement le résultat renvoyé<br>- <code>circle_center_latitude</code> - Attribut circle_center_latitude de la table zones<br>- <code>circle_center_longitude</code> - Attribut circle_center_longitude de la table zones<br>- <code>radius</code> - Taille de la géolocalisation en mètres<br>- <code>address</code> - Attribut address de la table zones<br>- <code>color</code> - Attribut color de la table zones</td></tr><tr><td><strong>Contenu</strong></td><td>Les types de zones incluent cercle, polygone (défini via <code>geofence_points</code>), et des classifications de zones spéciales</td></tr><tr><td><strong>Relations</strong></td><td>Référencé par <code>rules2zones</code>, <code>users2zones</code>; les sommets du polygone sont stockés dans <code>geofence_points</code></td></tr><tr><td><strong>Notes spéciales</strong></td><td>Les fonctions PostGIS peuvent être utilisées pour vérifier l’appartenance d’un point à un polygone pour une analyse complexe du géorepérage</td></tr></tbody></table>

</details>

<details>

<summary><strong><code>lieux</code></strong></summary>

**Description**: Points d’intérêt avec coordonnées géographiques, définitions de rayon et prise en charge extensible des champs personnalisés pour stocker les informations de contact client et les données spécifiques à l’entreprise, permettant l’intégration CRM/ERP via external\_id et la génération de rapports basés sur la localisation

<table><thead><tr><th width="129">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>place_id</code> - Identifiant de l’entité lieu<br>- <code>user_id</code> - Identifiant de l’entité utilisateur<br>- <code>place_label</code> - L’attribut place_label de la table places<br>- <code>latitude</code> - Objet lieu<br>- <code>longitude</code> - Objet lieu<br>- <code>radius</code> - Taille de la géolocalisation en mètres<br>- <code>address</code> - L’attribut address de la table places<br>- <code>description</code> - L’attribut description de la table places<br>- <code>external_id</code> - ID pour l’intégration avec des systèmes externes (CRM)<br>- <code>custom_fields</code> - Champs supplémentaires<br>- <code>assigned_datetime</code> - Date et heure d’attribution du point d’intérêt à l’utilisateur</td></tr><tr><td><strong>Relations</strong></td><td>Étendu avec les valeurs des champs personnalisés via <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>Notes spéciales</strong></td><td><code>custom_fields</code> JSONB fournit un accès rapide ; les tables associées permettent le filtrage et le tri sur les attributs personnalisés</td></tr></tbody></table>

</details>

<details>

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

**Description**: Coordonnées des sommets ordonnées (le champ number détermine la séquence) définissant les limites polygonales pour des formes de géorepérage complexes, permettant des périmètres géographiques précis au-delà des zones circulaires simples, utilisé avec PostGIS ST\_MakePolygon pour les opérations géométriques

<table><thead><tr><th width="133">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>zone_id</code> - ID de la zone à laquelle ce formulaire est rattaché<br>- <code>number</code> - Numéro de série<br>- <code>latitude</code> - Emplacement<br>- <code>longitude</code> - Emplacement</td></tr><tr><td><strong>Relations</strong></td><td>Plusieurs enregistrements par <code>zone_id</code> définissent les limites du polygone ; <code>number</code> le champ détermine l’ordre des sommets</td></tr><tr><td><strong>Notes spéciales</strong></td><td>Interroger avec <code>ORDER BY number</code> pour reconstruire le tracé du polygone ; à utiliser avec PostGIS ST_MakePolygon pour les opérations géométriques</td></tr></tbody></table>

</details>

Gestion des tâches et des flux de travail

<details>

<summary><strong><code>tâches</code></strong></summary>

**Description**: Affectations d’ordres de travail avec validation de localisation (latitude, longitude, radius), fenêtres temporelles (time\_from, time\_to), exigences de durée de visite (stay\_duration\_minutes, arrival\_duration\_minutes), structure hiérarchique via parent\_task\_id et suivi de statut pour la gestion des interventions terrain et des opérations de livraison

<table><thead><tr><th width="130">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>task_id</code> - Identifiant de l’entité tâche<br>- <code>user_id</code> - Identifiant de l’entité utilisateur<br>- <code>object_id</code> - Identifiant de l’objet de l’entité<br>- <code>parent_task_id</code> - Identifiant de l’entité tâche parente<br>- <code>task_label</code> - L’attribut task_label de la table tasks<br>- <code>status</code> - Valeur du statut de l’attribut status<br>- <code>task_type</code> - Type de tâche, tâche, itinéraire ou point de contrôle<br>- <code>latitude</code> - L’attribut latitude de la table tasks<br>- <code>longitude</code> - L’attribut longitude de la table tasks<br>- <code>radius</code> - Taille de la géolocalisation en mètres<br>- <code>arrival_datetime</code> - Moment où le traceur arrive dans la zone de la tâche. IGNORÉ lors de la création/mise à jour<br>- <code>created_at</code> - L’attribut created_at de la table tasks<br>- <code>status_change_datetime</code> - Date et heure de mise à jour de la tâche<br>- <code>time_from</code> - La date et l’heure associées à l’attribut time_from<br>- <code>time_to</code> - La date et l’heure associées à l’attribut time_to<br>- <code>stay_duration</code> - L’attribut stay_duration de la table tasks<br>- <code>stay_duration_minutes</code> - Durée de visite. Le temps qu’un travailleur mobile doit passer sur le site d’affectation pour terminer la tâche avec succès. Les visites multiples sont cumulatives<br>- <code>arrival_duration_minutes</code> - Ignorer les visites aléatoires plus courtes que la durée spécifiée. Lors du calcul de la durée minimale, les visites plus courtes que la durée spécifiée seront ignorées<br>- <code>max_delay_minuts</code> - Retard acceptable. Le temps maximum pendant lequel un employé peut être en retard. Toute tâche achevée pendant ce délai sera marquée comme « en retard »<br>- <code>is_stay_control_enabled</code> - L’attribut is_stay_control_enabled de la table tasks<br>- <code>address</code> - L’attribut address de la table tasks<br>- <code>description</code> - Attribut description de la table tasks<br>- <code>custom_fields</code> - L’attribut custom_fields de la table tasks<br>- <code>external_id</code> - Identifiant d’entité externe<br>- <code>order_sort</code> - L’attribut order_sort de la table tasks<br>- <code>created_by</code> - Source de la tâche créée</td></tr><tr><td><strong>Contenu</strong></td><td>Prend en charge les tâches hiérarchiques via <code>parent_task_id</code>; les fenêtres temporelles définies par <code>time_from</code>/<code>time_to</code>; la validation de géorepérage avec la localisation et le radius</td></tr><tr><td><strong>Relations</strong></td><td>Liens vers <code>forms</code> (collecte de données), <code>task_history</code> (changements de statut), <code>objects</code> (traceur affecté)</td></tr><tr><td><strong>Notes spéciales</strong></td><td><code>stay_duration</code> et <code>arrival_duration_minutes</code> permet de surveiller la conformité des tâches de livraison et de service</td></tr></tbody></table>

</details>

<details>

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

**Description**: Formulaires configurables de collecte de données pour capturer des informations structurées lors de l’exécution d’une tâche ou des enregistrements de connexion dans l’application mobile, avec des champs et des valeurs stockés en JSON, une validation de localisation facultative (is\_submission\_in\_zone) et des exigences de soumission obligatoires lorsqu’ils sont attachés à des tâches

<table><thead><tr><th width="141">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>form_id</code> - Identifiant de l’entité formulaire<br>- <code>task_id</code> - ID de la tâche à laquelle ce formulaire est rattaché<br>- <code>object_id</code> - Identifiant de l’objet de l’entité<br>- <code>form_label</code> - Libellé de formulaire défini par l’utilisateur<br>- <code>champs</code> - Si vrai, le formulaire ne peut être soumis que dans la zone de la tâche<br>- <code>values</code> - Une carte avec les ID de champ comme clés et des objets field_value comme valeurs. Clé utilisée pour lier le champ et sa valeur correspondante<br>- <code>submitted_at</code> - Date de la dernière soumission des valeurs du formulaire<br>- <code>submission_latitude</code> - Lieu où les valeurs du formulaire ont été soumises pour la dernière fois<br>- <code>submission_longitude</code> - Lieu où les valeurs du formulaire ont été soumises pour la dernière fois<br>- <code>submission_address</code> - Lieu où les valeurs du formulaire ont été soumises pour la dernière fois<br>- <code>is_submission_in_zone</code> - Si vrai, le formulaire ne peut être soumis que dans la zone de la tâche<br>- <code>description</code> - Date de création de ce formulaire (ou de son rattachement à la tâche)<br>- <code>created_at</code> - Date de création de ce formulaire (ou de son rattachement à la tâche)</td></tr><tr><td><strong>Contenu</strong></td><td><code>champs</code> définit la structure du formulaire (JSON) ; <code>values</code> contient les données soumises (JSON)</td></tr><tr><td><strong>Relations</strong></td><td>Liens vers <code>tâches</code> (ordre de travail associé), <code>objects</code> (émetteur), référencé dans <code>checkins</code></td></tr><tr><td><strong>Notes spéciales</strong></td><td>Indicateur de validation de localisation <code>is_submission_in_zone</code> permet des règles de soumission de formulaires basées sur le géorepérage</td></tr></tbody></table>

</details>

<details>

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

**Description**: Enregistrements de présence et d’activité basés sur la localisation, envoyés via l’application mobile, suivant les heures d’arrivée prévues et réelles (planned\_datetime vs actual\_datetime) avec des coordonnées géographiques et des mesures de précision de localisation (radius) pour les rapports de ponctualité

<table><thead><tr><th width="129">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>checkin_id</code> - Identifiant de l’entité check-in<br>- <code>employee_id</code> - L’identifiant de l’entité employé est également l’identifiant des chauffeurs<br>- <code>object_id</code> - Appareil de l’employé<br>- <code>form_id</code> - Identifiant de l’entité formulaire<br>- <code>user_id</code> - Utilisateur employé<br>- <code>planned_datetime</code> - Heure de l’appareil lorsque le check-in a été effectué<br>- <code>actual_datetime</code> - Heure du serveur lorsque la requête/le message a été traité<br>- <code>latitude</code> - Lieu où les check-ins ont été soumis<br>- <code>longitude</code> - Lieu où les check-ins ont été soumis<br>- <code>radius</code> - Erreur de positionnement en un point, en mètres<br>- <code>address</code> - Adresse du check-in<br>- <code>comment</code> - L’attribut comment de la table checkins</td></tr><tr><td><strong>Relations</strong></td><td>Relie les employés aux formulaires et aux emplacements ; suit l’écart par rapport au planning prévu</td></tr><tr><td><strong>Notes spéciales</strong></td><td>Écart de temps entre <code>planned_datetime</code> et <code>actual_datetime</code> permet les rapports de ponctualité ; le radius définit la tolérance de localisation acceptable</td></tr></tbody></table>

</details>

<details>

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

**Description**: Piste d’audit complète des événements du cycle de vie des tâches capturant tous les changements de statut, affectations, mises à jour et modifications de champs avec horodatages (event\_datetime), attribution utilisateur et types d’activité (create, update, assign, status\_change) stockés dans le champ payload pour la conformité et l’analyse des flux de travail

<table><thead><tr><th width="137">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>task_history_id</code> - Identifiant de l’entité historique de tâche<br>- <code>task_id</code> - Identifiant de l’entité tâche<br>- <code>user_id</code> - Identifiant de l’entité utilisateur<br>- <code>activity</code> - Opération effectuée. Peut être "create", "update", "assign" ou "status_change"<br>- <code>event_datetime</code> - Date et heure de l’événement<br>- <code>payload</code> - Dépend de l’opération. Contient généralement les champs modifiés pendant l’opération</td></tr><tr><td><strong>Contenu</strong></td><td>Types d’activité définis dans <code>description_parameters</code>; <code>payload</code> stocke les détails spécifiques à l’événement (texte)</td></tr><tr><td><strong>Notes spéciales</strong></td><td>Essentiel pour l’analyse de l’exécution des tâches, les rapports de transition de statut et le suivi des activités utilisateur</td></tr></tbody></table>

</details>

Règles et automatisation

<details>

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

**Description**: Règles de détection d’événements avec conditions de déclenchement configurables (excès de vitesse, violations de géorepérage, seuils de capteurs, temps d’inactivité) stockées dans parameters (JSONB), et paramètres de notification multicanaux (alert\_email, alert\_sms, alert\_phone, is\_push\_enabled) pour la surveillance et les alertes automatisées basées sur les données de l’appareil et du serveur

<table><thead><tr><th width="131">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>rule_id</code> - Identifiant de l’entité règle<br>- <code>object_id</code> - Identifiant de l’objet de l’entité<br>- <code>client_id</code> - Identifiant de l’entité client<br>- <code>event_type</code> - L’attribut event_type de la table rules<br>- <code>event_label</code> - L’attribut event_label de la table rules<br>- <code>event_group</code> - L’attribut event_group de la table rules<br>- <code>description</code> - Attribut description de la table rules<br>- <code>parameters</code> - Paramètres de l’événement. Pour plus de détails sur les paramètres disponibles, voir <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> - E-mail pour les notifications<br>- <code>alert_sms</code> - Numéros de téléphone pour les notifications SMS<br>- <code>alert_phone</code> - Téléphones pour les appels vocaux<br>- <code>is_push_enabled</code> - Si vrai, les notifications push sont disponibles<br>- <code>created_at</code> - L’attribut created_at de la table rules<br>- <code>is_deleted</code> - L’attribut is_deleted de la table rules<br>- <code>maximum</code> - Limites appliquées à diverses règles. Par exemple, pour la règle de temps d’inactivité avec le moteur en marche, en minutes<br>- <code>event_comment1</code> - L’attribut event_comment1 de la table rules<br>- <code>event_comment2</code> - L’attribut event_comment2 de la table rules</td></tr><tr><td><strong>Contenu</strong></td><td>Les paramètres de la règle (JSONB) définissent les conditions de déclenchement ; prend en charge les notifications par e-mail, SMS, téléphone et push</td></tr><tr><td><strong>Relations</strong></td><td>Liens vers les objets via <code>rules2objects</code>, vers les zones via <code>rules2zones</code></td></tr><tr><td><strong>Notes spéciales</strong></td><td><code>event_type</code> définit un scénario de surveillance spécifique (excès de vitesse, violation de géorepérage, seuil de capteur) ; <code>maximum</code> le champ permet l’agrégation d’événements pour les alertes basées sur des seuils</td></tr></tbody></table>

</details>

<details>

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

**Description**: Relation plusieurs-à-plusieurs liant les règles aux objets surveillés avec personnalisation des paramètres par objet via object\_params (JSONB), permettant différentes valeurs de seuil (par exemple, les limites de vitesse) pour chaque véhicule ou actif au sein de la même règle

<table><thead><tr><th width="140">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>rule_id</code> - Identifiant de l’entité règle<br>- <code>object_id</code> - Identifiant de l’objet de l’entité<br>- <code>param_group_number</code> - L’attribut param_group_number de la table rules2objects<br>- <code>object_params</code> - L’attribut object_params de la table rules2objects</td></tr><tr><td><strong>Contenu</strong></td><td><code>object_params</code> (JSONB) permet la personnalisation des règles par objet (par exemple, des limites de vitesse différentes par véhicule)</td></tr><tr><td><strong>Notes spéciales</strong></td><td>La relation plusieurs-à-plusieurs permet à une règle de surveiller plusieurs objets avec des paramètres différents</td></tr></tbody></table>

</details>

<details>

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

**Description**: Relation plusieurs-à-plusieurs associant des règles à des zones géorepérées, permettant à une seule règle de surveiller les événements d’entrée/sortie dans plusieurs zones géographiques pour des scénarios de surveillance spatiale complexes

<table><thead><tr><th width="144">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>rule_id</code> - Identifiant de l’entité règle<br>- <code>zone_id</code> - Identifiant de l’entité zone</td></tr><tr><td><strong>Notes spéciales</strong></td><td>La relation plusieurs-à-plusieurs permet une surveillance multi-zone pour une seule règle (par exemple, alerte lors de l’entrée dans l’une de plusieurs zones restreintes)</td></tr></tbody></table>

</details>

Statut et catégorisation

<details>

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

**Description**: Définitions de statuts personnalisés dans les listes de statuts, y compris les propriétés d’affichage (color pour l’affichage sur le site web, order\_sort pour le positionnement) utilisées pour représenter les états de travail de l’appareil ou de l’employé, avec prise en charge de la suppression souple via l’indicateur is\_deleted

<table><thead><tr><th width="128">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>status_id</code> - Identifiant d’entité du statut<br>- <code>listing_id</code> - Identifiant de l’entité liste<br>- <code>status_label</code> - Valeur de statut de l’attribut status_label<br>- <code>color</code> - Couleur utilisée pour l’affichage sur le site web<br>- <code>order_sort</code> - Position de tri dans la liste des statuts<br>- <code>is_deleted</code> - L’attribut is_deleted de la table statuses</td></tr><tr><td><strong>Relations</strong></td><td>Groupes de statuts organisés par <code>listing_id</code> (références <code>status_listings</code>); utilisé dans <code>status_history</code></td></tr><tr><td><strong>Notes spéciales</strong></td><td><code>order_sort</code> définit l’ordre d’affichage ; la couleur permet une différenciation visuelle dans les rapports</td></tr></tbody></table>

</details>

<details>

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

**Description**: Définitions d’ensembles de statuts contrôlant quelles valeurs de statut sont disponibles pour les appareils ou les employés, avec des indicateurs d’autorisation (is\_supervisor\_controlled, is\_employee\_controlled) déterminant si les superviseurs, les employés ou les deux peuvent modifier les valeurs de statut

<table><thead><tr><th width="144">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>status_listing_id</code> - Identifiant de l’entité liste de statuts<br>- <code>user_id</code> - Identifiant de l’entité utilisateur<br>- <code>status_listing_label</code> - Valeur de statut de l’attribut status_listing_label<br>- <code>is_supervisor_controlled</code> - Si vrai, les superviseurs peuvent modifier le statut de travail, par exemple via l’application de suivi mobile<br>- <code>is_employee_controlled</code> - Si vrai, les employés peuvent modifier eux-mêmes leur statut de travail, par exemple via l’application de suivi mobile<br>- <code>is_deleted</code> - L’attribut is_deleted de la table status_listings</td></tr><tr><td><strong>Relations</strong></td><td>Référencé par <code>devices.status_listing_id</code> et <code>statuses.listing_id</code></td></tr><tr><td><strong>Notes spéciales</strong></td><td>Les indicateurs de contrôle déterminent qui peut modifier les statuts : superviseur uniquement, libre-service pour les employés ou les deux</td></tr></tbody></table>

</details>

<details>

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

**Description**: Piste d’audit de toutes les transitions de statut des appareils avec horodatages (changed\_datetime sur l’appareil, server\_datetime sur le serveur), attribution utilisateur (updated\_by) et capture de localisation (latitude, longitude, address) permettant l’analyse géographique des changements de statut et les rapports de localisation de début/fin de journée de travail

<table><thead><tr><th width="143">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>status_history_id</code> - Identifiant de l’entité historique des statuts<br>- <code>device_id</code> - Identifiant de l’entité appareil<br>- <code>old_status_id</code> - Identifiant de l’ancien statut<br>- <code>new_status_id</code> - Identifiant du nouveau statut<br>- <code>updated_by</code> - La date et l’heure associées à l’attribut updated_by<br>- <code>changed_datetime</code> - Date et heure d’attribution d’un nouveau statut sur l’appareil<br>- <code>server_datetime</code> - Date et heure d’attribution du nouveau statut sur le serveur<br>- <code>latitude</code> - Localisation des appareils lors des changements de statut<br>- <code>longitude</code> - Localisation des appareils lors des changements de statut<br>- <code>address</code> - Localisation des appareils lors des changements de statut</td></tr><tr><td><strong>Relations</strong></td><td>Liens vers <code>devices</code>, <code>statuses</code> (ancien et nouveau), <code>description_parameters</code> (pour <code>updated_by</code> rôle)</td></tr><tr><td><strong>Notes spéciales</strong></td><td>La capture de localisation permet l’analyse géographique des transitions de statut ; utile pour les rapports de localisation de début/fin de journée de travail</td></tr></tbody></table>

</details>

<details>

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

**Description**: Libellés de catégorisation définis par l’utilisateur avec codage couleur, permettant un filtrage et une recherche rapides sur plusieurs types d’entités (lieux, géorepérages, employés, tâches, traceurs, véhicules) pour une organisation flexible

<table><thead><tr><th width="149">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>tag_id</code> - ID de l’entité tag<br>- <code>user_id</code> - Identifiant de l’entité utilisateur<br>- <code>tag_label</code> - L’attribut tag_label de la table tags<br>- <code>color</code> - L’attribut color de la table tags</td></tr><tr><td><strong>Relations</strong></td><td>Appliqués aux entités via <code>tag_links</code>; périmètre défini par l’utilisateur</td></tr><tr><td><strong>Notes spéciales</strong></td><td>Système de catégorisation flexible prenant en charge plusieurs tags par entité</td></tr></tbody></table>

</details>

<details>

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

**Description**: Table de relation polymorphe associant des tags à tout type d’entité via entity\_type et entity\_id, avec un champ ordinal pour la gestion de l’ordre d’affichage, permettant un marquage flexible multi-entités

<table><thead><tr><th width="127">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>tag_id</code> - ID de l’entité tag<br>- <code>entity_type</code> - L’attribut entity_type de la table tag_links<br>- <code>entity_id</code> - Identifiant d’entité<br>- <code>ordinal</code> - L’attribut ordinal de la table tag_links</td></tr><tr><td><strong>Contenu</strong></td><td><code>entity_type</code> identifie la table (vehicle, employee, task, etc.) ; <code>ordinal</code> définit l’ordre d’affichage</td></tr><tr><td><strong>Notes spéciales</strong></td><td>La relation polymorphe permet le marquage à travers différents types d’entités</td></tr></tbody></table>

</details>

Groupes et hiérarchie

<details>

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

**Description**: Structure de regroupement organisationnel pour les traceurs permettant une organisation visuelle dans l’interface utilisateur avec des couleurs personnalisables (group\_color) et une gestion hiérarchique de type dossier, servant actuellement à une fonction purement visuelle

<table><thead><tr><th width="148">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>group_id</code> - Groupe de traceurs (lié par objects.group_id). La division en groupes peut être observée dans la liste des balises, par exemple<br>- <code>client_id</code> - Identifiant de l’entité client<br>- <code>group_label</code> - Titre de groupe défini par l’utilisateur, de 1 à 60 caractères imprimables, par exemple "Employees"<br>- <code>group_color</code> - Couleur du groupe au format web (sans #), par exemple "FF6DDC". Détermine la couleur des marqueurs des traceurs sur la carte</td></tr><tr><td><strong>Relations</strong></td><td>Référencé par <code>objects.group_id</code>; propriété client via <code>client_id</code> (références <code>users</code>)</td></tr><tr><td><strong>Notes spéciales</strong></td><td>Permet une organisation en dossiers des entités de surveillance pour le reporting et les permissions</td></tr></tbody></table>

</details>

<details>

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

**Description**: Relation plusieurs-à-plusieurs entre les groupes et les objets utilisant une clé primaire composite (groups\_client\_id, objects\_client\_id), permettant aux objets d’appartenir simultanément à plusieurs groupes pour des structures organisationnelles flexibles

<table><thead><tr><th width="135">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>groups_client_id</code> - Identifiant d’entité client pour les groupes<br>- <code>objects_client_id</code> - Identifiant d’entité client pour les objets</td></tr><tr><td><strong>Notes spéciales</strong></td><td>Permet aux objets d’appartenir simultanément à plusieurs groupes ; interroger avec les deux <code>client_id</code> valeurs pour l’appartenance au groupe</td></tr></tbody></table>

</details>

Champs personnalisés et entités

<details>

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

**Description**: Registre des types d’entités définissant quelles entités métier prennent en charge les champs personnalisés et la structure de leur disposition de champs (sections, field\_order) stockée dans entity\_label (JSONB), permettant l’extension dynamique du schéma pour les lieux, tâches et autres entités sans modification de la base de données

<table><thead><tr><th width="141">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>entity_id</code> - Identifiant d’entité<br>- <code>user_id</code> - Identifiant de l’entité utilisateur<br>- <code>entity_label</code> - id - int. Identifiant de l’entité. type - enum. Actuellement, seul "place" est pris en charge. layout - object décrit la disposition des champs pour l’entité. sections - array d’objects. Chaque section peut contenir un ou plusieurs champs. Au moins une section doit exister dans une disposition. label - string. Nom de la section. field_order - string array. Champs intégrés et ID des champs personnalisés (sous forme de chaînes)<br>- <code>builtin_type</code> - L’attribut builtin_type de la table entities</td></tr><tr><td><strong>Relations</strong></td><td>Référencé par <code>custom_fields</code> pour définir quels champs personnalisés s’appliquent à quels types d’entités</td></tr><tr><td><strong>Notes spéciales</strong></td><td><code>builtin_type</code> liens vers <code>description_parameters</code> pour les classifications d’entités définies par le système</td></tr></tbody></table>

</details>

<details>

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

**Description**: Définitions de champs personnalisés permettant l’extension dynamique du schéma pour les types d’entités, avec des types de champs configurables (custom\_field\_type), des règles de validation et des options dans parameters (JSONB), ainsi que des indicateurs d’obligation (is\_required) pour une capture de données flexible sur les lieux, tâches et autres entités

<table><thead><tr><th width="146">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>custom_field_id</code> - Identifiant de l’entité du champ personnalisé<br>- <code>entity_id</code> - Identifiant d’entité<br>- <code>custom_field_label</code> - Nom du champ<br>- <code>custom_field_type</code> - Type de données du champ<br>- <code>description</code> - Description du champ<br>- <code>is_required</code> - Ce champ est-il obligatoire ou non ?<br>- <code>parameters</code> - Paramètres du champ</td></tr><tr><td><strong>Contenu</strong></td><td><code>parameters</code> (JSONB) stocke la configuration spécifique au type de champ (règles de validation, options de liste déroulante, etc.)</td></tr><tr><td><strong>Relations</strong></td><td>Définit les attributs personnalisés disponibles pour les entités ; le type de champ est lié à <code>description_parameters</code></td></tr><tr><td><strong>Notes spéciales</strong></td><td>Permet l’extension dynamique du schéma sans modification de la base de données ; utilisé largement dans <code>lieux</code> et <code>tâches</code></td></tr></tbody></table>

</details>

Suivi historique

<details>

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

**Description**: Piste d’audit complète des affectations employé-véhicule au fil du temps, suivant les transitions de old\_employee\_id vers new\_employee\_id avec horodatages (changed\_datetime, server\_datetime), données de localisation (latitude, longitude, address), informations de clé matérielle et attribution utilisateur (updated\_by), permettant des analyses spécifiques aux conducteurs lorsque ceux-ci changent de véhicule

<table><thead><tr><th width="146">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>driver_history_id</code> - Identifiant de l’entité historique du conducteur<br>- <code>object_id</code> - Identifiant de l’objet de l’entité<br>- <code>old_employee_id</code> - Identifiant de l’ancien employé<br>- <code>new_employee_id</code> - Identifiant du nouvel employé<br>- <code>hardware_key</code> - L’attribut hardware_key de la table driver_history<br>- <code>changed_datetime</code> - Date et heure des modifications effectuées sur l’appareil<br>- <code>server_datetime</code> - Date et heure des modifications effectuées sur le serveur<br>- <code>updated_by</code> - La date et l’heure associées à l’attribut updated_by<br>- <code>latitude</code> - L’attribut latitude de la table driver_history<br>- <code>longitude</code> - L’attribut longitude de la table driver_history<br>- <code>address</code> - L’attribut address de la table driver_history</td></tr><tr><td><strong>Relations</strong></td><td>Suit les affectations des conducteurs aux véhicules au fil du temps ; lié à <code>employés</code> et <code>objects</code></td></tr><tr><td><strong>Notes spéciales</strong></td><td>Essentiel pour les rapports spécifiques aux conducteurs lorsque ceux-ci changent de véhicule ; la capture de localisation permet l’analyse du lieu des changements d’affectation</td></tr></tbody></table>

</details>

<details>

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

**Description**: Piste d’audit suivant quels appareils GPS (object\_id) ont été installés dans quels véhicules (vehicle\_id) au fil du temps avec horodatages des changements (changed\_datetime), permettant une attribution historique précise des données et le calcul du kilométrage lorsque les traceurs sont déplacés entre véhicules

<table><thead><tr><th width="144">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>vehicle_tracker_history_id</code> - Identifiant de l’entité historique du traceur de véhicule<br>- <code>vehicle_id</code> - Identifiant de l’entité véhicule<br>- <code>object_id</code> - Identifiant de l’objet de l’entité<br>- <code>changed_datetime</code> - La date et l’heure associées à l’attribut changed_datetime</td></tr><tr><td><strong>Relations</strong></td><td>Suit quel appareil GPS a été installé dans quel véhicule au fil du temps</td></tr><tr><td><strong>Notes spéciales</strong></td><td>Critique pour l’analyse historique des données lorsque les traceurs sont déplacés entre véhicules ; permet une attribution précise du kilométrage et de l’utilisation</td></tr></tbody></table>

</details>

Données de référence et de consultation

<details>

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

**Description**: Données de référence à l’échelle du système fournissant des libellés lisibles par l’humain (description) pour des valeurs entières énumérées (key) utilisées dans toute la base de données, organisées par le champ type (par exemple, task\_status, fuel\_type, counter\_type, entity\_classification) pour une traduction cohérente des valeurs dans les rapports et l’affichage de l’interface utilisateur

<table><thead><tr><th width="146">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>key</code> - Valeur possible dans l’attribut<br>- <code>type</code> - Attribut composite constitué du nom de la table suivi d’un underscore et du nom d’un attribut dans la table<br>- <code>description</code> - Valeur implicite d’un attribut</td></tr><tr><td><strong>Contenu</strong></td><td>Fournit des libellés lisibles par l’humain pour les valeurs codées dans toute la base de données (statut des tâches, types de carburant, types de compteurs, etc.)</td></tr><tr><td><strong>Relations</strong></td><td>Référencé via des clés étrangères depuis plusieurs tables pour une catégorisation standardisée</td></tr><tr><td><strong>Notes spéciales</strong></td><td>Essentiel pour convertir les codes entiers en valeurs lisibles dans les rapports ; <code>type</code> champs groupés et énumérations associées</td></tr></tbody></table>

</details>

<details>

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

**Description**: Configurations de compteur kilométrique et d’heures moteur reliant les lectures de capteurs de l’appareil (sensor\_id) aux mesures de distance ou de temps avec des coefficients multiplicateurs pour la conversion d’unités (km, miles, hours) et counter\_type provenant de description\_parameters définissant le type de mesure

<table><thead><tr><th width="140">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>counter_id</code> - ID interne<br>- <code>device_id</code> - Identifiant de l’entité appareil<br>- <code>counter_type</code> - Type de compteur<br>- <code>sensor_id</code> - Identifiant de l’entité capteur<br>- <code>multiplier</code> - Coefficient de conversion des valeurs vers l’une des unités de mesure (km, l, etc.)</td></tr><tr><td><strong>Relations</strong></td><td>Relie les appareils aux lectures de capteurs représentant des compteurs de distance ou de temps</td></tr><tr><td><strong>Notes spéciales</strong></td><td><code>multiplier</code> convertit les impulsions du capteur en unités réelles (km, miles, hours) ; <code>counter_type</code> from <code>description_parameters</code> définit le type de mesure</td></tr></tbody></table>

</details>

<details>

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

**Description**: Libellés personnalisés pour les canaux de sortie des appareils reliant les identifiants numériques de sortie (number) à des noms définis par l’utilisateur (label) tels que "Door Lock" ou "Engine Block" pour des rapports et analyses lisibles des commandes et états de sortie des appareils

<table><thead><tr><th width="140">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td>- <code>device_id</code> - Identifiant de l’entité appareil<br>- <code>number</code> - L’attribut number de la table device_output_name<br>- <code>label</code> - L’attribut label de la table device_output_name</td></tr><tr><td><strong>Contenu</strong></td><td>Associe les numéros de canal de sortie à des noms définis par l’utilisateur (par ex. "Door Lock", "Engine Block")</td></tr><tr><td><strong>Notes spéciales</strong></td><td>Permet des rapports lisibles lors de l’analyse des commandes et états de sortie des appareils</td></tr></tbody></table>

</details>

## `raw_telematics_data` structure

Le **`raw_telematics_data`** schéma contient trois types de tables principaux qui fonctionnent ensemble pour fournir des données complètes sur les appareils.

<figure><img src="https://504457471-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>Diagramme ERD des données télématiques brutes de la couche Bronze</p></figcaption></figure>

{% hint style="info" %}
Le diagramme interactif du schéma raw\_telematics\_data est disponible sur **dbdiagram.io**: <https://dbdiagram.io/d/v1-schema-telematics-bd-67a0acef263d6cf9a0d8e750>
{% endhint %}

Trouvez ci-dessous les détails du schéma des données télématiques brutes.

{% code title="schéma raw\_telematics\_data" expandable="true" %}

```sql
Table 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)}

}

  

Table 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)}

}

  

Table 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 %}

### Tables clés par catégorie

Chaque table sert un objectif spécifique dans la capture de différents aspects des informations de l’appareil :

<details>

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

**Objectif**: Données principales de localisation et de mouvement

<table><thead><tr><th width="181.20001220703125">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</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>Indexation</strong></td><td>Optimisé avec un index sur (<code>device_id</code>, <code>device_time</code>)</td></tr><tr><td><strong>Notes spéciales</strong></td><td>Les données de localisation (latitude et longitude) utilisent un format entier avec une précision de 10⁷ pour des performances optimales de TimescaleDB<br><br>La vitesse est également stockée en entier, vous devez donc la diviser par 100</td></tr></tbody></table>

</details>

<details>

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

**Objectif**: Lectures de capteurs provenant des appareils

<table><thead><tr><th width="182">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</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>Contenu</strong></td><td>Lectures analogiques (niveau de carburant, température, tension), valeurs calculées (régime moteur)</td></tr><tr><td><strong>Relations</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>

**Objectif**: Indicateurs d’état et modes de fonctionnement de l’appareil

<table><thead><tr><th width="174.800048828125">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</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>Contenu</strong></td><td>Indicateurs de mode de fonctionnement (working, idle, off), états des composants (ignition, doors)</td></tr><tr><td><strong>Format de valeur</strong></td><td>Valeurs booléennes (1/0) ou codes d’état spécifiques</td></tr></tbody></table>

</details>

Les données de ce schéma sont ingérées directement depuis les appareils, avec une latence minimale (généralement de quelques secondes). Le schéma est optimisé pour les données de séries temporelles en utilisant TimescaleDB pour un stockage et une récupération efficaces.

## Informations supplémentaires

### Validation des données

La base de données garantit l’intégrité des données grâce à plusieurs mécanismes :

* **Contraintes CHECK** valident que les valeurs se situent dans des plages acceptables
* **Clés étrangères** garantissent que les relations entre les tables restent cohérentes
* **Contraintes NOT NULL** garantissent que les champs obligatoires ont toujours des valeurs
* **Valeurs DEFAULT** fournissent une valeur de repli lorsque les données ne sont pas fournies explicitement

### Optimisation des requêtes

Les tables sont organisées selon des stratégies d’indexation spécifiques :

* Toutes les tables incluent **des index basés sur le temps** sur `record_added_at`
* Les colonnes de clés étrangères disposent d’index dédiés pour optimiser les jointures
* Les combinaisons de colonnes fréquemment utilisées disposent de **index composites**
* TimescaleDB fournit des index spécialisés pour les requêtes sur les séries temporelles

## `repo` structure des données

{% hint style="warning" %}
**Ce schéma est actuellement en cours de développement.** Si vous êtes intéressé par un accès anticipé ou si vous avez des questions sur cette fonctionnalité, veuillez contacter <iotquery@navixy.com>.
{% endhint %}

Le `repo` Le schéma fournit un cadre complet pour la gestion des structures organisationnelles, des actifs, des appareils et de leurs relations dans des environnements multitenants. Construit sur PostgreSQL 14+ avec l’extension ltree, le schéma prend en charge les organisations hiérarchiques, les définitions de champs personnalisés pour tout type d’entité, le contrôle d’accès basé sur les rôles avec des restrictions au niveau des objets, ainsi que des journaux d’audit complets avec suivi des modifications au niveau des champs. Toutes les entités peuvent être étendues sans modification du schéma, localisées pour les déploiements internationaux et reliées par des relations polymorphes flexibles.

Le schéma répond à des scénarios complexes de gestion des données, notamment les hiérarchies d’actifs de flotte à travers plusieurs niveaux organisationnels, les plateformes SaaS multitenantes nécessitant une isolation des données, les opérations soumises à la conformité avec des exigences détaillées d’audit, ainsi que les systèmes nécessitant des modèles de données dynamiques adaptables via des champs personnalisés plutôt que par des migrations de base de données.

<figure><img src="https://504457471-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" %}
Le diagramme interactif de`repo` la structure de données est disponible sur **dbdiagram.io**: <https://dbdiagram.io/d/Navixy-Repo-data-schema-68ad788c1e7a611967a0930e>
{% endhint %}

Trouvez les `repo` détails du schéma ci-dessous.

{% code title="schéma de données du repo" expandable="true" %}

```sql
// ============================================
// Nouveau schéma DataHub - Parcours client
// PostgreSQL 14+ avec l’extension ltree
// Version : 2.0 (Concept)
// ============================================

// ============================================
// TABLES DE RÉFÉRENCE DE BASE (hiérarchie 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
}

// ============================================
// ENTITÉ DE BASE AVEC PRISE EN CHARGE DES CHAMPS PERSONNALISÉS
// ============================================

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']
  }
}

// ============================================
// ENTITÉS MÉTIER PRINCIPALES
// ============================================

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']
  }
}

// ============================================
// CONTRÔLE D’ACCÈS (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']
  }
}

// ============================================
// ENTITÉS MÉTIER
// ============================================

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']
  }
}

// ============================================
// LOCALISATION
// ============================================

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']
  }
}

// ============================================
// CHAMPS PERSONNALISÉS - DÉFINITIONS
// ============================================

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']
  }
}

// ============================================
// CHAMPS PERSONNALISÉS - VALEURS (par type)
// ============================================

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']
  }
}

// ============================================
// AUDIT
// ============================================

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']
  }
}

// ============================================
// RELATIONS
// ============================================

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 %}

### Fréquence de mise à jour

Les données du `repo` schéma sont synchronisées en temps réel avec les systèmes sources. Les mises à jour se produisent immédiatement au fur et à mesure des changements, et les pistes d’audit capturent toutes les modifications à des fins de conformité et d’analyse historique.

### `ci_base`

Le `repo` Le schéma utilise un modèle Single Table Inheritance pour toutes les données de référence via la `ci_base` table :

Le `repo` Le schéma utilise un **modèle Single Table Inheritance** pour toutes les données de référence via la `ci_base` table. Cette conception regroupe les dictionnaires système, les classifications et les éléments de référence définis par l’utilisateur dans une structure unifiée, offrant cohérence et flexibilité sur l’ensemble du schéma.

**Architecture :**

Le `ci_base` La table sert de base à toutes les données de référence, en utilisant un champ `discriminator` pour identifier le type de référence spécifique. Chaque type de référence possède une table correspondante (comme `ci_device_type`, `ci_asset_type`) qui partage le même `id` que `ci_base`, créant ainsi une relation d’héritage de type sûr.

**Comment les entités métier se connectent à ci\_base :**

Toutes les entités métier dans le `repo` schéma référencent `ci_base` des sous-types pour définir leur classification et leur comportement :

* `organization` → référence `ci_organization_type` (qui hérite de `ci_entity_type` → `ci_base`)
* `user` → référence `ci_user_type` (qui hérite de `ci_entity_type` → `ci_base`)
* `device` → référence `ci_device_type` et `ci_device_status` (tous deux héritent de `ci_base`)
* `asset` → référence `ci_asset_type` (qui hérite de `ci_entity_type` → `ci_base`)
* `inventory` → référence `ci_inventory_type` (qui hérite de `ci_entity_type` → `ci_base`)
* `asset_group` → référence `ci_asset_group_type` (qui hérite de `ci_entity_type` → `ci_base`)

**Catégories de types de référence :**

| Catégorie                          | Tables                                                                                                                                  | Objectif                                                                                          |
| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| **Configuration système**          | `ci_module`, `ci_country`, `ci_role`                                                                                                    | Définir les modules système, les références géographiques et les rôles des utilisateurs           |
| **Définitions des types d’entité** | `ci_entity_type`, `ci_device_type`, `ci_asset_type`, `ci_inventory_type`, `ci_organization_type`, `ci_user_type`, `ci_asset_group_type` | Classer toutes les entités métier par type                                                        |
| **Statut et classification**       | `ci_device_status`, `ci_asset_type_category`                                                                                            | Suivre les états des entités et regrouper les types en catégories                                 |
| **Contrôle d’accès**               | `ci_permission_scope`                                                                                                                   | Définissez quelles autorisations peuvent être accordées (liées à `ci_module` et `ci_entity_type`) |
| **Relations**                      | `ci_device_relation_type`                                                                                                               | Définissez les types de relations entre appareils (maître-esclave, secours, etc.)                 |
| **Catégorisation**                 | `ci_tag`, `ci_catalog_category`                                                                                                         | Permet un étiquetage flexible et une organisation du catalogue                                    |

<details>

<summary><strong>Exemples de modèles de requêtes</strong></summary>

```sql
-- Obtenir tous les types d’appareils d’une organisation (système + personnalisé)
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;

-- Obtenir le type d’actif avec sa catégorie
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;

-- Obtenir la structure hiérarchique des balises
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>

### Tables clés par catégorie

Les tables du `repo` Le schéma est organisé en catégories fonctionnelles. Les descriptions ci-dessous résument les tables les plus importantes selon leur finalité métier.

<details>

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

**Finalité :** Gestion hiérarchique de l’organisation

<table><thead><tr><th width="139">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</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>Indexation</strong></td><td>Index GiST sur <code>path</code> pour les requêtes hiérarchiques, index sur <code>parent_id</code> et <code>organization_type_id</code></td></tr><tr><td><strong>Notes spéciales</strong></td><td>Utilise ltree pour les hiérarchies multiniveaux, hérite de <code>customizable_entity</code> pour la prise en charge des champs personnalisés</td></tr></tbody></table>

</details>

<details>

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

**Finalité :** Comptes utilisateurs et authentification

<table><thead><tr><th width="139">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</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>Indexation</strong></td><td>Index unique sur (<code>organization_id</code>, <code>identity_provider</code>, <code>identity_provider_id</code>)</td></tr><tr><td><strong>Notes spéciales</strong></td><td>Intégration d’un fournisseur d’identité externe (Keycloak, Auth0, Okta), hérite de <code>customizable_entity</code></td></tr></tbody></table>

</details>

<details>

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

**Finalité :** Appareils de suivi physiques

<table><thead><tr><th width="139">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</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>Indexation</strong></td><td>Index sur <code>organization_id</code>, <code>device_type_id</code>, <code>status_id</code>, <code>hw_id</code></td></tr><tr><td><strong>Notes spéciales</strong></td><td>Identifiant matériel pour le suivi de l’appareil, hérite de <code>customizable_entity</code> pour les champs personnalisés</td></tr></tbody></table>

</details>

<details>

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

**Finalité :** Actifs physiques ou virtuels

<table><thead><tr><th width="139">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</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>Indexation</strong></td><td>Index sur <code>organization_id</code> et <code>asset_type_id</code></td></tr><tr><td><strong>Notes spéciales</strong></td><td>Hérite de <code>customizable_entity</code>, lié aux appareils via <code>device_asset_link</code></td></tr></tbody></table>

</details>

<details>

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

**Finalité :** Inventaire et enregistrements d’entrepôt

<table><thead><tr><th width="139">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</strong></td><td><code>id</code>, <code>organization_id</code>, <code>inventory_type_id</code>, <code>code</code></td></tr><tr><td><strong>Indexation</strong></td><td>Index unique sur (<code>organization_id</code>, <code>code</code>)</td></tr><tr><td><strong>Notes spéciales</strong></td><td>Codes uniques au sein de l’organisation, liés aux appareils via <code>device_inventory_link</code></td></tr></tbody></table>

</details>

<details>

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

**Finalité :** Regroupement d’actifs avec suivi historique

<table><thead><tr><th width="139">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</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>Relations</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>Notes spéciales</strong></td><td>Appartenance basée sur le temps via <code>asset_group_item</code>, interrogez les membres actuels avec <code>WHERE detached_at IS NULL</code></td></tr></tbody></table>

</details>

<details>

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

**Finalité :** Définitions et métadonnées des champs personnalisés

<table><thead><tr><th width="139">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</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>Contenu</strong></td><td>Les types de champs incluent texte, nombre, booléen, date, datetime, entity_ref, catalog_item_ref</td></tr><tr><td><strong>Notes spéciales</strong></td><td>Permet des champs personnalisés flexibles pour tout type d’entité, les valeurs étant stockées dans des tables spécifiques au type <code>custom_field_value_*</code> tables</td></tr></tbody></table>

</details>

<details>

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

**Finalité :** Gestion des autorisations basée sur les rôles

<table><thead><tr><th width="139">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</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>Contenu</strong></td><td>Masque de bits d’action (READ=1, UPDATE=2, DELETE=4, CREATE=8), autorisations spécifiques à la cible ou à l’ensemble du type d’entité</td></tr><tr><td><strong>Relations</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>Notes spéciales</strong></td><td>Fonctionne avec <code>user_role</code> et <code>acl_user_scope</code> pour déterminer les autorisations finales de l’utilisateur</td></tr></tbody></table>

</details>

<details>

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

**Finalité :** Journal d’audit unifié pour toutes les modifications du système

<table><thead><tr><th width="139">Attribut</th><th>Détails</th></tr></thead><tbody><tr><td><strong>Champs clés</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>Indexation</strong></td><td>Index sur (<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>Notes spéciales</strong></td><td>Partitionné par <code>occurred_at</code> (mensuellement), deux catégories : <code>auth</code> (authentification) et <code>domain</code> (événements métier), stocke les écarts de modification au niveau des champs dans <code>event_data</code> JSONB</td></tr></tbody></table>

</details>

### Relations de données

Le `repo` Le schéma met en œuvre des modèles de relations sophistiqués pour une modélisation de données flexible :

**Structures hiérarchiques**

* Les organisations utilisent des chemins ltree pour des requêtes d’arborescence efficaces
* Les éléments de référence (`ci_base`) prennent en charge des hiérarchies optionnelles
* Maintenance automatique des chemins via des déclencheurs de base de données

**Modèles d’héritage**

* Héritage de table : `customizable_entity` → entités métier (`organization`, `user`, `device`, `asset`, `inventory`, `asset_group`)
* Héritage d’ID : `ci_base` → tables de types de référence
* Discrimination de type via `entity_type_id` et `discriminator` champs

**Relations polymorphes**

Certaines tables utilisent des références polymorphes sans contraintes de clé étrangère pour une flexibilité maximale :

* `acl_role_permission.target_entity_id` → n’importe quel `customizable_entity`
* `acl_user_scope.target_entity_id` → n’importe quel `customizable_entity`
* `entity_tag.entity_id` → n’importe quel `customizable_entity`

Ces relations sont validées au niveau de l’application.

### Informations supplémentaires

#### Validation des données

Le `repo` Le schéma impose l’intégrité des données par plusieurs mécanismes :

**Contraintes de base de données**

* Contraintes UNIQUE avec prise en charge de la suppression logique (index partiels WHERE `deleted_at` IS NULL)
* Contraintes CHECK (par ex., `device_relation` garantit `master_id` ≠ `slave_id`)
* Contraintes NOT NULL sur les champs obligatoires
* Valeurs DEFAULT pour les horodatages et les indicateurs booléens

**Validation au niveau de l’application**

* Validation du type d’entité pour les références polymorphes
* Validation du catalogue pour les références de champs personnalisés
* Validation du type de champ personnalisé
* Gestion des tableaux de champs à valeurs multiples

#### Optimisation des requêtes

Les tables sont organisées selon des stratégies d’indexation spécifiques :

**Index standard :**

* Toutes les clés étrangères disposent d’index dédiés
* Index temporels sur `created_at`, `updated_at`, `deleted_at`
* Index composites pour les colonnes fréquemment jointes

**Index spécialisés :**

* Index GiST sur les chemins ltree pour les requêtes hiérarchiques
* Index uniques partiels prenant en charge la suppression logique
* Index des valeurs de champs personnalisés pour le filtrage et le tri
* Index des événements d’audit sur le temps + l’entité pour des recherches efficaces

**Considérations de performance :**

* Regroupement de connexions recommandé (PgBouncer)
* Maintenance VACUUM régulière pour les grandes tables
* Partitionnement futur possible pour `device` table par `organization_id`
* Vues matérialisées pour les calculs complexes de contrôle d’accès
