Files
boc/landvex-admin-v2/schema-hr-support.sql
T
Bernt 48ea61cdcc docs: add quixzoom-auth-core product to AAMOS
- Product documentation in docs/products/
- Updated MEMORY.md with product info
- quiXzoom Auth Core as AAMOS Identity product
2026-07-14 09:58:53 +00:00

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;