Обновить utils/clients.py
This commit is contained in:
parent
bf84ee2820
commit
8d0cfdbe17
169
utils/clients.py
169
utils/clients.py
|
@ -12,6 +12,8 @@ from sqlalchemy import select, and_
|
||||||
from sqlalchemy.exc import IntegrityError
|
from sqlalchemy.exc import IntegrityError
|
||||||
from model.database import Client, AppliedJob, Job
|
from model.database import Client, AppliedJob, Job
|
||||||
|
|
||||||
|
from sqlalchemy import func, or_
|
||||||
|
import urllib.parse
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
import os
|
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,
|
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): #
|
user_location_type, user_locations, user_levels, user_job_types):
|
||||||
# Строим фильтры для каждого из параметров пользователя
|
title_filters = []
|
||||||
filters = []
|
location_filters = []
|
||||||
|
|
||||||
# Фильтрация по job_title (примерное совпадение)
|
# Очистка и нормализация входных данных
|
||||||
|
def clean_text(text):
|
||||||
|
return urllib.parse.unquote(text).strip().lower()
|
||||||
|
|
||||||
|
# 2. Фильтр по должностям (OR-группа)
|
||||||
if user_job_titles:
|
if user_job_titles:
|
||||||
title_filters = [Job.job_title.ilike(f"%{title}%") for title in user_job_titles]
|
seen_titles = set() # Для избежания дубликатов
|
||||||
filters.append(or_(*title_filters))
|
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 (если указано)
|
words = clean_title.split()
|
||||||
if minimum_annual_salary is not None:
|
if len(words) > 1:
|
||||||
filters.append(Job.minimum_annual_salary >= minimum_annual_salary)
|
# Для составных названий ищем все слова через 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 (если указано)
|
# 3. Фильтр по локациям (OR-группа)
|
||||||
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 (разделяем по каждому городу)
|
|
||||||
if user_locations:
|
if user_locations:
|
||||||
location_filters = [Job.location.ilike(location) for location in user_locations]
|
seen_locations = set()
|
||||||
filters.append(or_(*location_filters))
|
for location in user_locations:
|
||||||
|
clean_loc = clean_text(location)
|
||||||
|
if clean_loc in seen_locations:
|
||||||
|
continue
|
||||||
|
seen_locations.add(clean_loc)
|
||||||
|
|
||||||
# Фильтрация по job_level (если указаны)
|
location_filters.append(func.lower(Job.location).contains(clean_loc))
|
||||||
if user_levels:
|
|
||||||
filters.append(Job.job_level.in_(user_levels))
|
|
||||||
|
|
||||||
# Фильтрация по job_type (если указаны)
|
# Обработка составных локаций (City, Country)
|
||||||
if user_job_types:
|
if ',' in clean_loc:
|
||||||
filters.append(Job.job_type.in_(user_job_types))
|
main_part = clean_loc.split(',')[0].strip()
|
||||||
|
location_filters.append(func.lower(Job.location).contains(main_part))
|
||||||
|
|
||||||
# Выполняем запрос с применением всех фильтров
|
# 4. Комбинирование фильтров
|
||||||
query = select(Job).filter(*filters)
|
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)
|
result = await db.execute(query)
|
||||||
|
|
||||||
# Получаем все результаты
|
|
||||||
jobs = result.scalars().all()
|
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
|
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):
|
async def upsert_client(db: AsyncSession, user_id: str, user_login: str, user_nicename: str, user_email: str, phone: str, json_data: str):
|
||||||
# Проверяем, существует ли клиент с таким логином или email
|
# Проверяем, существует ли клиент с таким логином или email
|
||||||
async with db.begin():
|
async with db.begin():
|
||||||
|
@ -153,17 +177,53 @@ async def del_jobs(db: AsyncSession, user_id: str):
|
||||||
# return {"message": f"{len(applied_jobs)} вакансий добавлено в AppliedJob"}
|
# return {"message": f"{len(applied_jobs)} вакансий добавлено в AppliedJob"}
|
||||||
|
|
||||||
|
|
||||||
async def add_jobs(db: AsyncSession, user_id: str):
|
async def add_jobs(db: AsyncSession, user_id: str, up):
|
||||||
# Получаем все активные вакансии (предполагаю, что ты хотел использовать True, а не 3)
|
print(up)
|
||||||
query = select(Job).where(Job.active == 3)
|
|
||||||
result = await db.execute(query)
|
try:
|
||||||
jobs = result.scalars().all()
|
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:
|
if not jobs:
|
||||||
return {"message": "Нет вакансий по данному фильтру"}
|
return {"message": "Нет вакансий по данному фильтру"}
|
||||||
|
|
||||||
applied_jobs = []
|
|
||||||
scheduled_count = 0
|
scheduled_count = 0
|
||||||
|
added_count = 0
|
||||||
|
|
||||||
for job in jobs:
|
for job in jobs:
|
||||||
# Проверяем, существует ли уже такая пара client_id + job_id
|
# Проверяем, существует ли уже такая пара client_id + job_id
|
||||||
|
@ -177,18 +237,21 @@ async def add_jobs(db: AsyncSession, user_id: str):
|
||||||
existing = check_result.scalar_one_or_none()
|
existing = check_result.scalar_one_or_none()
|
||||||
|
|
||||||
if not existing:
|
if not existing:
|
||||||
# Первые 5 добавим со статусом Scheduled, остальные Backlogged
|
|
||||||
status = "Scheduled" if scheduled_count < 5 else "Backlogged"
|
status = "Scheduled" if scheduled_count < 5 else "Backlogged"
|
||||||
applied_jobs.append(
|
new_applied = AppliedJob(
|
||||||
AppliedJob(client_id=user_id, job_id=job.job_id, status=status)
|
client_id=user_id,
|
||||||
|
job_id=job.job_id,
|
||||||
|
status=status
|
||||||
)
|
)
|
||||||
if status == "Scheduled":
|
db.add(new_applied)
|
||||||
scheduled_count += 1
|
await db.commit() # коммитим каждую запись сразу
|
||||||
|
scheduled_count += 1 if status == "Scheduled" else 0
|
||||||
|
added_count += 1
|
||||||
|
|
||||||
if applied_jobs:
|
if added_count > 0:
|
||||||
db.add_all(applied_jobs)
|
return {
|
||||||
await db.commit()
|
"message": f"{added_count} вакансий добавлено в AppliedJob (Scheduled: {scheduled_count}, Backlogged: {added_count - scheduled_count})"
|
||||||
return {"message": f"{len(applied_jobs)} вакансий добавлено в AppliedJob (Scheduled: {scheduled_count})"}
|
}
|
||||||
else:
|
else:
|
||||||
return {"message": "Все вакансии уже были добавлены ранее"}
|
return {"message": "Все вакансии уже были добавлены ранее"}
|
||||||
|
|
||||||
|
@ -323,8 +386,9 @@ async def get_delite(db, data):
|
||||||
|
|
||||||
async def get_update(db: AsyncSession, data: update):
|
async def get_update(db: AsyncSession, data: update):
|
||||||
user_id = data.user_id
|
user_id = data.user_id
|
||||||
|
print(data)
|
||||||
up_client = requests.get(f"{url_up}{user_id}") # Лучше заменить на httpx.AsyncClient
|
up_client = requests.get(f"{url_up}{user_id}") # Лучше заменить на httpx.AsyncClient
|
||||||
|
print("22222")
|
||||||
if up_client.status_code == 200:
|
if up_client.status_code == 200:
|
||||||
datas = up_client.json()
|
datas = up_client.json()
|
||||||
|
|
||||||
|
@ -353,7 +417,7 @@ async def get_update(db: AsyncSession, data: update):
|
||||||
email_addr = data_dict['email_addr']
|
email_addr = data_dict['email_addr']
|
||||||
user_id = data_dict['user_id']
|
user_id = data_dict['user_id']
|
||||||
phone_num = data_dict['phone_num']
|
phone_num = data_dict['phone_num']
|
||||||
print(data_dict)
|
# print(data_dict)
|
||||||
|
|
||||||
# Обновляем или создаём клиента
|
# Обновляем или создаём клиента
|
||||||
async with db.begin():
|
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)
|
Loading…
Reference in New Issue