Primo schema DB
This commit is contained in:
@@ -3,6 +3,9 @@
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
.env
|
||||
|
||||
# C extensions
|
||||
*.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