v1.0
This commit is contained in:
721
test_data.py
Normal file
721
test_data.py
Normal file
@@ -0,0 +1,721 @@
|
||||
# test_data.py (исправленная версия с правильной транслитерацией)
|
||||
import sqlite3
|
||||
import hashlib
|
||||
from datetime import datetime, timedelta
|
||||
import random
|
||||
import re
|
||||
|
||||
# Конфигурация
|
||||
DB_NAME = "rabota_today.db"
|
||||
|
||||
|
||||
# Функция для транслитерации кириллицы в латиницу
|
||||
def transliterate(text):
|
||||
"""Преобразование кириллицы в латиницу для email"""
|
||||
translit_dict = {
|
||||
'а': 'a', 'б': 'b', 'в': 'v', 'г': 'g', 'д': 'd', 'е': 'e', 'ё': 'e',
|
||||
'ж': 'zh', 'з': 'z', 'и': 'i', 'й': 'y', 'к': 'k', 'л': 'l', 'м': 'm',
|
||||
'н': 'n', 'о': 'o', 'п': 'p', 'р': 'r', 'с': 's', 'т': 't', 'у': 'u',
|
||||
'ф': 'f', 'х': 'kh', 'ц': 'ts', 'ч': 'ch', 'ш': 'sh', 'щ': 'shch',
|
||||
'ъ': '', 'ы': 'y', 'ь': '', 'э': 'e', 'ю': 'yu', 'я': 'ya',
|
||||
'А': 'A', 'Б': 'B', 'В': 'V', 'Г': 'G', 'Д': 'D', 'Е': 'E', 'Ё': 'E',
|
||||
'Ж': 'Zh', 'З': 'Z', 'И': 'I', 'Й': 'Y', 'К': 'K', 'Л': 'L', 'М': 'M',
|
||||
'Н': 'N', 'О': 'O', 'П': 'P', 'Р': 'R', 'С': 'S', 'Т': 'T', 'У': 'U',
|
||||
'Ф': 'F', 'Х': 'Kh', 'Ц': 'Ts', 'Ч': 'Ch', 'Ш': 'Sh', 'Щ': 'Shch',
|
||||
'Ъ': '', 'Ы': 'Y', 'Ь': '', 'Э': 'E', 'Ю': 'Yu', 'Я': 'Ya'
|
||||
}
|
||||
|
||||
result = ''
|
||||
for char in text:
|
||||
result += translit_dict.get(char, char)
|
||||
|
||||
# Приводим к нижнему регистру
|
||||
result = result.lower()
|
||||
# Заменяем пробелы и спецсимволы на точки
|
||||
result = re.sub(r'[^a-z0-9]', '.', result)
|
||||
# Убираем множественные точки
|
||||
result = re.sub(r'\.+', '.', result)
|
||||
# Убираем точки в начале и конце
|
||||
result = result.strip('.')
|
||||
|
||||
return result
|
||||
|
||||
|
||||
# Список тегов по категориям
|
||||
TAGS = {
|
||||
'skill': [
|
||||
'Python', 'JavaScript', 'TypeScript', 'React', 'Vue.js', 'Angular',
|
||||
'Node.js', 'Django', 'Flask', 'FastAPI', 'Java', 'Spring',
|
||||
'C#', '.NET', 'PHP', 'Laravel', 'Ruby', 'Rails', 'Go', 'Rust',
|
||||
'SQL', 'PostgreSQL', 'MySQL', 'MongoDB', 'Redis', 'Docker',
|
||||
'Kubernetes', 'AWS', 'Azure', 'GCP', 'Git', 'CI/CD', 'Linux',
|
||||
'HTML', 'CSS', 'SASS', 'Tailwind', 'Bootstrap', 'Figma',
|
||||
'Photoshop', 'UI/UX', 'Аналитика данных', 'Machine Learning',
|
||||
'Data Science', 'Excel', '1С', 'SAP', 'CRM', 'Salesforce'
|
||||
],
|
||||
'industry': [
|
||||
'IT', 'Финансы', 'Банки', 'Ритейл', 'E-commerce', 'Медицина',
|
||||
'Образование', 'Строительство', 'Производство', 'Логистика',
|
||||
'Транспорт', 'Маркетинг', 'Реклама', 'PR', 'Консалтинг',
|
||||
'Юриспруденция', 'HR', 'Туризм', 'HoReCa', 'СМИ', 'Телеком'
|
||||
],
|
||||
'position': [
|
||||
'Разработчик', 'Программист', 'Тестировщик', 'QA', 'DevOps',
|
||||
'Системный администратор', 'Аналитик', 'Data Scientist',
|
||||
'Менеджер', 'Руководитель', 'Директор', 'Team Lead',
|
||||
'Project Manager', 'Product Manager', 'Scrum Master',
|
||||
'Дизайнер', 'Верстальщик', 'Маркетолог', 'SMM', 'SEO',
|
||||
'Бухгалтер', 'Экономист', 'Юрист', 'HR', 'Recruiter'
|
||||
]
|
||||
}
|
||||
|
||||
# Имена и фамилии для генерации
|
||||
FIRST_NAMES = [
|
||||
'Александр', 'Дмитрий', 'Максим', 'Сергей', 'Андрей', 'Алексей',
|
||||
'Артём', 'Илья', 'Кирилл', 'Михаил', 'Никита', 'Макар',
|
||||
'Егор', 'Роман', 'Олег', 'Владимир', 'Иван', 'Денис',
|
||||
'Анна', 'Елена', 'Ольга', 'Наталья', 'Екатерина', 'Мария',
|
||||
'Анастасия', 'Татьяна', 'Ирина', 'Юлия', 'Светлана', 'Дарья'
|
||||
]
|
||||
|
||||
LAST_NAMES = [
|
||||
'Иванов', 'Петров', 'Сидоров', 'Смирнов', 'Кузнецов', 'Попов',
|
||||
'Васильев', 'Соколов', 'Михайлов', 'Новиков', 'Федоров', 'Морозов',
|
||||
'Волков', 'Алексеев', 'Лебедев', 'Семенов', 'Егоров', 'Павлов',
|
||||
'Козлов', 'Степанов', 'Николаев', 'Орлов', 'Андреев', 'Макаров'
|
||||
]
|
||||
|
||||
# Названия компаний (уже на латинице)
|
||||
COMPANIES = [
|
||||
{'name': 'Yandex', 'website': 'yandex.ru', 'industry': 'IT'},
|
||||
{'name': 'VK', 'website': 'vk.com', 'industry': 'IT'},
|
||||
{'name': 'Sber', 'website': 'sberbank.ru', 'industry': 'Финансы'},
|
||||
{'name': 'Tinkoff', 'website': 'tinkoff.ru', 'industry': 'Финансы'},
|
||||
{'name': 'Ozon', 'website': 'ozon.ru', 'industry': 'E-commerce'},
|
||||
{'name': 'Wildberries', 'website': 'wildberries.ru', 'industry': 'E-commerce'},
|
||||
{'name': 'Avito', 'website': 'avito.ru', 'industry': 'IT'},
|
||||
{'name': '2GIS', 'website': '2gis.ru', 'industry': 'IT'},
|
||||
{'name': 'Kaspersky', 'website': 'kaspersky.ru', 'industry': 'IT'},
|
||||
{'name': 'Skyeng', 'website': 'skyeng.ru', 'industry': 'Образование'},
|
||||
{'name': 'Skillbox', 'website': 'skillbox.ru', 'industry': 'Образование'},
|
||||
{'name': 'GeekBrains', 'website': 'gb.ru', 'industry': 'Образование'},
|
||||
{'name': 'Rostelecom', 'website': 'rt.ru', 'industry': 'Телеком'},
|
||||
{'name': 'MTS', 'website': 'mts.ru', 'industry': 'Телеком'},
|
||||
{'name': 'Beeline', 'website': 'beeline.ru', 'industry': 'Телеком'},
|
||||
{'name': 'Megafon', 'website': 'megafon.ru', 'industry': 'Телеком'},
|
||||
{'name': 'X5 Retail Group', 'website': 'x5.ru', 'industry': 'Ритейл'},
|
||||
{'name': 'Magnit', 'website': 'magnit.ru', 'industry': 'Ритейл'},
|
||||
{'name': 'Lenta', 'website': 'lenta.com', 'industry': 'Ритейл'}
|
||||
]
|
||||
|
||||
# Описания компаний
|
||||
COMPANY_DESCRIPTIONS = [
|
||||
"Крупнейшая IT-компания в России, занимаемся разработкой поисковых систем и сервисов.",
|
||||
"Ведущая социальная сеть, развиваем экосистему сервисов для общения и развлечений.",
|
||||
"Крупнейший банк, внедряем инновационные технологии в финансовый сектор.",
|
||||
"Инновационный банк, полностью цифровой сервис для миллионов клиентов.",
|
||||
"Лидер e-commerce, развиваем маркетплейс и логистику по всей стране.",
|
||||
"Крупнейший маркетплейс, работаем с миллионами заказов ежедневно.",
|
||||
"Платформа для объявлений, помогаем людям покупать и продавать.",
|
||||
"Разрабатываем картографические сервисы и навигационные приложения.",
|
||||
"Мировой лидер в области кибербезопасности, защищаем пользователей по всему миру.",
|
||||
"Образовательная платформа, помогаем людям осваивать новые профессии.",
|
||||
"Онлайн-университет, обучаем востребованным digital-профессиям.",
|
||||
"Телеком-оператор, предоставляем услуги связи и цифровые сервисы."
|
||||
]
|
||||
|
||||
# Заголовки вакансий
|
||||
VACANCY_TITLES = [
|
||||
"Python разработчик",
|
||||
"Java разработчик",
|
||||
"Frontend разработчик (React)",
|
||||
"Backend разработчик (Node.js)",
|
||||
"Fullstack разработчик",
|
||||
"DevOps инженер",
|
||||
"Системный администратор",
|
||||
"QA тестировщик",
|
||||
"Data Scientist",
|
||||
"Аналитик данных",
|
||||
"Project Manager",
|
||||
"Product Manager",
|
||||
"UI/UX дизайнер",
|
||||
"Веб-дизайнер",
|
||||
"Маркетолог",
|
||||
"SMM менеджер",
|
||||
"SEO специалист",
|
||||
"HR менеджер",
|
||||
"Recruiter",
|
||||
"Менеджер по продажам",
|
||||
"Руководитель отдела разработки",
|
||||
"Team Lead",
|
||||
"Бухгалтер",
|
||||
"Юрист",
|
||||
"Системный аналитик"
|
||||
]
|
||||
|
||||
# Описания вакансий
|
||||
VACANCY_DESCRIPTIONS = [
|
||||
"""Требования:
|
||||
- Опыт работы от 2 лет
|
||||
- Знание Python, Django/Flask
|
||||
- Понимание ООП и паттернов проектирования
|
||||
- Опыт работы с базами данных (PostgreSQL, MySQL)
|
||||
- Знание Git, Linux
|
||||
|
||||
Условия:
|
||||
- Удаленная работа
|
||||
- Гибкий график
|
||||
- ДМС со стоматологией
|
||||
- Белая заработная плата
|
||||
- Возможность роста""",
|
||||
|
||||
"""Что нужно делать:
|
||||
- Разработка новых фич
|
||||
- Рефакторинг существующего кода
|
||||
- Участие в code review
|
||||
- Оптимизация производительности
|
||||
|
||||
Мы ждем:
|
||||
- Опыт от 3 лет
|
||||
- Знание Java 11+, Spring Boot
|
||||
- Понимание микросервисной архитектуры
|
||||
- Опыт с Docker, Kubernetes""",
|
||||
|
||||
"""Обязанности:
|
||||
- Верстка интерфейсов по макетам
|
||||
- Разработка новых компонентов
|
||||
- Интеграция с API
|
||||
- Оптимизация загрузки страниц
|
||||
|
||||
Требования:
|
||||
- React, Redux, TypeScript
|
||||
- HTML5, CSS3, адаптивная верстка
|
||||
- Опыт работы с REST API
|
||||
- Git, Webpack""",
|
||||
|
||||
"""Кого мы ищем:
|
||||
- Опыт разработки от 1 года
|
||||
- Знание Node.js, Express/NestJS
|
||||
- Опыт работы с MongoDB или PostgreSQL
|
||||
- Понимание асинхронного программирования
|
||||
- Будет плюсом знание TypeScript""",
|
||||
|
||||
"""Задачи:
|
||||
- Управление инфраструктурой
|
||||
- Настройка CI/CD
|
||||
- Мониторинг и логирование
|
||||
- Автоматизация процессов
|
||||
|
||||
Требования:
|
||||
- Опыт работы с Docker, Kubernetes
|
||||
- Знание облачных платформ (AWS/Azure/GCP)
|
||||
- Опыт с системами мониторинга
|
||||
- Понимание сетевых протоколов"""
|
||||
]
|
||||
|
||||
# Сопроводительные письма
|
||||
COVER_LETTERS = [
|
||||
"Здравствуйте! Меня заинтересовала ваша вакансия. Имею большой опыт в данной сфере, готов выполнять тестовое задание и проходить собеседование.",
|
||||
"Добрый день! Откликаюсь на вакансию. Уверен, что мой опыт и навыки будут полезны вашей компании. Готов к сотрудничеству!",
|
||||
"Здравствуйте! Хочу предложить свою кандидатуру. Имею успешный опыт реализации аналогичных проектов. Буду рад обсудить детали.",
|
||||
"Добрый день! Мой опыт полностью соответствует требованиям. Ищу интересные задачи и профессиональный рост. Рассмотрю любые предложения.",
|
||||
"Здравствуйте! Откликаюсь на вакансию. Готов приступить к работе с завтрашнего дня. Могу выполнить тестовое задание для подтверждения квалификации.",
|
||||
"Добрый день! Опыт работы 5 лет в данной сфере. Уверен, что смогу принести пользу компании. Жду обратной связи."
|
||||
]
|
||||
|
||||
# Ответы работодателей
|
||||
EMPLOYER_RESPONSES = [
|
||||
"Здравствуйте! Спасибо за отклик. Приглашаем вас на собеседование в пятницу в 15:00.",
|
||||
"Добрый день! Ваше резюме нам подходит. Когда вам удобно созвониться для интервью?",
|
||||
"Здравствуйте! К сожалению, мы вынуждены отказать, так как ищем кандидата с большим опытом.",
|
||||
"Добрый день! Спасибо за интерес к нашей компании. Мы готовы сделать вам предложение о работе.",
|
||||
"Здравствуйте! Приглашаем вас на техническое собеседование в четверг. Ждем подтверждения.",
|
||||
"Добрый день! Ваш опыт выглядит интересно. Хотели бы обсудить детали сотрудничества."
|
||||
]
|
||||
|
||||
|
||||
def hash_password(password: str) -> str:
|
||||
"""Хеширование пароля"""
|
||||
salt = "rabota.today.salt"
|
||||
return hashlib.sha256((password + salt).encode()).hexdigest()
|
||||
|
||||
|
||||
def generate_email(first_name, last_name, domain=None):
|
||||
"""Генерация email на латинице"""
|
||||
# Транслитерируем имя и фамилию
|
||||
first_lat = transliterate(first_name)
|
||||
last_lat = transliterate(last_name)
|
||||
|
||||
# Случайный выбор формата email
|
||||
formats = [
|
||||
f"{first_lat}.{last_lat}",
|
||||
f"{first_lat}{last_lat}",
|
||||
f"{first_lat[0]}.{last_lat}",
|
||||
f"{first_lat}.{last_lat[0]}",
|
||||
f"{first_lat}{random.randint(1, 999)}"
|
||||
]
|
||||
|
||||
username = random.choice(formats)
|
||||
|
||||
if domain:
|
||||
# Для работодателей используем домен компании
|
||||
email = f"{username}@{domain}"
|
||||
else:
|
||||
# Для соискателей используем популярные домены
|
||||
domains = ['gmail.com', 'yandex.ru', 'mail.ru', 'inbox.ru', 'list.ru', 'bk.ru']
|
||||
email = f"{username}@{random.choice(domains)}"
|
||||
|
||||
return email.lower()
|
||||
|
||||
|
||||
def update_database_schema():
|
||||
"""Обновление схемы базы данных (добавление недостающих колонок)"""
|
||||
conn = sqlite3.connect(DB_NAME)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Проверяем существование таблицы applications и добавляем недостающие колонки
|
||||
cursor.execute("PRAGMA table_info(applications)")
|
||||
columns = [col[1] for col in cursor.fetchall()]
|
||||
|
||||
if 'applications' in [t[0] for t in cursor.execute("SELECT name FROM sqlite_master WHERE type='table'").fetchall()]:
|
||||
if 'viewed_at' not in columns:
|
||||
cursor.execute("ALTER TABLE applications ADD COLUMN viewed_at TIMESTAMP")
|
||||
print("✅ Добавлена колонка viewed_at в таблицу applications")
|
||||
|
||||
if 'response_message' not in columns:
|
||||
cursor.execute("ALTER TABLE applications ADD COLUMN response_message TEXT")
|
||||
print("✅ Добавлена колонка response_message в таблицу applications")
|
||||
|
||||
if 'response_at' not in columns:
|
||||
cursor.execute("ALTER TABLE applications ADD COLUMN response_at TIMESTAMP")
|
||||
print("✅ Добавлена колонка response_at в таблицу applications")
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
|
||||
def clear_database():
|
||||
"""Очистка базы данных"""
|
||||
conn = sqlite3.connect(DB_NAME)
|
||||
cursor = conn.cursor()
|
||||
|
||||
# Отключаем проверку внешних ключей временно
|
||||
cursor.execute("PRAGMA foreign_keys = OFF")
|
||||
|
||||
# Очищаем все таблицы
|
||||
tables = [
|
||||
'applications',
|
||||
'favorites',
|
||||
'resume_tags',
|
||||
'vacancy_tags',
|
||||
'work_experience',
|
||||
'education',
|
||||
'resumes',
|
||||
'vacancies',
|
||||
'companies',
|
||||
'users',
|
||||
'tags'
|
||||
]
|
||||
|
||||
for table in tables:
|
||||
try:
|
||||
cursor.execute(f"DELETE FROM {table}")
|
||||
print(f" Очищена таблица: {table}")
|
||||
except sqlite3.OperationalError as e:
|
||||
print(f" Таблица {table} не существует или ошибка: {e}")
|
||||
|
||||
# Сбрасываем счетчики автоинкремента
|
||||
try:
|
||||
cursor.execute("DELETE FROM sqlite_sequence")
|
||||
except:
|
||||
pass
|
||||
|
||||
cursor.execute("PRAGMA foreign_keys = ON")
|
||||
conn.commit()
|
||||
conn.close()
|
||||
print("✅ База данных очищена")
|
||||
|
||||
|
||||
def create_test_data():
|
||||
"""Создание тестовых данных"""
|
||||
conn = sqlite3.connect(DB_NAME)
|
||||
cursor = conn.cursor()
|
||||
|
||||
print("\n🚀 Начинаем создание тестовых данных...")
|
||||
|
||||
# 1. Создаем теги
|
||||
print("\n📌 Создаем теги...")
|
||||
tag_ids = {}
|
||||
for category, tags in TAGS.items():
|
||||
for tag in tags:
|
||||
try:
|
||||
cursor.execute(
|
||||
"INSERT INTO tags (name, category) VALUES (?, ?)",
|
||||
(tag, category)
|
||||
)
|
||||
tag_ids[tag] = cursor.lastrowid
|
||||
print(f" ✓ Добавлен тег: {tag} ({category})")
|
||||
except sqlite3.IntegrityError:
|
||||
# Тег уже существует
|
||||
cursor.execute("SELECT id FROM tags WHERE name = ?", (tag,))
|
||||
tag_ids[tag] = cursor.fetchone()[0]
|
||||
print(f" • Тег уже существует: {tag}")
|
||||
|
||||
# 2. Создаем админа
|
||||
print("\n👑 Создаем администратора...")
|
||||
admin_password = hash_password("admin123")
|
||||
try:
|
||||
cursor.execute("""
|
||||
INSERT INTO users (full_name, email, phone, telegram, password_hash, role, is_admin)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
""", (
|
||||
"Admin Adminov",
|
||||
"admin@rabota.today",
|
||||
"+7 (999) 999-99-99",
|
||||
"@admin",
|
||||
admin_password,
|
||||
"admin",
|
||||
1
|
||||
))
|
||||
print(" ✓ Администратор создан")
|
||||
except sqlite3.IntegrityError:
|
||||
print(" • Администратор уже существует")
|
||||
|
||||
# 3. Создаем работодателей и их компании
|
||||
print("\n🏢 Создаем работодателей...")
|
||||
employer_ids = []
|
||||
|
||||
for i, company in enumerate(COMPANIES[:15]): # Берем первые 15 компаний
|
||||
# Выбираем имя и фамилию
|
||||
first_name = random.choice(FIRST_NAMES)
|
||||
last_name = random.choice(LAST_NAMES)
|
||||
full_name = f"{first_name} {last_name}"
|
||||
|
||||
# Генерируем email на латинице с доменом компании
|
||||
email = generate_email(first_name, last_name, company['name'].lower())
|
||||
|
||||
phone = f"+7 (9{random.randint(10, 99)}) {random.randint(100, 999)}-{random.randint(10, 99)}-{random.randint(10, 99)}"
|
||||
telegram = f"@{transliterate(first_name)}_{random.randint(1, 999)}"
|
||||
password = hash_password("password123")
|
||||
|
||||
try:
|
||||
cursor.execute("""
|
||||
INSERT INTO users (full_name, email, phone, telegram, password_hash, role, is_admin)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
""", (full_name, email, phone, telegram, password, "employer", 0))
|
||||
|
||||
employer_id = cursor.lastrowid
|
||||
employer_ids.append(employer_id)
|
||||
print(f" ✓ Создан работодатель: {full_name}")
|
||||
print(f" Email: {email}")
|
||||
|
||||
# Создаем компанию для работодателя
|
||||
description = random.choice(COMPANY_DESCRIPTIONS)
|
||||
address = f"г. Москва, ул. {random.choice(['Tverskaya', 'Nevskogo', 'Lenina'])}, д. {random.randint(1, 50)}"
|
||||
company_phone = f"+7 (495) {random.randint(100, 999)}-{random.randint(10, 99)}-{random.randint(10, 99)}"
|
||||
company_email = f"hr@{company['name'].lower()}.ru"
|
||||
|
||||
cursor.execute("""
|
||||
INSERT INTO companies (user_id, name, description, website, address, phone, email)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
""", (
|
||||
employer_id,
|
||||
company['name'],
|
||||
description,
|
||||
f"https://{company['website']}",
|
||||
address,
|
||||
company_phone,
|
||||
company_email
|
||||
))
|
||||
print(f" 🏢 Компания: {company['name']}")
|
||||
|
||||
except sqlite3.IntegrityError as e:
|
||||
print(f" ✗ Ошибка при создании работодателя: {e}")
|
||||
|
||||
# 4. Создаем соискателей
|
||||
print("\n👨💼 Создаем соискателей...")
|
||||
employee_ids = []
|
||||
|
||||
for i in range(30): # Создаем 30 соискателей
|
||||
# Выбираем имя и фамилию
|
||||
first_name = random.choice(FIRST_NAMES)
|
||||
last_name = random.choice(LAST_NAMES)
|
||||
full_name = f"{first_name} {last_name}"
|
||||
|
||||
# Генерируем email на латинице
|
||||
email = generate_email(first_name, last_name)
|
||||
|
||||
phone = f"+7 (9{random.randint(10, 99)}) {random.randint(100, 999)}-{random.randint(10, 99)}-{random.randint(10, 99)}"
|
||||
telegram = f"@{transliterate(first_name)}_{random.randint(1, 999)}"
|
||||
password = hash_password("password123")
|
||||
|
||||
try:
|
||||
cursor.execute("""
|
||||
INSERT INTO users (full_name, email, phone, telegram, password_hash, role, is_admin)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
""", (full_name, email, phone, telegram, password, "employee", 0))
|
||||
|
||||
employee_id = cursor.lastrowid
|
||||
employee_ids.append(employee_id)
|
||||
|
||||
# Создаем резюме
|
||||
desired_position = random.choice(VACANCY_TITLES)
|
||||
about_me = f"Опыт работы {random.randint(1, 10)} лет. {random.choice(['Ответственный', 'Коммуникабельный', 'Целеустремленный', 'Креативный', 'Аккуратный'])} специалист. Ищу интересные задачи и профессиональный рост."
|
||||
desired_salary = f"{random.choice(['от', 'до'])} {random.choice([50, 70, 100, 120, 150, 180, 200, 250])} 000 ₽"
|
||||
|
||||
cursor.execute("""
|
||||
INSERT INTO resumes (user_id, desired_position, about_me, desired_salary, views)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
""", (employee_id, desired_position, about_me, desired_salary, random.randint(0, 100)))
|
||||
|
||||
resume_id = cursor.lastrowid
|
||||
|
||||
# Добавляем теги к резюме (3-7 случайных тегов)
|
||||
resume_tags = random.sample(list(TAGS['skill']), random.randint(3, 7))
|
||||
for tag in resume_tags:
|
||||
tag_id = tag_ids[tag]
|
||||
cursor.execute("""
|
||||
INSERT OR IGNORE INTO resume_tags (resume_id, tag_id)
|
||||
VALUES (?, ?)
|
||||
""", (resume_id, tag_id))
|
||||
|
||||
# Добавляем опыт работы (1-3 места)
|
||||
for j in range(random.randint(1, 3)):
|
||||
years_ago = random.randint(1, 5)
|
||||
start_year = 2020 + random.randint(0, 3)
|
||||
end_year = start_year + random.randint(1, 3)
|
||||
|
||||
cursor.execute("""
|
||||
INSERT INTO work_experience (resume_id, position, company, period)
|
||||
VALUES (?, ?, ?, ?)
|
||||
""", (
|
||||
resume_id,
|
||||
random.choice(VACANCY_TITLES),
|
||||
random.choice(COMPANIES)['name'],
|
||||
f"{start_year}–{end_year if end_year <= 2025 else 2025}"
|
||||
))
|
||||
|
||||
# Добавляем образование (1-2 записи)
|
||||
for j in range(random.randint(1, 2)):
|
||||
institutions = ['MGU', 'SPbGU', 'MFTI', 'HSE', 'BMSTU', 'ITMO', 'NGU', 'UrFU']
|
||||
specialties = ['Прикладная математика', 'Программная инженерия', 'Информатика', 'Экономика',
|
||||
'Менеджмент', 'Дизайн']
|
||||
|
||||
cursor.execute("""
|
||||
INSERT INTO education (resume_id, institution, specialty, graduation_year)
|
||||
VALUES (?, ?, ?, ?)
|
||||
""", (
|
||||
resume_id,
|
||||
random.choice(institutions),
|
||||
random.choice(specialties),
|
||||
str(2015 + random.randint(0, 10))
|
||||
))
|
||||
|
||||
if i % 5 == 0:
|
||||
print(f" ✓ Создано {i + 1} соискателей...")
|
||||
|
||||
except sqlite3.IntegrityError as e:
|
||||
print(f" ✗ Ошибка при создании соискателя: {e}")
|
||||
|
||||
print(f" ✓ Всего создано соискателей: {len(employee_ids)}")
|
||||
|
||||
# 5. Создаем вакансии
|
||||
print("\n📋 Создаем вакансии...")
|
||||
vacancy_ids = []
|
||||
|
||||
for employer_id in employer_ids:
|
||||
# У каждого работодателя 3-8 вакансий
|
||||
for i in range(random.randint(3, 8)):
|
||||
title = random.choice(VACANCY_TITLES)
|
||||
salary = f"{random.choice(['от', 'до'])} {random.choice([50, 70, 100, 120, 150, 180, 200, 250, 300])} 000 ₽"
|
||||
description = random.choice(VACANCY_DESCRIPTIONS)
|
||||
contact = f"@hr_{random.choice(COMPANIES)['name'].lower()}"
|
||||
|
||||
cursor.execute("""
|
||||
INSERT INTO vacancies (user_id, title, salary, description, contact, views, is_active)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
""", (
|
||||
employer_id,
|
||||
title,
|
||||
salary,
|
||||
description,
|
||||
contact,
|
||||
random.randint(0, 500),
|
||||
1 # активна
|
||||
))
|
||||
|
||||
vacancy_id = cursor.lastrowid
|
||||
vacancy_ids.append(vacancy_id)
|
||||
|
||||
# Добавляем теги к вакансии (2-6 тегов)
|
||||
vacancy_tags = random.sample(list(TAGS['skill']), random.randint(2, 6))
|
||||
for tag in vacancy_tags:
|
||||
tag_id = tag_ids[tag]
|
||||
cursor.execute("""
|
||||
INSERT OR IGNORE INTO vacancy_tags (vacancy_id, tag_id)
|
||||
VALUES (?, ?)
|
||||
""", (vacancy_id, tag_id))
|
||||
|
||||
print(f" ✓ Создано вакансий: {len(vacancy_ids)}")
|
||||
|
||||
# 6. Создаем отклики
|
||||
print("\n✉️ Создаем отклики...")
|
||||
|
||||
statuses = ['pending', 'viewed', 'accepted', 'rejected']
|
||||
weights = [0.3, 0.3, 0.2, 0.2] # вероятности статусов
|
||||
|
||||
applications_count = 0
|
||||
|
||||
for employee_id in employee_ids[:20]: # Берем первых 20 соискателей для откликов
|
||||
# Каждый соискатель откликается на 2-8 вакансий
|
||||
for i in range(random.randint(2, 8)):
|
||||
vacancy_id = random.choice(vacancy_ids)
|
||||
|
||||
# Проверяем, не откликался ли уже
|
||||
cursor.execute("""
|
||||
SELECT id FROM applications
|
||||
WHERE vacancy_id = ? AND user_id = ?
|
||||
""", (vacancy_id, employee_id))
|
||||
|
||||
if cursor.fetchone():
|
||||
continue
|
||||
|
||||
status = random.choices(statuses, weights=weights)[0]
|
||||
message = random.choice(COVER_LETTERS) if random.random() > 0.3 else None
|
||||
|
||||
created_at = datetime.now() - timedelta(days=random.randint(1, 30))
|
||||
created_at_str = created_at.strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
cursor.execute("""
|
||||
INSERT INTO applications (vacancy_id, user_id, message, status, created_at)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
""", (vacancy_id, employee_id, message, status, created_at_str))
|
||||
|
||||
application_id = cursor.lastrowid
|
||||
applications_count += 1
|
||||
|
||||
# Если статус не pending, добавляем дату просмотра
|
||||
if status != 'pending':
|
||||
viewed_at = created_at + timedelta(hours=random.randint(1, 48))
|
||||
viewed_at_str = viewed_at.strftime("%Y-%m-%d %H:%M:%S")
|
||||
cursor.execute("""
|
||||
UPDATE applications SET viewed_at = ? WHERE id = ?
|
||||
""", (viewed_at_str, application_id))
|
||||
|
||||
# Если принято или отклонено, добавляем ответ
|
||||
if status in ['accepted', 'rejected']:
|
||||
response_message = random.choice(EMPLOYER_RESPONSES)
|
||||
response_at = created_at + timedelta(days=random.randint(1, 5))
|
||||
response_at_str = response_at.strftime("%Y-%m-%d %H:%M:%S")
|
||||
cursor.execute("""
|
||||
UPDATE applications
|
||||
SET response_message = ?, response_at = ?
|
||||
WHERE id = ?
|
||||
""", (response_message, response_at_str, application_id))
|
||||
|
||||
print(f" ✓ Создано откликов: {applications_count}")
|
||||
|
||||
# 7. Создаем избранное
|
||||
print("\n❤️ Создаем избранное...")
|
||||
|
||||
favorites_count = 0
|
||||
|
||||
for user_id in employee_ids[:15] + employer_ids[:10]: # Берем часть пользователей
|
||||
# Каждый пользователь добавляет в избранное 3-10 элементов
|
||||
for i in range(random.randint(3, 10)):
|
||||
if random.random() > 0.5 or user_id in employee_ids:
|
||||
# Добавляем вакансию в избранное
|
||||
item_id = random.choice(vacancy_ids)
|
||||
item_type = 'vacancy'
|
||||
else:
|
||||
# Добавляем резюме в избранное (только для работодателей)
|
||||
if user_id in employer_ids:
|
||||
# Берем случайного соискателя
|
||||
random_employee = random.choice(employee_ids)
|
||||
cursor.execute("SELECT id FROM resumes WHERE user_id = ?", (random_employee,))
|
||||
resume = cursor.fetchone()
|
||||
if not resume:
|
||||
continue
|
||||
item_id = resume[0]
|
||||
item_type = 'resume'
|
||||
else:
|
||||
continue
|
||||
|
||||
try:
|
||||
created_at = datetime.now() - timedelta(days=random.randint(1, 20))
|
||||
created_at_str = created_at.strftime("%Y-%m-%d %H:%M:%S")
|
||||
|
||||
cursor.execute("""
|
||||
INSERT INTO favorites (user_id, item_type, item_id, created_at)
|
||||
VALUES (?, ?, ?, ?)
|
||||
""", (user_id, item_type, item_id, created_at_str))
|
||||
favorites_count += 1
|
||||
except sqlite3.IntegrityError:
|
||||
# Уже в избранном
|
||||
pass
|
||||
|
||||
print(f" ✓ Создано записей в избранном: {favorites_count}")
|
||||
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("✅ ТЕСТОВЫЕ ДАННЫЕ УСПЕШНО СОЗДАНЫ!")
|
||||
print("=" * 60)
|
||||
print(f"👤 Пользователей: {len(employer_ids) + len(employee_ids) + 1}")
|
||||
print(f" - Админ: 1")
|
||||
print(f" - Работодателей: {len(employer_ids)}")
|
||||
print(f" - Соискателей: {len(employee_ids)}")
|
||||
print(f"🏢 Компаний: {len(employer_ids)}")
|
||||
print(f"📋 Вакансий: {len(vacancy_ids)}")
|
||||
print(f"📄 Резюме: {len(employee_ids)}")
|
||||
print(f"🏷️ Тегов: {len(tag_ids)}")
|
||||
print(f"✉️ Откликов: {applications_count}")
|
||||
print(f"❤️ Записей в избранном: {favorites_count}")
|
||||
print("=" * 60)
|
||||
print("\n🔑 ДАННЫЕ ДЛЯ ВХОДА:")
|
||||
print("-" * 60)
|
||||
print("👑 Админ:")
|
||||
print(" Email: admin@rabota.today")
|
||||
print(" Пароль: admin123")
|
||||
print("\n👨💼 Работодатель (пример):")
|
||||
if employer_ids:
|
||||
cursor = sqlite3.connect(DB_NAME).cursor()
|
||||
cursor.execute("SELECT email FROM users WHERE id = ?", (employer_ids[0],))
|
||||
employer_email = cursor.fetchone()
|
||||
if employer_email:
|
||||
print(f" Email: {employer_email[0]}")
|
||||
print(" Пароль: password123")
|
||||
print("\n👨💻 Соискатель (пример):")
|
||||
if employee_ids:
|
||||
cursor = sqlite3.connect(DB_NAME).cursor()
|
||||
cursor.execute("SELECT email FROM users WHERE id = ?", (employee_ids[0],))
|
||||
employee_email = cursor.fetchone()
|
||||
if employee_email:
|
||||
print(f" Email: {employee_email[0]}")
|
||||
print(" Пароль: password123")
|
||||
print("=" * 60)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("🔄 Начинаем подготовку тестовых данных...")
|
||||
print("=" * 60)
|
||||
|
||||
# Спрашиваем подтверждение
|
||||
response = input("Это удалит все существующие данные. Продолжить? (y/n): ")
|
||||
|
||||
if response.lower() == 'y':
|
||||
try:
|
||||
# Сначала обновляем схему базы данных
|
||||
update_database_schema()
|
||||
# Затем очищаем данные
|
||||
clear_database()
|
||||
# И создаем новые
|
||||
create_test_data()
|
||||
except Exception as e:
|
||||
print(f"\n❌ Ошибка: {e}")
|
||||
import traceback
|
||||
|
||||
traceback.print_exc()
|
||||
else:
|
||||
print("❌ Операция отменена")
|
||||
Reference in New Issue
Block a user