213 lines
9.6 KiB
PL/PgSQL
213 lines
9.6 KiB
PL/PgSQL
-- Создаем таблицу для отслеживания отправленных уведомлений об окончании подписки
|
|
CREATE TABLE IF NOT EXISTS subscription_notifications (
|
|
id SERIAL PRIMARY KEY,
|
|
parent_id BIGINT NOT NULL REFERENCES parents(user_id) ON DELETE CASCADE,
|
|
notified_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
days_left INTEGER NOT NULL,
|
|
UNIQUE(parent_id, days_left) -- Чтобы не дублировать уведомления для одного количества дней
|
|
);
|
|
-- Создаем таблицу справочника школ
|
|
CREATE TABLE IF NOT EXISTS schools (
|
|
id SERIAL PRIMARY KEY,
|
|
school_number VARCHAR(50) NOT NULL UNIQUE,
|
|
school_name VARCHAR(255) NOT NULL,
|
|
address TEXT,
|
|
city VARCHAR(100),
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- Создаем таблицу родителей (пользователей)
|
|
CREATE TABLE IF NOT EXISTS parents (
|
|
user_id BIGINT PRIMARY KEY,
|
|
username VARCHAR(255),
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- Создаем таблицу детей
|
|
CREATE TABLE IF NOT EXISTS children (
|
|
id SERIAL PRIMARY KEY,
|
|
parent_id BIGINT NOT NULL REFERENCES parents(user_id) ON DELETE CASCADE,
|
|
card_number VARCHAR(16) NOT NULL,
|
|
student_name VARCHAR(255) NOT NULL,
|
|
school_id INTEGER NOT NULL REFERENCES schools(id) ON DELETE CASCADE,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
UNIQUE(parent_id, card_number)
|
|
);
|
|
|
|
-- Индексы для детей
|
|
CREATE INDEX IF NOT EXISTS idx_children_parent_id ON children(parent_id);
|
|
CREATE INDEX IF NOT EXISTS idx_children_card_number ON children(card_number);
|
|
CREATE INDEX IF NOT EXISTS idx_children_school_id ON children(school_id);
|
|
CREATE INDEX IF NOT EXISTS idx_subscription_notifications_parent_id ON subscription_notifications(parent_id);
|
|
|
|
-- Создаем таблицу для истории проходов через турникет
|
|
CREATE TABLE IF NOT EXISTS access_events (
|
|
id SERIAL PRIMARY KEY,
|
|
event_id VARCHAR(100) UNIQUE,
|
|
user_id VARCHAR(100) NOT NULL,
|
|
device_id VARCHAR(100),
|
|
resource_number INTEGER NOT NULL,
|
|
access_zone_id1 VARCHAR(100),
|
|
access_zone_id2 VARCHAR(100),
|
|
school_id INTEGER REFERENCES schools(id) ON DELETE CASCADE,
|
|
event_time TIMESTAMP NOT NULL,
|
|
processed BOOLEAN DEFAULT FALSE,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- Индексы для access_events
|
|
CREATE INDEX IF NOT EXISTS idx_access_events_user_id ON access_events(user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_access_events_time ON access_events(event_time);
|
|
CREATE INDEX IF NOT EXISTS idx_access_events_processed ON access_events(processed);
|
|
|
|
-- Создаем таблицу уведомлений
|
|
CREATE TABLE IF NOT EXISTS notifications (
|
|
id SERIAL PRIMARY KEY,
|
|
parent_id BIGINT NOT NULL REFERENCES parents(user_id) ON DELETE CASCADE,
|
|
child_id INTEGER REFERENCES children(id) ON DELETE CASCADE,
|
|
message TEXT NOT NULL,
|
|
event_type VARCHAR(50),
|
|
is_read BOOLEAN DEFAULT FALSE,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- Индексы для уведомлений
|
|
CREATE INDEX IF NOT EXISTS idx_notifications_parent_id ON notifications(parent_id);
|
|
CREATE INDEX IF NOT EXISTS idx_notifications_is_read ON notifications(is_read);
|
|
|
|
-- ============================================
|
|
-- ПОДПИСОЧНАЯ СИСТЕМА
|
|
-- ============================================
|
|
|
|
-- Создаем таблицу подписок
|
|
CREATE TABLE IF NOT EXISTS subscriptions (
|
|
id SERIAL PRIMARY KEY,
|
|
parent_id BIGINT NOT NULL UNIQUE REFERENCES parents(user_id) ON DELETE CASCADE,
|
|
status VARCHAR(20) NOT NULL DEFAULT 'trial', -- 'trial', 'active', 'expired', 'cancelled'
|
|
trial_start TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
trial_end TIMESTAMP,
|
|
paid_until TIMESTAMP,
|
|
last_payment_date TIMESTAMP,
|
|
payment_amount DECIMAL(10, 2) DEFAULT 50.00,
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- Индексы для подписок
|
|
CREATE INDEX IF NOT EXISTS idx_subscriptions_parent_id ON subscriptions(parent_id);
|
|
CREATE INDEX IF NOT EXISTS idx_subscriptions_status ON subscriptions(status);
|
|
|
|
-- Создаем таблицу истории платежей
|
|
CREATE TABLE IF NOT EXISTS payments (
|
|
id SERIAL PRIMARY KEY,
|
|
parent_id BIGINT NOT NULL REFERENCES parents(user_id) ON DELETE CASCADE,
|
|
amount DECIMAL(10, 2) NOT NULL,
|
|
payment_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
payment_method VARCHAR(50),
|
|
transaction_id VARCHAR(255) UNIQUE,
|
|
status VARCHAR(20) DEFAULT 'pending', -- 'pending', 'success', 'failed'
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- Индексы для платежей
|
|
CREATE INDEX IF NOT EXISTS idx_payments_parent_id ON payments(parent_id);
|
|
CREATE INDEX IF NOT EXISTS idx_payments_transaction_id ON payments(transaction_id);
|
|
CREATE INDEX IF NOT EXISTS idx_payments_status ON payments(status);
|
|
|
|
-- ============================================
|
|
-- ФУНКЦИИ И ТРИГГЕРЫ
|
|
-- ============================================
|
|
|
|
-- Функция для автоматического обновления updated_at
|
|
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
NEW.updated_at = CURRENT_TIMESTAMP;
|
|
RETURN NEW;
|
|
END;
|
|
$$ language 'plpgsql';
|
|
|
|
-- Триггер для обновления updated_at в parents
|
|
DROP TRIGGER IF EXISTS update_parents_updated_at ON parents;
|
|
CREATE TRIGGER update_parents_updated_at
|
|
BEFORE UPDATE ON parents
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION update_updated_at_column();
|
|
|
|
-- Триггер для обновления updated_at в children
|
|
DROP TRIGGER IF EXISTS update_children_updated_at ON children;
|
|
CREATE TRIGGER update_children_updated_at
|
|
BEFORE UPDATE ON children
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION update_updated_at_column();
|
|
|
|
-- Триггер для обновления updated_at в subscriptions
|
|
DROP TRIGGER IF EXISTS update_subscriptions_updated_at ON subscriptions;
|
|
CREATE TRIGGER update_subscriptions_updated_at
|
|
BEFORE UPDATE ON subscriptions
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION update_updated_at_column();
|
|
|
|
-- ============================================
|
|
-- НАЧАЛЬНЫЕ ДАННЫЕ
|
|
-- ============================================
|
|
|
|
-- Добавляем школы
|
|
INSERT INTO schools (school_number, school_name, address, city) VALUES
|
|
('101', 'Средняя общеобразовательная школа №101', 'ул. Ленина, 15', 'Москва'),
|
|
('102', 'Средняя общеобразовательная школа №102', 'ул. Гагарина, 10', 'Москва'),
|
|
('103', 'Средняя общеобразовательная школа №103', 'ул. Мира, 25', 'Москва'),
|
|
('104', 'Гимназия №104', 'ул. Садовая, 8', 'Москва'),
|
|
('105', 'Лицей №105', 'ул. Тверская, 12', 'Москва'),
|
|
('201', 'Гимназия №201', 'ул. Пушкина, 5', 'Санкт-Петербург'),
|
|
('202', 'Средняя школа №202', 'ул. Невский проспект, 20', 'Санкт-Петербург'),
|
|
('203', 'Средняя школа №203', 'ул. Московская, 15', 'Санкт-Петербург'),
|
|
('301', 'Лицей №301', 'ул. Советская, 8', 'Казань'),
|
|
('302', 'Средняя школа №302', 'ул. Ленина, 42', 'Казань'),
|
|
('401', 'Средняя школа №401', 'ул. Мира, 12', 'Новосибирск'),
|
|
('402', 'Гимназия №402', 'ул. Кирова, 7', 'Новосибирск'),
|
|
('501', 'Школа №501 с углубленным изучением математики', 'ул. Лермонтова, 3', 'Екатеринбург'),
|
|
('502', 'Гимназия №502', 'ул. Свердлова, 10', 'Екатеринбург'),
|
|
('601', 'Средняя общеобразовательная школа №601', 'ул. Садовая, 25', 'Нижний Новгород'),
|
|
('602', 'Лицей №602', 'ул. Горького, 8', 'Нижний Новгород'),
|
|
('701', 'Гимназия №701', 'ул. Чехова, 10', 'Ростов-на-Дону'),
|
|
('702', 'Средняя школа №702', 'ул. Пушкинская, 15', 'Ростов-на-Дону')
|
|
ON CONFLICT (school_number) DO NOTHING;
|
|
|
|
-- Добавляем тестового пользователя (для разработки)
|
|
-- INSERT INTO parents (user_id, username) VALUES (15649081, 'Алексей Халецкий')
|
|
-- ON CONFLICT (user_id) DO NOTHING;
|
|
|
|
-- Добавляем тестовую подписку для разработчика (активная на год)
|
|
-- INSERT INTO subscriptions (parent_id, status, paid_until, payment_amount)
|
|
-- VALUES (15649081, 'active', CURRENT_TIMESTAMP + INTERVAL '365 days', 50.00)
|
|
-- ON CONFLICT (parent_id) DO NOTHING;
|
|
|
|
-- ============================================
|
|
-- ПРОВЕРОЧНЫЕ ЗАПРОСЫ
|
|
-- ============================================
|
|
|
|
-- Проверка количества школ
|
|
-- SELECT COUNT(*) as total_schools FROM schools;
|
|
|
|
-- Проверка подписок
|
|
-- SELECT
|
|
-- p.username,
|
|
-- s.status,
|
|
-- s.trial_end,
|
|
-- s.paid_until,
|
|
-- s.payment_amount
|
|
-- FROM subscriptions s
|
|
-- JOIN parents p ON s.parent_id = p.user_id;
|
|
|
|
-- Проверка детей
|
|
-- SELECT
|
|
-- p.username,
|
|
-- c.student_name,
|
|
-- c.card_number,
|
|
-- sc.school_name
|
|
-- FROM children c
|
|
-- JOIN parents p ON c.parent_id = p.user_id
|
|
-- JOIN schools sc ON c.school_id = sc.id; |