107 lines
4.7 KiB
SQL
107 lines
4.7 KiB
SQL
-- GPS-мониторинг: объекты (транспорт/люди), треки, геозоны, события, группы, подписки.
|
||
-- Интеграция с Traccar (forward позиций на /api/gps/ingest) и приём геолокации из PWA.
|
||
|
||
-- Объекты мониторинга (машины, люди с трекерами)
|
||
CREATE TABLE IF NOT EXISTS gps_assets (
|
||
id SERIAL PRIMARY KEY,
|
||
organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||
name TEXT NOT NULL,
|
||
type TEXT NOT NULL DEFAULT 'vehicle',
|
||
user_id INTEGER REFERENCES users(id),
|
||
external_id TEXT,
|
||
color TEXT DEFAULT '#3b82f6',
|
||
is_active BOOLEAN DEFAULT TRUE,
|
||
is_online BOOLEAN DEFAULT FALSE,
|
||
last_lat DOUBLE PRECISION,
|
||
last_lng DOUBLE PRECISION,
|
||
last_speed DOUBLE PRECISION,
|
||
last_course DOUBLE PRECISION,
|
||
last_seen_at TIMESTAMP,
|
||
created_at TIMESTAMP DEFAULT NOW()
|
||
);
|
||
CREATE INDEX IF NOT EXISTS gps_assets_org_idx ON gps_assets(organization_id);
|
||
-- IMEI/идентификатор трекера уникален в рамках организации (только для заполненных)
|
||
CREATE UNIQUE INDEX IF NOT EXISTS gps_assets_org_external_idx
|
||
ON gps_assets(organization_id, external_id) WHERE external_id IS NOT NULL;
|
||
CREATE INDEX IF NOT EXISTS gps_assets_user_idx ON gps_assets(user_id);
|
||
|
||
-- История позиций (треки)
|
||
CREATE TABLE IF NOT EXISTS gps_positions (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
asset_id INTEGER NOT NULL REFERENCES gps_assets(id) ON DELETE CASCADE,
|
||
organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||
lat DOUBLE PRECISION NOT NULL,
|
||
lng DOUBLE PRECISION NOT NULL,
|
||
speed DOUBLE PRECISION,
|
||
course DOUBLE PRECISION,
|
||
accuracy DOUBLE PRECISION,
|
||
recorded_at TIMESTAMP NOT NULL,
|
||
created_at TIMESTAMP DEFAULT NOW()
|
||
);
|
||
CREATE INDEX IF NOT EXISTS gps_positions_asset_recorded_idx ON gps_positions(asset_id, recorded_at);
|
||
CREATE INDEX IF NOT EXISTS gps_positions_org_recorded_idx ON gps_positions(organization_id, recorded_at);
|
||
|
||
-- Геозоны (полигоны)
|
||
CREATE TABLE IF NOT EXISTS gps_geozones (
|
||
id SERIAL PRIMARY KEY,
|
||
organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||
name TEXT NOT NULL,
|
||
polygon JSONB NOT NULL,
|
||
color TEXT DEFAULT '#f59e0b',
|
||
notify_enter BOOLEAN DEFAULT TRUE,
|
||
notify_exit BOOLEAN DEFAULT TRUE,
|
||
is_active BOOLEAN DEFAULT TRUE,
|
||
created_at TIMESTAMP DEFAULT NOW()
|
||
);
|
||
CREATE INDEX IF NOT EXISTS gps_geozones_org_idx ON gps_geozones(organization_id);
|
||
|
||
-- События входа/выхода из геозон
|
||
CREATE TABLE IF NOT EXISTS gps_geozone_events (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||
geozone_id INTEGER NOT NULL REFERENCES gps_geozones(id) ON DELETE CASCADE,
|
||
asset_id INTEGER NOT NULL REFERENCES gps_assets(id) ON DELETE CASCADE,
|
||
event TEXT NOT NULL,
|
||
lat DOUBLE PRECISION,
|
||
lng DOUBLE PRECISION,
|
||
created_at TIMESTAMP DEFAULT NOW()
|
||
);
|
||
CREATE INDEX IF NOT EXISTS gps_geozone_events_asset_idx ON gps_geozone_events(asset_id, created_at);
|
||
CREATE INDEX IF NOT EXISTS gps_geozone_events_org_idx ON gps_geozone_events(organization_id, created_at);
|
||
|
||
-- Текущее состояние «объект внутри геозоны» (для детекта входа/выхода)
|
||
CREATE TABLE IF NOT EXISTS gps_geozone_states (
|
||
asset_id INTEGER NOT NULL REFERENCES gps_assets(id) ON DELETE CASCADE,
|
||
geozone_id INTEGER NOT NULL REFERENCES gps_geozones(id) ON DELETE CASCADE,
|
||
inside BOOLEAN NOT NULL,
|
||
updated_at TIMESTAMP DEFAULT NOW(),
|
||
PRIMARY KEY (asset_id, geozone_id)
|
||
);
|
||
|
||
-- Группы объектов (для фильтров на карте)
|
||
CREATE TABLE IF NOT EXISTS gps_groups (
|
||
id SERIAL PRIMARY KEY,
|
||
organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||
name TEXT NOT NULL,
|
||
created_at TIMESTAMP DEFAULT NOW()
|
||
);
|
||
CREATE INDEX IF NOT EXISTS gps_groups_org_idx ON gps_groups(organization_id);
|
||
|
||
-- Связь групп и объектов (многие-ко-многим)
|
||
CREATE TABLE IF NOT EXISTS gps_group_assets (
|
||
group_id INTEGER NOT NULL REFERENCES gps_groups(id) ON DELETE CASCADE,
|
||
asset_id INTEGER NOT NULL REFERENCES gps_assets(id) ON DELETE CASCADE,
|
||
PRIMARY KEY (group_id, asset_id)
|
||
);
|
||
|
||
-- Подписчики на события объекта (уведомления о входе/выходе/офлайне)
|
||
CREATE TABLE IF NOT EXISTS gps_asset_subscribers (
|
||
id SERIAL PRIMARY KEY,
|
||
asset_id INTEGER NOT NULL REFERENCES gps_assets(id) ON DELETE CASCADE,
|
||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||
on_enter BOOLEAN DEFAULT TRUE,
|
||
on_exit BOOLEAN DEFAULT TRUE,
|
||
on_offline BOOLEAN DEFAULT FALSE,
|
||
UNIQUE (asset_id, user_id)
|
||
);
|