Primo schema DB
This commit is contained in:
@@ -3,6 +3,9 @@
|
|||||||
__pycache__/
|
__pycache__/
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
*$py.class
|
*$py.class
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
.env
|
||||||
|
|
||||||
# C extensions
|
# C extensions
|
||||||
*.so
|
*.so
|
||||||
|
|||||||
@@ -0,0 +1,350 @@
|
|||||||
|
"""schema iniziale
|
||||||
|
|
||||||
|
Revision ID: 0001
|
||||||
|
Revises:
|
||||||
|
Create Date: 2026-04-28 12:40:08.000000
|
||||||
|
|
||||||
|
"""
|
||||||
|
from typing import Sequence, Union
|
||||||
|
from alembic import op
|
||||||
|
|
||||||
|
revision: str = "0001"
|
||||||
|
down_revision: Union[str, None] = None
|
||||||
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
op.execute("""
|
||||||
|
DO $$ BEGIN
|
||||||
|
CREATE TYPE userrole AS ENUM ('venditore','valutatore','backoffice','operatore_perizie','approvatore_perizie','admin');
|
||||||
|
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||||
|
|
||||||
|
DO $$ BEGIN
|
||||||
|
CREATE TYPE valuationstatus AS ENUM ('bozza','inviata','in_lavorazione','completata','vinta','persa');
|
||||||
|
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||||
|
|
||||||
|
DO $$ BEGIN
|
||||||
|
CREATE TYPE valuationpriority AS ENUM ('contratto','preventivo','valutazione');
|
||||||
|
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||||
|
|
||||||
|
DO $$ BEGIN
|
||||||
|
CREATE TYPE retakeregime AS ENUM ('nuovo','usato');
|
||||||
|
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||||
|
|
||||||
|
DO $$ BEGIN
|
||||||
|
CREATE TYPE repairstatus AS ENUM ('bozza','inviata','in_approvazione','approvata','rifiutata','chiusa');
|
||||||
|
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||||
|
|
||||||
|
DO $$ BEGIN
|
||||||
|
CREATE TYPE repairdestination AS ENUM ('vendita','rottamazione','altro');
|
||||||
|
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||||
|
|
||||||
|
DO $$ BEGIN
|
||||||
|
CREATE TYPE offerstatus AS ENUM ('in_attesa','accettata','rifiutata');
|
||||||
|
EXCEPTION WHEN duplicate_object THEN NULL; END $$;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS groups (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
name VARCHAR(100) NOT NULL,
|
||||||
|
description VARCHAR(255),
|
||||||
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
email VARCHAR(255) NOT NULL UNIQUE,
|
||||||
|
full_name VARCHAR(200) NOT NULL,
|
||||||
|
hashed_password VARCHAR(255) NOT NULL,
|
||||||
|
role userrole NOT NULL,
|
||||||
|
group_id INTEGER REFERENCES groups(id),
|
||||||
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
notify_email BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
notify_push BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||||
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
CREATE INDEX IF NOT EXISTS ix_users_email ON users (email);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS vehicle_registry (
|
||||||
|
plate VARCHAR(10) PRIMARY KEY,
|
||||||
|
vin VARCHAR(17),
|
||||||
|
vehicle_type VARCHAR(50),
|
||||||
|
registration_date DATE,
|
||||||
|
homologation_code VARCHAR(50),
|
||||||
|
engine_code VARCHAR(20),
|
||||||
|
last_revision_date DATE,
|
||||||
|
foreign_plate VARCHAR(20),
|
||||||
|
foreign_registration_date DATE,
|
||||||
|
foreign_country VARCHAR(50),
|
||||||
|
is_foreign_registered BOOLEAN,
|
||||||
|
source VARCHAR(20),
|
||||||
|
raw_response JSONB,
|
||||||
|
fetched_at TIMESTAMPTZ,
|
||||||
|
expires_at TIMESTAMPTZ,
|
||||||
|
selected_motornet_code VARCHAR(20)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS vehicle_versions (
|
||||||
|
motornet_code VARCHAR(20) PRIMARY KEY,
|
||||||
|
brand_acronym VARCHAR(10),
|
||||||
|
brand_name VARCHAR(50),
|
||||||
|
model_code VARCHAR(10),
|
||||||
|
model_description VARCHAR(100),
|
||||||
|
gamma_code VARCHAR(10),
|
||||||
|
gamma_description VARCHAR(100),
|
||||||
|
series_code VARCHAR(10),
|
||||||
|
series_description VARCHAR(100),
|
||||||
|
historical_group_code VARCHAR(10),
|
||||||
|
historical_group_desc VARCHAR(100),
|
||||||
|
cod_desc_model_code VARCHAR(10),
|
||||||
|
cod_desc_model_desc VARCHAR(100),
|
||||||
|
version_label VARCHAR(200),
|
||||||
|
body_type VARCHAR(10),
|
||||||
|
doors SMALLINT,
|
||||||
|
wheelbase SMALLINT,
|
||||||
|
list_price NUMERIC(10,2),
|
||||||
|
production_start DATE,
|
||||||
|
production_end DATE,
|
||||||
|
commercial_start DATE,
|
||||||
|
commercial_end DATE,
|
||||||
|
first_seen_at TIMESTAMPTZ,
|
||||||
|
last_seen_at TIMESTAMPTZ,
|
||||||
|
seen_count INTEGER NOT NULL DEFAULT 1,
|
||||||
|
source VARCHAR(20)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS plate_version_candidates (
|
||||||
|
plate VARCHAR(10) REFERENCES vehicle_registry(plate),
|
||||||
|
motornet_code VARCHAR(20) REFERENCES vehicle_versions(motornet_code),
|
||||||
|
is_selected BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
PRIMARY KEY (plate, motornet_code)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS api_usage_log (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
source VARCHAR(20),
|
||||||
|
plate VARCHAR(10),
|
||||||
|
hit_cache BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
remaining_queries INTEGER,
|
||||||
|
called_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS valuations (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
plate VARCHAR(10) NOT NULL REFERENCES vehicle_registry(plate),
|
||||||
|
user_id INTEGER NOT NULL REFERENCES users(id),
|
||||||
|
group_id INTEGER REFERENCES groups(id),
|
||||||
|
motornet_code VARCHAR(20) REFERENCES vehicle_versions(motornet_code),
|
||||||
|
mileage INTEGER,
|
||||||
|
retake_regime retakeregime,
|
||||||
|
expected_return_date DATE,
|
||||||
|
interest_fuel VARCHAR(50),
|
||||||
|
priority valuationpriority NOT NULL DEFAULT 'valutazione',
|
||||||
|
notes TEXT,
|
||||||
|
status valuationstatus NOT NULL DEFAULT 'bozza',
|
||||||
|
final_value NUMERIC(10,2),
|
||||||
|
evaluator_id INTEGER REFERENCES users(id),
|
||||||
|
evaluator_notes TEXT,
|
||||||
|
is_frozen BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
priority_rank INTEGER NOT NULL DEFAULT 3,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||||
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
CREATE INDEX IF NOT EXISTS ix_valuations_plate ON valuations (plate);
|
||||||
|
CREATE INDEX IF NOT EXISTS ix_valuations_status ON valuations (status);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS valuation_photos (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
valuation_id INTEGER NOT NULL REFERENCES valuations(id),
|
||||||
|
filename VARCHAR(255) NOT NULL,
|
||||||
|
storage_path VARCHAR(500) NOT NULL,
|
||||||
|
uploaded_by INTEGER NOT NULL REFERENCES users(id),
|
||||||
|
uploaded_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS valuation_comments (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
valuation_id INTEGER NOT NULL REFERENCES valuations(id),
|
||||||
|
user_id INTEGER NOT NULL REFERENCES users(id),
|
||||||
|
content TEXT NOT NULL,
|
||||||
|
visible_to_all BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS valuation_history (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
valuation_id INTEGER NOT NULL REFERENCES valuations(id),
|
||||||
|
changed_by INTEGER NOT NULL REFERENCES users(id),
|
||||||
|
field_name VARCHAR(100) NOT NULL,
|
||||||
|
old_value TEXT,
|
||||||
|
new_value TEXT,
|
||||||
|
changed_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS contracts (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
contract_number VARCHAR(50) NOT NULL,
|
||||||
|
year INTEGER NOT NULL,
|
||||||
|
company VARCHAR(100) NOT NULL,
|
||||||
|
area VARCHAR(100),
|
||||||
|
plate VARCHAR(10),
|
||||||
|
customer_name VARCHAR(200),
|
||||||
|
import_batch VARCHAR(100),
|
||||||
|
imported_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS valuation_contracts (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
valuation_id INTEGER NOT NULL REFERENCES valuations(id),
|
||||||
|
contract_id INTEGER NOT NULL REFERENCES contracts(id),
|
||||||
|
linked_by INTEGER NOT NULL REFERENCES users(id),
|
||||||
|
linked_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS repairs (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
plate VARCHAR(10) NOT NULL REFERENCES vehicle_registry(plate),
|
||||||
|
company VARCHAR(100),
|
||||||
|
infinity_repair_number VARCHAR(50),
|
||||||
|
intervention_type VARCHAR(100),
|
||||||
|
delivery_location VARCHAR(100),
|
||||||
|
group_id INTEGER REFERENCES groups(id),
|
||||||
|
created_by INTEGER NOT NULL REFERENCES users(id),
|
||||||
|
status repairstatus NOT NULL DEFAULT 'bozza',
|
||||||
|
destination repairdestination,
|
||||||
|
offer_status offerstatus,
|
||||||
|
estimated_value NUMERIC(10,2),
|
||||||
|
actual_value NUMERIC(10,2),
|
||||||
|
subtotal NUMERIC(10,2),
|
||||||
|
notes TEXT,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||||
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
CREATE INDEX IF NOT EXISTS ix_repairs_plate ON repairs (plate);
|
||||||
|
CREATE INDEX IF NOT EXISTS ix_repairs_status ON repairs (status);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS repair_documents (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
repair_id INTEGER NOT NULL REFERENCES repairs(id),
|
||||||
|
filename VARCHAR(255) NOT NULL,
|
||||||
|
storage_path VARCHAR(500) NOT NULL,
|
||||||
|
uploaded_by INTEGER NOT NULL REFERENCES users(id),
|
||||||
|
uploaded_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS repair_comments (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
repair_id INTEGER NOT NULL REFERENCES repairs(id),
|
||||||
|
user_id INTEGER NOT NULL REFERENCES users(id),
|
||||||
|
content TEXT NOT NULL,
|
||||||
|
mentions TEXT,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS repair_history (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
repair_id INTEGER NOT NULL REFERENCES repairs(id),
|
||||||
|
changed_by INTEGER NOT NULL REFERENCES users(id),
|
||||||
|
field_name VARCHAR(100) NOT NULL,
|
||||||
|
old_value TEXT,
|
||||||
|
new_value TEXT,
|
||||||
|
changed_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS notifications (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
user_id INTEGER NOT NULL REFERENCES users(id),
|
||||||
|
title VARCHAR(200) NOT NULL,
|
||||||
|
body TEXT,
|
||||||
|
link VARCHAR(500),
|
||||||
|
is_read BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS alert_config (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
key VARCHAR(100) NOT NULL UNIQUE,
|
||||||
|
value VARCHAR(255) NOT NULL,
|
||||||
|
description VARCHAR(500),
|
||||||
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS vehicle_stock (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
plate VARCHAR(10) NOT NULL,
|
||||||
|
brand VARCHAR(50),
|
||||||
|
model VARCHAR(100),
|
||||||
|
version VARCHAR(200),
|
||||||
|
registration_date VARCHAR(20),
|
||||||
|
mileage INTEGER,
|
||||||
|
location VARCHAR(100),
|
||||||
|
import_batch VARCHAR(100),
|
||||||
|
imported_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
CREATE INDEX IF NOT EXISTS ix_vehicle_stock_plate ON vehicle_stock (plate);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS repair_costs_avg (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
model VARCHAR(100) NOT NULL,
|
||||||
|
avg_cost NUMERIC(10,2),
|
||||||
|
import_batch VARCHAR(100),
|
||||||
|
imported_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
CREATE INDEX IF NOT EXISTS ix_repair_costs_avg_model ON repair_costs_avg (model);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS vehicle_sales_avg (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
model VARCHAR(100) NOT NULL,
|
||||||
|
avg_stock_days NUMERIC(6,1),
|
||||||
|
avg_repair_cost NUMERIC(10,2),
|
||||||
|
avg_margin_eur NUMERIC(10,2),
|
||||||
|
avg_margin_pct NUMERIC(5,2),
|
||||||
|
avg_sale_price NUMERIC(10,2),
|
||||||
|
import_batch VARCHAR(100),
|
||||||
|
imported_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||||
|
);
|
||||||
|
CREATE INDEX IF NOT EXISTS ix_vehicle_sales_avg_model ON vehicle_sales_avg (model);
|
||||||
|
|
||||||
|
INSERT INTO alert_config (key, value, description)
|
||||||
|
VALUES
|
||||||
|
('cache_ttl_days', '90', 'TTL cache targhe in giorni'),
|
||||||
|
('alert_days_threshold', '30', 'Giorni ritardo rientro per alert'),
|
||||||
|
('repair_alert_pct_consuntiva', '20', 'Soglia % preventivo vs consuntiva'),
|
||||||
|
('repair_alert_pct_preventiva', '20', 'Soglia % preventivo vs preventiva')
|
||||||
|
ON CONFLICT (key) DO NOTHING;
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
op.execute("""
|
||||||
|
DROP TABLE IF EXISTS vehicle_sales_avg CASCADE;
|
||||||
|
DROP TABLE IF EXISTS repair_costs_avg CASCADE;
|
||||||
|
DROP TABLE IF EXISTS vehicle_stock CASCADE;
|
||||||
|
DROP TABLE IF EXISTS alert_config CASCADE;
|
||||||
|
DROP TABLE IF EXISTS notifications CASCADE;
|
||||||
|
DROP TABLE IF EXISTS repair_history CASCADE;
|
||||||
|
DROP TABLE IF EXISTS repair_comments CASCADE;
|
||||||
|
DROP TABLE IF EXISTS repair_documents CASCADE;
|
||||||
|
DROP TABLE IF EXISTS repairs CASCADE;
|
||||||
|
DROP TABLE IF EXISTS valuation_contracts CASCADE;
|
||||||
|
DROP TABLE IF EXISTS contracts CASCADE;
|
||||||
|
DROP TABLE IF EXISTS valuation_history CASCADE;
|
||||||
|
DROP TABLE IF EXISTS valuation_comments CASCADE;
|
||||||
|
DROP TABLE IF EXISTS valuation_photos CASCADE;
|
||||||
|
DROP TABLE IF EXISTS valuations CASCADE;
|
||||||
|
DROP TABLE IF EXISTS api_usage_log CASCADE;
|
||||||
|
DROP TABLE IF EXISTS plate_version_candidates CASCADE;
|
||||||
|
DROP TABLE IF EXISTS vehicle_versions CASCADE;
|
||||||
|
DROP TABLE IF EXISTS vehicle_registry CASCADE;
|
||||||
|
DROP TABLE IF EXISTS users CASCADE;
|
||||||
|
DROP TABLE IF EXISTS groups CASCADE;
|
||||||
|
DROP TYPE IF EXISTS offerstatus;
|
||||||
|
DROP TYPE IF EXISTS repairdestination;
|
||||||
|
DROP TYPE IF EXISTS repairstatus;
|
||||||
|
DROP TYPE IF EXISTS retakeregime;
|
||||||
|
DROP TYPE IF EXISTS valuationpriority;
|
||||||
|
DROP TYPE IF EXISTS valuationstatus;
|
||||||
|
DROP TYPE IF EXISTS userrole;
|
||||||
|
""")
|
||||||
Reference in New Issue
Block a user