Обновить utils/clients.py

This commit is contained in:
Alex55 2025-04-24 18:53:22 +03:00
parent bf84ee2820
commit 8d0cfdbe17
1 changed files with 460 additions and 389 deletions

View File

@ -12,6 +12,8 @@ from sqlalchemy import select, and_
from sqlalchemy.exc import IntegrityError
from model.database import Client, AppliedJob, Job
from sqlalchemy import func, or_
import urllib.parse
from dotenv import load_dotenv
import os
@ -23,53 +25,75 @@ url_up = os.getenv('UP_DOMEN')
async def get_filtered_jobs(db: AsyncSession, user_job_titles, minimum_annual_salary, salary_currency,
user_location_type, user_locations, user_levels, user_job_types): #
# Строим фильтры для каждого из параметров пользователя
filters = []
user_location_type, user_locations, user_levels, user_job_types):
title_filters = []
location_filters = []
# Фильтрация по job_title (примерное совпадение)
# Очистка и нормализация входных данных
def clean_text(text):
return urllib.parse.unquote(text).strip().lower()
# 2. Фильтр по должностям (OR-группа)
if user_job_titles:
title_filters = [Job.job_title.ilike(f"%{title}%") for title in user_job_titles]
filters.append(or_(*title_filters))
seen_titles = set() # Для избежания дубликатов
for title in user_job_titles:
clean_title = clean_text(title)
if clean_title in seen_titles:
continue
seen_titles.add(clean_title)
# Фильтрация по minimum_annual_salary (если указано)
if minimum_annual_salary is not None:
filters.append(Job.minimum_annual_salary >= minimum_annual_salary)
words = clean_title.split()
if len(words) > 1:
# Для составных названий ищем все слова через AND
word_filters = [func.lower(Job.job_title).contains(word) for word in words]
title_filters.append(and_(*word_filters))
else:
title_filters.append(func.lower(Job.job_title).contains(clean_title))
# Фильтрация по salary_currency (если указано)
if salary_currency is not None:
filters.append(Job.salary_currency == salary_currency)
# Фильтрация по location_type (если указано)
if user_location_type:
filters.append(Job.location_type == user_location_type)
# Фильтрация по location (разделяем по каждому городу)
# 3. Фильтр по локациям (OR-группа)
if user_locations:
location_filters = [Job.location.ilike(location) for location in user_locations]
filters.append(or_(*location_filters))
seen_locations = set()
for location in user_locations:
clean_loc = clean_text(location)
if clean_loc in seen_locations:
continue
seen_locations.add(clean_loc)
# Фильтрация по job_level (если указаны)
if user_levels:
filters.append(Job.job_level.in_(user_levels))
location_filters.append(func.lower(Job.location).contains(clean_loc))
# Фильтрация по job_type (если указаны)
if user_job_types:
filters.append(Job.job_type.in_(user_job_types))
# Обработка составных локаций (City, Country)
if ',' in clean_loc:
main_part = clean_loc.split(',')[0].strip()
location_filters.append(func.lower(Job.location).contains(main_part))
# Выполняем запрос с применением всех фильтров
query = select(Job).filter(*filters)
# 4. Комбинирование фильтров
final_filters = []
if title_filters:
final_filters.append(or_(*title_filters))
if location_filters:
final_filters.append(or_(*location_filters))
if not final_filters:
return []
# 5. Формирование и выполнение запроса
query = select(Job).filter(*final_filters)
# Для отладки
print("Final query:", str(query))
# Выполняем асинхронный запрос
result = await db.execute(query)
# Получаем все результаты
jobs = result.scalars().all()
print(f"Found {len(jobs)} matching jobs")
for job in jobs:
print(f"Match: {job.job_title} | {job.location}")
return jobs
async def upsert_client(db: AsyncSession, user_id: str, user_login: str, user_nicename: str, user_email: str, phone: str, json_data: str):
# Проверяем, существует ли клиент с таким логином или email
async with db.begin():
@ -153,17 +177,53 @@ async def del_jobs(db: AsyncSession, user_id: str):
# return {"message": f"{len(applied_jobs)} вакансий добавлено в AppliedJob"}
async def add_jobs(db: AsyncSession, user_id: str):
# Получаем все активные вакансии (предполагаю, что ты хотел использовать True, а не 3)
query = select(Job).where(Job.active == 3)
result = await db.execute(query)
jobs = result.scalars().all()
async def add_jobs(db: AsyncSession, user_id: str, up):
print(up)
try:
user_data = up
print(type(user_data))
job_preferences = user_data.get('job_preferences', {})
job_titles = job_preferences.get('job_titles', [])
locations = job_preferences.get('locations', [])
location_types = [k for k, v in job_preferences.get('location_types', {}).items() if v is True]
job_levels = [k for k, v in job_preferences.get('job_levels', {}).items() if v is True]
job_types = [k for k, v in job_preferences.get('job_types', {}).items() if v is True]
print("Job Titles:", job_titles)
print("Locations:", locations)
print("Location Types (True only):", location_types)
print("Job Levels (True only):", job_levels)
print("Job Types (True only):", job_types)
except json.JSONDecodeError as e:
print("Ошибка декодирования JSON:", e)
jobs = await get_filtered_jobs(
db,
user_job_titles=job_titles,
minimum_annual_salary=None,
salary_currency=None,
user_location_type=None,
user_locations=locations,
user_levels=None,
user_job_types=None
)
for job in jobs:
print(job.job_title, job.location, job.job_level, job.job_type)
# # Получаем все активные вакансии (предполагаю, что ты хотел использовать True, а не 3)
# # query = select(Job).where(Job.active == 3)
# # result = await db.execute(query)
# # jobs = result.scalars().all()
if not jobs:
return {"message": "Нет вакансий по данному фильтру"}
applied_jobs = []
scheduled_count = 0
added_count = 0
for job in jobs:
# Проверяем, существует ли уже такая пара client_id + job_id
@ -177,18 +237,21 @@ async def add_jobs(db: AsyncSession, user_id: str):
existing = check_result.scalar_one_or_none()
if not existing:
# Первые 5 добавим со статусом Scheduled, остальные Backlogged
status = "Scheduled" if scheduled_count < 5 else "Backlogged"
applied_jobs.append(
AppliedJob(client_id=user_id, job_id=job.job_id, status=status)
new_applied = AppliedJob(
client_id=user_id,
job_id=job.job_id,
status=status
)
if status == "Scheduled":
scheduled_count += 1
db.add(new_applied)
await db.commit() # коммитим каждую запись сразу
scheduled_count += 1 if status == "Scheduled" else 0
added_count += 1
if applied_jobs:
db.add_all(applied_jobs)
await db.commit()
return {"message": f"{len(applied_jobs)} вакансий добавлено в AppliedJob (Scheduled: {scheduled_count})"}
if added_count > 0:
return {
"message": f"{added_count} вакансий добавлено в AppliedJob (Scheduled: {scheduled_count}, Backlogged: {added_count - scheduled_count})"
}
else:
return {"message": "Все вакансии уже были добавлены ранее"}
@ -323,8 +386,9 @@ async def get_delite(db, data):
async def get_update(db: AsyncSession, data: update):
user_id = data.user_id
print(data)
up_client = requests.get(f"{url_up}{user_id}") # Лучше заменить на httpx.AsyncClient
print("22222")
if up_client.status_code == 200:
datas = up_client.json()
@ -353,7 +417,7 @@ async def get_update(db: AsyncSession, data: update):
email_addr = data_dict['email_addr']
user_id = data_dict['user_id']
phone_num = data_dict['phone_num']
print(data_dict)
# print(data_dict)
# Обновляем или создаём клиента
async with db.begin():
@ -387,3 +451,10 @@ async def get_update(db: AsyncSession, data: update):
async def get_users(db: AsyncSession, data: update):
user_id = data.user_id
client = await db.get(Client, user_id)
return
print(client.json_data)