175 lines
9.5 KiB
SQL
175 lines
9.5 KiB
SQL
|
|
-- ═══════════════════════════════════════════════════════════════════════════
|
||
|
|
-- AAMOS Admin v2 — HR & Support Schema
|
||
|
|
-- ═══════════════════════════════════════════════════════════════════════════
|
||
|
|
|
||
|
|
-- ── Support Tickets ────────────────────────────────────────────────────────
|
||
|
|
CREATE TABLE IF NOT EXISTS support_tickets (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
ticket_number TEXT NOT NULL UNIQUE,
|
||
|
|
customer_id UUID REFERENCES billing_customers(id),
|
||
|
|
subject TEXT NOT NULL,
|
||
|
|
description TEXT,
|
||
|
|
status TEXT NOT NULL DEFAULT 'open', -- 'open'|'in_progress'|'waiting'|'closed'
|
||
|
|
priority TEXT NOT NULL DEFAULT 'medium', -- 'low'|'medium'|'high'|'urgent'
|
||
|
|
category TEXT, -- 'technical'|'billing'|'general'|'feature_request'
|
||
|
|
source TEXT NOT NULL DEFAULT 'web', -- 'web'|'email'|'phone'|'chat'
|
||
|
|
assignee_id UUID,
|
||
|
|
resolution TEXT,
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
closed_at TIMESTAMPTZ
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_support_tickets_status ON support_tickets (status);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_support_tickets_priority ON support_tickets (priority);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_support_tickets_customer ON support_tickets (customer_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_support_tickets_assignee ON support_tickets (assignee_id);
|
||
|
|
|
||
|
|
-- ── Support Messages ───────────────────────────────────────────────────────
|
||
|
|
CREATE TABLE IF NOT EXISTS support_messages (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
ticket_id UUID NOT NULL REFERENCES support_tickets(id) ON DELETE CASCADE,
|
||
|
|
body TEXT NOT NULL,
|
||
|
|
author_id UUID,
|
||
|
|
is_internal BOOLEAN NOT NULL DEFAULT FALSE,
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_support_messages_ticket ON support_messages (ticket_id);
|
||
|
|
|
||
|
|
-- ── FAQ / Knowledge Base ───────────────────────────────────────────────────
|
||
|
|
CREATE TABLE IF NOT EXISTS support_faq (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
question TEXT NOT NULL,
|
||
|
|
answer TEXT NOT NULL,
|
||
|
|
category TEXT,
|
||
|
|
views INTEGER NOT NULL DEFAULT 0,
|
||
|
|
is_published BOOLEAN NOT NULL DEFAULT FALSE,
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_support_faq_category ON support_faq (category);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_support_faq_published ON support_faq (is_published);
|
||
|
|
|
||
|
|
-- ── HR Departments ─────────────────────────────────────────────────────────
|
||
|
|
CREATE TABLE IF NOT EXISTS hr_departments (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
name TEXT NOT NULL,
|
||
|
|
description TEXT,
|
||
|
|
manager_id UUID,
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- ── HR Employees ───────────────────────────────────────────────────────────
|
||
|
|
CREATE TABLE IF NOT EXISTS hr_employees (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
first_name TEXT NOT NULL,
|
||
|
|
last_name TEXT NOT NULL,
|
||
|
|
email TEXT NOT NULL UNIQUE,
|
||
|
|
phone TEXT,
|
||
|
|
personal_number TEXT,
|
||
|
|
address TEXT,
|
||
|
|
postal_code TEXT,
|
||
|
|
city TEXT,
|
||
|
|
department_id UUID REFERENCES hr_departments(id),
|
||
|
|
position TEXT,
|
||
|
|
start_date DATE NOT NULL,
|
||
|
|
end_date DATE,
|
||
|
|
employment_type TEXT NOT NULL DEFAULT 'full_time', -- 'full_time'|'part_time'|'contract'|'intern'
|
||
|
|
salary NUMERIC(18,2),
|
||
|
|
status TEXT NOT NULL DEFAULT 'active', -- 'active'|'on_leave'|'terminated'|'suspended'
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_hr_employees_status ON hr_employees (status);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_hr_employees_department ON hr_employees (department_id);
|
||
|
|
|
||
|
|
-- ── HR Contracts ───────────────────────────────────────────────────────────
|
||
|
|
CREATE TABLE IF NOT EXISTS hr_contracts (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
contract_number TEXT NOT NULL UNIQUE,
|
||
|
|
employee_id UUID NOT NULL REFERENCES hr_employees(id),
|
||
|
|
contract_type TEXT NOT NULL, -- 'permanent'|'fixed_term'|'consultant'|'internship'
|
||
|
|
start_date DATE NOT NULL,
|
||
|
|
end_date DATE,
|
||
|
|
salary NUMERIC(18,2) NOT NULL,
|
||
|
|
working_hours NUMERIC(4,2) NOT NULL DEFAULT 40.00,
|
||
|
|
probation_months INTEGER DEFAULT 6,
|
||
|
|
benefits JSONB NOT NULL DEFAULT '{}',
|
||
|
|
terms JSONB NOT NULL DEFAULT '{}',
|
||
|
|
status TEXT NOT NULL DEFAULT 'active', -- 'active'|'terminated'|'expired'
|
||
|
|
termination_reason TEXT,
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_hr_contracts_employee ON hr_contracts (employee_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_hr_contracts_status ON hr_contracts (status);
|
||
|
|
|
||
|
|
-- ── HR Documents ───────────────────────────────────────────────────────────
|
||
|
|
CREATE TABLE IF NOT EXISTS hr_documents (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
employee_id UUID NOT NULL REFERENCES hr_employees(id),
|
||
|
|
document_type TEXT NOT NULL, -- 'contract'|'id'|'certificate'|'review'|'other'
|
||
|
|
title TEXT NOT NULL,
|
||
|
|
file_url TEXT,
|
||
|
|
expiry_date DATE,
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_hr_documents_employee ON hr_documents (employee_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_hr_documents_type ON hr_documents (document_type);
|
||
|
|
|
||
|
|
-- ── HR Salary ──────────────────────────────────────────────────────────────
|
||
|
|
CREATE TABLE IF NOT EXISTS hr_salary (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
employee_id UUID NOT NULL REFERENCES hr_employees(id),
|
||
|
|
year INTEGER NOT NULL,
|
||
|
|
month INTEGER NOT NULL,
|
||
|
|
base_salary NUMERIC(18,2) NOT NULL,
|
||
|
|
overtime NUMERIC(18,2) DEFAULT 0,
|
||
|
|
bonus NUMERIC(18,2) DEFAULT 0,
|
||
|
|
deductions NUMERIC(18,2) DEFAULT 0,
|
||
|
|
tax NUMERIC(18,2) NOT NULL,
|
||
|
|
net_salary NUMERIC(18,2) NOT NULL,
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||
|
|
UNIQUE (employee_id, year, month)
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_hr_salary_employee ON hr_salary (employee_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_hr_salary_period ON hr_salary (year, month);
|
||
|
|
|
||
|
|
-- ── HR Salary History ──────────────────────────────────────────────────────
|
||
|
|
CREATE TABLE IF NOT EXISTS hr_salary_history (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
employee_id UUID NOT NULL REFERENCES hr_employees(id),
|
||
|
|
old_salary NUMERIC(18,2),
|
||
|
|
new_salary NUMERIC(18,2) NOT NULL,
|
||
|
|
effective_date DATE NOT NULL,
|
||
|
|
reason TEXT,
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
|
|
);
|
||
|
|
|
||
|
|
-- Insert default departments
|
||
|
|
INSERT INTO hr_departments (name, description) VALUES
|
||
|
|
('Ledning', 'Företagsledning och strategi'),
|
||
|
|
('Utveckling', 'Produktutveckling och teknik'),
|
||
|
|
('Försäljning', 'Försäljning och marknadsföring'),
|
||
|
|
('Support', 'Kundsupport och service'),
|
||
|
|
('Ekonomi', 'Bokföring och ekonomi'),
|
||
|
|
('HR', 'Personal och rekrytering')
|
||
|
|
ON CONFLICT DO NOTHING;
|
||
|
|
|
||
|
|
-- Insert test employee (Erik Svensson)
|
||
|
|
INSERT INTO hr_employees (first_name, last_name, email, personal_number, position, start_date, employment_type, salary, status)
|
||
|
|
VALUES ('Erik', 'Svensson', 'erik@landvex.com', '19750101-1234', 'VD', '2024-01-01', 'full_time', 100000, 'active')
|
||
|
|
ON CONFLICT (email) DO NOTHING;
|
||
|
|
|
||
|
|
-- Insert test employee (Johan Berglund)
|
||
|
|
INSERT INTO hr_employees (first_name, last_name, email, personal_number, position, start_date, employment_type, salary, status)
|
||
|
|
VALUES ('Johan', 'Berglund', 'johan@landvex.com', '19800215-5678', 'CTO', '2024-01-01', 'full_time', 90000, 'active')
|
||
|
|
ON CONFLICT (email) DO NOTHING;
|