103 lines
4.3 KiB
MySQL
103 lines
4.3 KiB
MySQL
|
|
-- Migration 1001: Alert Notes System
|
||
|
|
-- Description: Contextual popup/info system for customers and contacts
|
||
|
|
-- Date: 2026-02-17
|
||
|
|
|
||
|
|
-- Alert Notes main table
|
||
|
|
CREATE TABLE IF NOT EXISTS alert_notes (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
entity_type VARCHAR(20) NOT NULL CHECK (entity_type IN ('customer', 'contact')),
|
||
|
|
entity_id INTEGER NOT NULL,
|
||
|
|
title VARCHAR(255) NOT NULL,
|
||
|
|
message TEXT NOT NULL,
|
||
|
|
severity VARCHAR(20) NOT NULL DEFAULT 'info' CHECK (severity IN ('info', 'warning', 'critical')),
|
||
|
|
requires_acknowledgement BOOLEAN DEFAULT TRUE,
|
||
|
|
active BOOLEAN DEFAULT TRUE,
|
||
|
|
created_by_user_id INTEGER REFERENCES users(user_id) ON DELETE SET NULL,
|
||
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||
|
|
);
|
||
|
|
|
||
|
|
-- Alert Note Restrictions (who is allowed to handle the customer/contact)
|
||
|
|
-- Supports both group-based and user-based restrictions
|
||
|
|
CREATE TABLE IF NOT EXISTS alert_note_restrictions (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
alert_note_id INTEGER NOT NULL REFERENCES alert_notes(id) ON DELETE CASCADE,
|
||
|
|
restriction_type VARCHAR(20) NOT NULL CHECK (restriction_type IN ('group', 'user')),
|
||
|
|
restriction_id INTEGER NOT NULL,
|
||
|
|
-- restriction_id references either groups.id or users.user_id depending on restriction_type
|
||
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
UNIQUE(alert_note_id, restriction_type, restriction_id)
|
||
|
|
);
|
||
|
|
|
||
|
|
-- Alert Note Acknowledgements (tracking who has seen and acknowledged alerts)
|
||
|
|
CREATE TABLE IF NOT EXISTS alert_note_acknowledgements (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
alert_note_id INTEGER NOT NULL REFERENCES alert_notes(id) ON DELETE CASCADE,
|
||
|
|
user_id INTEGER NOT NULL REFERENCES users(user_id) ON DELETE CASCADE,
|
||
|
|
acknowledged_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
UNIQUE(alert_note_id, user_id)
|
||
|
|
);
|
||
|
|
|
||
|
|
-- Create indexes for performance
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_alert_notes_entity ON alert_notes(entity_type, entity_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_alert_notes_active ON alert_notes(active) WHERE active = TRUE;
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_alert_notes_severity ON alert_notes(severity);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_alert_notes_created_by ON alert_notes(created_by_user_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_alert_note_restrictions_alert ON alert_note_restrictions(alert_note_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_alert_note_acknowledgements_alert ON alert_note_acknowledgements(alert_note_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_alert_note_acknowledgements_user ON alert_note_acknowledgements(user_id);
|
||
|
|
|
||
|
|
-- Trigger to update updated_at timestamp
|
||
|
|
CREATE OR REPLACE FUNCTION update_alert_notes_updated_at()
|
||
|
|
RETURNS TRIGGER AS $$
|
||
|
|
BEGIN
|
||
|
|
NEW.updated_at = CURRENT_TIMESTAMP;
|
||
|
|
RETURN NEW;
|
||
|
|
END;
|
||
|
|
$$ LANGUAGE plpgsql;
|
||
|
|
|
||
|
|
CREATE TRIGGER trigger_update_alert_notes_updated_at
|
||
|
|
BEFORE UPDATE ON alert_notes
|
||
|
|
FOR EACH ROW
|
||
|
|
EXECUTE FUNCTION update_alert_notes_updated_at();
|
||
|
|
|
||
|
|
-- Add alert_notes permissions
|
||
|
|
INSERT INTO permissions (code, description, category) VALUES
|
||
|
|
('alert_notes.view', 'View alert notes', 'alert_notes'),
|
||
|
|
('alert_notes.create', 'Create alert notes', 'alert_notes'),
|
||
|
|
('alert_notes.edit', 'Edit alert notes', 'alert_notes'),
|
||
|
|
('alert_notes.delete', 'Delete alert notes', 'alert_notes'),
|
||
|
|
('alert_notes.manage', 'Full management of alert notes', 'alert_notes')
|
||
|
|
ON CONFLICT (code) DO NOTHING;
|
||
|
|
|
||
|
|
-- Assign all alert_notes permissions to Administrators group
|
||
|
|
INSERT INTO group_permissions (group_id, permission_id)
|
||
|
|
SELECT g.id, p.id
|
||
|
|
FROM groups g
|
||
|
|
CROSS JOIN permissions p
|
||
|
|
WHERE g.name = 'Administrators' AND p.category = 'alert_notes'
|
||
|
|
ON CONFLICT DO NOTHING;
|
||
|
|
|
||
|
|
-- Assign create, edit permissions to Managers group
|
||
|
|
INSERT INTO group_permissions (group_id, permission_id)
|
||
|
|
SELECT g.id, p.id
|
||
|
|
FROM groups g
|
||
|
|
CROSS JOIN permissions p
|
||
|
|
WHERE g.name = 'Managers' AND p.code IN (
|
||
|
|
'alert_notes.view', 'alert_notes.create', 'alert_notes.edit'
|
||
|
|
)
|
||
|
|
ON CONFLICT DO NOTHING;
|
||
|
|
|
||
|
|
-- Assign view permission to all other groups (Technicians, Viewers)
|
||
|
|
INSERT INTO group_permissions (group_id, permission_id)
|
||
|
|
SELECT g.id, p.id
|
||
|
|
FROM groups g
|
||
|
|
CROSS JOIN permissions p
|
||
|
|
WHERE g.name IN ('Technicians', 'Viewers') AND p.code = 'alert_notes.view'
|
||
|
|
ON CONFLICT DO NOTHING;
|
||
|
|
|
||
|
|
-- Verify migration
|
||
|
|
SELECT 'Alert Notes system created successfully' AS status,
|
||
|
|
(SELECT COUNT(*) FROM alert_notes) AS alert_notes_count,
|
||
|
|
(SELECT COUNT(*) FROM permissions WHERE category = 'alert_notes') AS permissions_count;
|