402 lines
17 KiB
PL/PgSQL
402 lines
17 KiB
PL/PgSQL
-- AegisOne Engineering — PostgreSQL Schema
|
|
-- Adapted from MySQL for Python/FastAPI migration
|
|
|
|
-- Users
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id SERIAL PRIMARY KEY,
|
|
login VARCHAR(50) NOT NULL UNIQUE,
|
|
password_hash VARCHAR(255) NOT NULL,
|
|
role VARCHAR(20) NOT NULL DEFAULT 'technician' CHECK (role IN ('owner','engineer','technician')),
|
|
full_name VARCHAR(255) NOT NULL,
|
|
phone VARCHAR(50) DEFAULT '',
|
|
email VARCHAR(255) DEFAULT '',
|
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX idx_users_role ON users(role);
|
|
CREATE INDEX idx_users_active ON users(is_active);
|
|
|
|
-- Login attempts
|
|
CREATE TABLE IF NOT EXISTS login_attempts (
|
|
id SERIAL PRIMARY KEY,
|
|
ip_address VARCHAR(45) NOT NULL,
|
|
login VARCHAR(50) NOT NULL DEFAULT '',
|
|
attempt_time TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
CREATE INDEX idx_login_attempts_ip ON login_attempts(ip_address);
|
|
CREATE INDEX idx_login_attempts_time ON login_attempts(attempt_time);
|
|
|
|
-- Audit log
|
|
CREATE TABLE IF NOT EXISTS audit_log (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
user_id INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
|
action VARCHAR(255) NOT NULL,
|
|
details TEXT,
|
|
ip_address VARCHAR(45) DEFAULT '',
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
CREATE INDEX idx_audit_user ON audit_log(user_id);
|
|
CREATE INDEX idx_audit_action ON audit_log(action);
|
|
CREATE INDEX idx_audit_created ON audit_log(created_at);
|
|
|
|
-- Customers
|
|
CREATE TABLE IF NOT EXISTS customers (
|
|
id SERIAL PRIMARY KEY,
|
|
name VARCHAR(255) NOT NULL,
|
|
inn VARCHAR(12) DEFAULT '',
|
|
kpp VARCHAR(9) DEFAULT '',
|
|
legal_address VARCHAR(500) DEFAULT '',
|
|
contact_person VARCHAR(255) DEFAULT '',
|
|
contact_phone VARCHAR(50) DEFAULT '',
|
|
contact_email VARCHAR(255) DEFAULT '',
|
|
status VARCHAR(20) NOT NULL DEFAULT 'active' CHECK (status IN ('active','inactive','prospect')),
|
|
notes TEXT,
|
|
created_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
CREATE INDEX idx_customers_status ON customers(status);
|
|
CREATE INDEX idx_customers_inn ON customers(inn);
|
|
|
|
-- Objects
|
|
CREATE TABLE IF NOT EXISTS objects (
|
|
id SERIAL PRIMARY KEY,
|
|
customer_id INTEGER REFERENCES customers(id) ON DELETE SET NULL,
|
|
name VARCHAR(255) NOT NULL,
|
|
address VARCHAR(500) DEFAULT '',
|
|
object_type VARCHAR(100) DEFAULT '',
|
|
area_sqm NUMERIC(10,2) DEFAULT 0,
|
|
employees_count INTEGER DEFAULT 0,
|
|
contact_person VARCHAR(255) DEFAULT '',
|
|
contact_phone VARCHAR(50) DEFAULT '',
|
|
status VARCHAR(20) NOT NULL DEFAULT 'active' CHECK (status IN ('active','inactive','audit','prospective')),
|
|
notes TEXT,
|
|
risk_score NUMERIC(5,2) DEFAULT 0,
|
|
complexity_index NUMERIC(5,2) DEFAULT 0,
|
|
infrastructure_load NUMERIC(5,2) DEFAULT 0,
|
|
service_history NUMERIC(5,2) DEFAULT 0,
|
|
object_index NUMERIC(5,2) DEFAULT 0,
|
|
sla_price_monthly NUMERIC(12,2) DEFAULT 0,
|
|
region_factor NUMERIC(3,2) DEFAULT 1.00,
|
|
created_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
CREATE INDEX idx_objects_status ON objects(status);
|
|
CREATE INDEX idx_objects_customer ON objects(customer_id);
|
|
|
|
-- Object assignments
|
|
CREATE TABLE IF NOT EXISTS object_assignments (
|
|
id SERIAL PRIMARY KEY,
|
|
object_id INTEGER NOT NULL REFERENCES objects(id) ON DELETE CASCADE,
|
|
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
role VARCHAR(20) NOT NULL CHECK (role IN ('engineer','technician')),
|
|
assigned_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
unassigned_at TIMESTAMP DEFAULT NULL
|
|
);
|
|
CREATE INDEX idx_assignments_object ON object_assignments(object_id);
|
|
CREATE INDEX idx_assignments_user ON object_assignments(user_id);
|
|
|
|
-- Tasks
|
|
CREATE TABLE IF NOT EXISTS tasks (
|
|
id SERIAL PRIMARY KEY,
|
|
object_id INTEGER NOT NULL REFERENCES objects(id) ON DELETE CASCADE,
|
|
assigned_to INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
|
created_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
|
title VARCHAR(500) NOT NULL,
|
|
description TEXT,
|
|
priority VARCHAR(4) NOT NULL DEFAULT 'P3' CHECK (priority IN ('P1','P2','P3','P4')),
|
|
status VARCHAR(20) NOT NULL DEFAULT 'open' CHECK (status IN ('open','in_progress','completed','cancelled')),
|
|
deadline TIMESTAMP,
|
|
sla_remaining_hours NUMERIC(6,1) DEFAULT 0,
|
|
response_time_minutes INTEGER DEFAULT 0,
|
|
resolution_time_minutes INTEGER DEFAULT 0,
|
|
sla_compliant BOOLEAN,
|
|
checklist_data JSONB,
|
|
result_notes TEXT,
|
|
closed_at TIMESTAMP,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
CREATE INDEX idx_tasks_object ON tasks(object_id);
|
|
CREATE INDEX idx_tasks_assigned ON tasks(assigned_to);
|
|
CREATE INDEX idx_tasks_status ON tasks(status);
|
|
CREATE INDEX idx_tasks_priority ON tasks(priority);
|
|
|
|
-- Task comments
|
|
CREATE TABLE IF NOT EXISTS task_comments (
|
|
id SERIAL PRIMARY KEY,
|
|
task_id INTEGER NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
|
user_id INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
|
comment TEXT NOT NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
CREATE INDEX idx_comments_task ON task_comments(task_id);
|
|
|
|
-- Task photos
|
|
CREATE TABLE IF NOT EXISTS task_photos (
|
|
id SERIAL PRIMARY KEY,
|
|
task_id INTEGER REFERENCES tasks(id) ON DELETE SET NULL,
|
|
report_id INTEGER REFERENCES reports(id) ON DELETE SET NULL,
|
|
file_path VARCHAR(500) NOT NULL,
|
|
description VARCHAR(500) DEFAULT '',
|
|
type VARCHAR(20) DEFAULT 'other' CHECK (type IN ('before','after','evidence','other')),
|
|
uploaded_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
CREATE INDEX idx_photos_task ON task_photos(task_id);
|
|
|
|
-- Reports (created after task_photos for FK reference)
|
|
CREATE TABLE IF NOT EXISTS reports (
|
|
id SERIAL PRIMARY KEY,
|
|
object_id INTEGER NOT NULL REFERENCES objects(id) ON DELETE CASCADE,
|
|
created_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
|
report_type VARCHAR(20) NOT NULL DEFAULT 'service' CHECK (report_type IN ('inspection','service','emergency','audit','monthly')),
|
|
title VARCHAR(500) DEFAULT '',
|
|
description TEXT,
|
|
findings TEXT,
|
|
recommendations TEXT,
|
|
work_done TEXT,
|
|
cause_classification VARCHAR(100),
|
|
result_status VARCHAR(20) DEFAULT 'ok' CHECK (result_status IN ('fixed','partial','revisit','ok')),
|
|
status VARCHAR(20) NOT NULL DEFAULT 'draft' CHECK (status IN ('draft','final','cancelled')),
|
|
client_confirmed BOOLEAN DEFAULT FALSE,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
CREATE INDEX idx_reports_object ON reports(object_id);
|
|
CREATE INDEX idx_reports_author ON reports(created_by);
|
|
|
|
-- Add FK for task_photos.report_id after reports table exists
|
|
-- (handled in application-level migration)
|
|
|
|
-- Questionnaire sessions
|
|
CREATE TABLE IF NOT EXISTS questionnaire_sessions (
|
|
id SERIAL PRIMARY KEY,
|
|
object_id INTEGER REFERENCES objects(id) ON DELETE SET NULL,
|
|
client_name VARCHAR(255) DEFAULT '',
|
|
created_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
|
status VARCHAR(20) NOT NULL DEFAULT 'draft' CHECK (status IN ('draft','completed','cancelled')),
|
|
current_step SMALLINT NOT NULL DEFAULT 1,
|
|
risk_score NUMERIC(5,2) DEFAULT 0,
|
|
complexity_index NUMERIC(5,2) DEFAULT 0,
|
|
infrastructure_load NUMERIC(5,2) DEFAULT 0,
|
|
service_history NUMERIC(5,2) DEFAULT 0,
|
|
object_index NUMERIC(5,2) DEFAULT 0,
|
|
sla_price_monthly NUMERIC(12,2) DEFAULT 0,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
CREATE INDEX idx_qsessions_object ON questionnaire_sessions(object_id);
|
|
CREATE INDEX idx_qsessions_author ON questionnaire_sessions(created_by);
|
|
|
|
-- Questionnaire answers
|
|
CREATE TABLE IF NOT EXISTS questionnaire_answers (
|
|
id SERIAL PRIMARY KEY,
|
|
session_id INTEGER NOT NULL REFERENCES questionnaire_sessions(id) ON DELETE CASCADE,
|
|
step SMALLINT NOT NULL,
|
|
question_key VARCHAR(100) NOT NULL,
|
|
answer_value TEXT,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
CREATE INDEX idx_qanswers_session ON questionnaire_answers(session_id);
|
|
CREATE INDEX idx_qanswers_step ON questionnaire_answers(step);
|
|
|
|
-- Questionnaire items
|
|
CREATE TABLE IF NOT EXISTS questionnaire_items (
|
|
id SERIAL PRIMARY KEY,
|
|
step INTEGER NOT NULL DEFAULT 1,
|
|
section VARCHAR(100) NOT NULL DEFAULT '',
|
|
question_key VARCHAR(100) NOT NULL UNIQUE,
|
|
label VARCHAR(255) NOT NULL,
|
|
type VARCHAR(20) NOT NULL DEFAULT 'text' CHECK (type IN ('text','number','select','radio','checkbox','textarea')),
|
|
options JSONB,
|
|
required BOOLEAN NOT NULL DEFAULT FALSE,
|
|
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
help_text VARCHAR(500) DEFAULT '',
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
CREATE INDEX idx_qitems_step ON questionnaire_items(step);
|
|
CREATE INDEX idx_qitems_key ON questionnaire_items(question_key);
|
|
CREATE INDEX idx_qitems_sort ON questionnaire_items(sort_order);
|
|
|
|
-- Object passports
|
|
CREATE TABLE IF NOT EXISTS object_passports (
|
|
id SERIAL PRIMARY KEY,
|
|
session_id INTEGER REFERENCES questionnaire_sessions(id) ON DELETE SET NULL,
|
|
object_id INTEGER REFERENCES objects(id) ON DELETE SET NULL,
|
|
object_index NUMERIC(5,2) DEFAULT 0,
|
|
risk_score NUMERIC(5,2) DEFAULT 0,
|
|
complexity_index NUMERIC(5,2) DEFAULT 0,
|
|
sla_price_monthly NUMERIC(12,2) DEFAULT 0,
|
|
passport_data JSONB,
|
|
created_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
CREATE INDEX idx_passports_object ON object_passports(object_id);
|
|
CREATE INDEX idx_passports_session ON object_passports(session_id);
|
|
|
|
-- SLA contracts
|
|
CREATE TABLE IF NOT EXISTS sla_contracts (
|
|
id SERIAL PRIMARY KEY,
|
|
customer_id INTEGER REFERENCES customers(id) ON DELETE SET NULL,
|
|
object_id INTEGER NOT NULL REFERENCES objects(id) ON DELETE CASCADE,
|
|
contract_number VARCHAR(50) DEFAULT '',
|
|
client_name VARCHAR(255) DEFAULT '',
|
|
description TEXT,
|
|
start_date DATE NOT NULL,
|
|
end_date DATE,
|
|
sla_price_monthly NUMERIC(12,2) NOT NULL DEFAULT 0,
|
|
penalty_rate NUMERIC(5,2) DEFAULT 0,
|
|
response_time_p1 INTEGER DEFAULT 4,
|
|
response_time_p2 INTEGER DEFAULT 8,
|
|
response_time_p3 INTEGER DEFAULT 24,
|
|
response_time_hours NUMERIC(5,1),
|
|
service_level VARCHAR(20) NOT NULL DEFAULT 'business' CHECK (service_level IN ('start','business','enterprise')),
|
|
status VARCHAR(20) NOT NULL DEFAULT 'negotiation' CHECK (status IN ('active','expired','cancelled','negotiation')),
|
|
created_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
CREATE INDEX idx_sla_object ON sla_contracts(object_id);
|
|
CREATE INDEX idx_sla_status ON sla_contracts(status);
|
|
CREATE INDEX idx_sla_customer ON sla_contracts(customer_id);
|
|
|
|
-- Incidents
|
|
CREATE TABLE IF NOT EXISTS incidents (
|
|
id SERIAL PRIMARY KEY,
|
|
object_id INTEGER NOT NULL REFERENCES objects(id) ON DELETE CASCADE,
|
|
reported_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
|
assigned_to INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
|
title VARCHAR(500) NOT NULL,
|
|
description TEXT,
|
|
severity VARCHAR(4) NOT NULL DEFAULT 'P3' CHECK (severity IN ('P1','P2','P3')),
|
|
status VARCHAR(20) NOT NULL DEFAULT 'open' CHECK (status IN ('open','in_progress','resolved','closed')),
|
|
resolution TEXT,
|
|
cause VARCHAR(500) DEFAULT '',
|
|
resolution_time_minutes INTEGER DEFAULT 0,
|
|
sla_breached BOOLEAN DEFAULT FALSE,
|
|
resolved_at TIMESTAMP,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
CREATE INDEX idx_incidents_object ON incidents(object_id);
|
|
CREATE INDEX idx_incidents_severity ON incidents(severity);
|
|
CREATE INDEX idx_incidents_status ON incidents(status);
|
|
CREATE INDEX idx_incidents_assigned ON incidents(assigned_to);
|
|
|
|
-- Engineer KPI
|
|
CREATE TABLE IF NOT EXISTS engineer_kpi (
|
|
id SERIAL PRIMARY KEY,
|
|
engineer_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
period_start DATE NOT NULL,
|
|
period_end DATE NOT NULL,
|
|
sla_compliance NUMERIC(5,2) DEFAULT 0,
|
|
response_time_score NUMERIC(5,2) DEFAULT 0,
|
|
resolution_time_score NUMERIC(5,2) DEFAULT 0,
|
|
diagnosis_accuracy NUMERIC(5,2) DEFAULT 0,
|
|
reopen_rate NUMERIC(5,2) DEFAULT 0,
|
|
risk_coverage_score NUMERIC(5,2) DEFAULT 0,
|
|
documentation_quality NUMERIC(5,2) DEFAULT 0,
|
|
engineer_score NUMERIC(5,2) DEFAULT 0,
|
|
grade VARCHAR(20) DEFAULT '',
|
|
components_json JSONB,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
CREATE INDEX idx_kpi_engineer ON engineer_kpi(engineer_id);
|
|
CREATE INDEX idx_kpi_period ON engineer_kpi(period_start, period_end);
|
|
|
|
-- SHS records
|
|
CREATE TABLE IF NOT EXISTS shs_records (
|
|
id SERIAL PRIMARY KEY,
|
|
recorded_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
|
period_start DATE NOT NULL,
|
|
period_end DATE NOT NULL,
|
|
sla_stability NUMERIC(5,2) DEFAULT 0,
|
|
revenue_stability NUMERIC(5,2) DEFAULT 0,
|
|
retention NUMERIC(5,2) DEFAULT 0,
|
|
engineer_performance NUMERIC(5,2) DEFAULT 0,
|
|
incident_stability NUMERIC(5,2) DEFAULT 0,
|
|
sales_flow NUMERIC(5,2) DEFAULT 0,
|
|
operational_efficiency NUMERIC(5,2) DEFAULT 0,
|
|
shs_score NUMERIC(5,2) DEFAULT 0,
|
|
shs_status VARCHAR(20) DEFAULT '',
|
|
components_json JSONB,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
CREATE INDEX idx_shs_period ON shs_records(period_start, period_end);
|
|
|
|
-- Blog posts
|
|
CREATE TABLE IF NOT EXISTS blog_posts (
|
|
id SERIAL PRIMARY KEY,
|
|
title VARCHAR(500) NOT NULL,
|
|
slug VARCHAR(500) NOT NULL UNIQUE,
|
|
content TEXT NOT NULL,
|
|
excerpt VARCHAR(1000) DEFAULT '',
|
|
category VARCHAR(50) NOT NULL DEFAULT 'audit' CHECK (category IN ('audit','sla','incident','supervision','documentation','risk','cases')),
|
|
author_id INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
|
status VARCHAR(20) NOT NULL DEFAULT 'draft' CHECK (status IN ('draft','published','archived')),
|
|
published_at TIMESTAMP,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
CREATE INDEX idx_blog_slug ON blog_posts(slug);
|
|
CREATE INDEX idx_blog_category ON blog_posts(category);
|
|
CREATE INDEX idx_blog_status ON blog_posts(status);
|
|
CREATE INDEX idx_blog_published ON blog_posts(published_at);
|
|
|
|
-- Formula coefficients
|
|
CREATE TABLE IF NOT EXISTS formula_coefficients (
|
|
id SERIAL PRIMARY KEY,
|
|
key VARCHAR(100) NOT NULL UNIQUE,
|
|
value NUMERIC(10,4) NOT NULL DEFAULT 0,
|
|
description VARCHAR(500) DEFAULT '',
|
|
formula_ref VARCHAR(255) DEFAULT '',
|
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
updated_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
CREATE INDEX idx_coeff_key ON formula_coefficients(key);
|
|
CREATE INDEX idx_coeff_active ON formula_coefficients(is_active);
|
|
|
|
-- Cases
|
|
CREATE TABLE IF NOT EXISTS cases (
|
|
id SERIAL PRIMARY KEY,
|
|
title VARCHAR(500) NOT NULL,
|
|
text TEXT NOT NULL,
|
|
effect TEXT NOT NULL,
|
|
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
);
|
|
CREATE INDEX idx_cases_sort ON cases(sort_order);
|
|
CREATE INDEX idx_cases_active ON cases(is_active);
|
|
|
|
-- Updated_at trigger function
|
|
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
NEW.updated_at = NOW();
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- Apply triggers
|
|
CREATE TRIGGER update_users_updated_at BEFORE UPDATE ON users FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER update_customers_updated_at BEFORE UPDATE ON customers FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER update_objects_updated_at BEFORE UPDATE ON objects FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER update_tasks_updated_at BEFORE UPDATE ON tasks FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER update_reports_updated_at BEFORE UPDATE ON reports FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER update_qsessions_updated_at BEFORE UPDATE ON questionnaire_sessions FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER update_qitems_updated_at BEFORE UPDATE ON questionnaire_items FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER update_sla_updated_at BEFORE UPDATE ON sla_contracts FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER update_incidents_updated_at BEFORE UPDATE ON incidents FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER update_blog_updated_at BEFORE UPDATE ON blog_posts FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER update_cases_updated_at BEFORE UPDATE ON cases FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
|
CREATE TRIGGER update_coeff_updated_at BEFORE UPDATE ON formula_coefficients FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|