This commit is contained in:
Xander 2025-03-26 11:26:38 +02:00
parent a3723bcdd6
commit 8bb87c6bba
5 changed files with 2724 additions and 14 deletions

File diff suppressed because it is too large Load Diff

View File

@ -117,10 +117,14 @@ class Job(Base):
job_level = Column(String(50), nullable=True) # Entry-level, Junior, Mid job_level = Column(String(50), nullable=True) # Entry-level, Junior, Mid
job_type = Column(String(50), nullable=True) # Full-time, Part-time job_type = Column(String(50), nullable=True) # Full-time, Part-time
days_posted = Column(Integer, nullable=True) days_posted = Column(Integer, nullable=True)
hourly_rate = Column(Float, nullable=True) hourly_rate = Column(Float, nullable=True)
link = Column(String(2083), nullable=True) # URL вакансии link = Column(String(2083), nullable=True) # URL вакансии
link_company = Column(String(2083), nullable=True) # URL компании link_company = Column(String(2083), nullable=True) # URL компании
active = Column(Boolean, default=True) # Вакансия активна? active = Column(Boolean, default=True) # Вакансия активна?
about = Column(Text, nullable=True)
date_posted = Column(DateTime)
text = Column(Text, nullable=True) text = Column(Text, nullable=True)

View File

@ -1,14 +1,17 @@
from fastapi import FastAPI, HTTPException, APIRouter, Request, Header, Depends from fastapi import FastAPI, HTTPException, APIRouter, Request, Header, Depends
from fastapi.responses import JSONResponse from fastapi.responses import JSONResponse
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
from sqlalchemy.ext.asyncio import async_sessionmaker
from typing import Dict from typing import Dict
from pydantic import BaseModel from pydantic import BaseModel
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
import json import json
from model.database import get_async_session, Client from model.database import get_async_session, Client
from utils.clients import upsert_client from utils.clients import upsert_client, del_jobs, add_jobs, get_applied_jobs
from typing import Union from typing import Union
import asyncio
router = APIRouter() router = APIRouter()
templates = Jinja2Templates(directory="templates") templates = Jinja2Templates(directory="templates")
API_KEY = "4545454" API_KEY = "4545454"
@ -38,24 +41,44 @@ async def client(data: JsonData, x_api_key: str = Header(...), db: Session = Dep
if isinstance(data.json_data, str): if isinstance(data.json_data, str):
try: try:
data.json_data = json.loads(data.json_data) data.json_data = json.loads(data.json_data)
first_name = data.json_data['first_name']
# print(first_name)
last_name = data.json_data['last_name']
email_addr = data.json_data['email_addr']
user_id = data.json_data['user_id']
phone_num = data.json_data['phone_num']
print(first_name)
# Создаем отдельные сессии для работы с БД
async_session_maker = async_sessionmaker(bind=db.bind, expire_on_commit=False)
async with async_session_maker() as db1, async_session_maker() as db2:
client_task = upsert_client(db1, user_id, first_name, last_name, email_addr, phone_num, str(data.json_data))
del_task = del_jobs(db2, user_id)
client, _ = await asyncio.gather(client_task, del_task)
# ## TODO Получить данные для фильтра!
ads = await add_jobs(db, user_id)
get_jobs = await get_applied_jobs(db, user_id)
except json.JSONDecodeError: except json.JSONDecodeError:
raise HTTPException(status_code=400, detail="Invalid JSON format") raise HTTPException(status_code=400, detail="Invalid JSON format")
print("Полученные данные:", data.json_data) print("Полученные данные:", data.json_data)
return {"message": "JSON получен", "data": "ok"} return {"message": "JSON получен", "data": get_jobs}
# first_name = parsed_data['first_name'] # data = await upsert_client(db, first_name, last_name, email_addr, parsed_data)
# last_name = parsed_data['last_name'] # client = await upsert_client(db, user_id, first_name, last_name, email_addr, phone_num, str(data.json_data))
# email_addr = parsed_data['email_addr']
# user_id = parsed_data['user_id']
# phone_num = parsed_data['phone_num']
# print(first_name) # resp = await idss(db, user_id)
# # data = await upsert_client(db, first_name, last_name, email_addr, parsed_data) # resp2 = await idss(db, user_id, first_name)
# client = await upsert_client(db, user_id, first_name, last_name, email_addr, phone_num, str(parsed_data))
# print(f"Received data: data={client}")

View File

@ -80,13 +80,14 @@ async def get_job(db: AsyncSession, job_id: str):
location = jobs['formattedLocation'] location = jobs['formattedLocation']
title = jobs['title'] title = jobs['title']
listed_at = jobs['listedAt'] listed_at = jobs['listedAt']
listed_ats = datetime.utcfromtimestamp(listed_at / 1000).strftime('%Y-%m-%d %H:%M:%S')
company_info = jobs.get("companyDetails", {}).get("com.linkedin.voyager.deco.jobs.web.shared.WebCompactJobPostingCompany", {}).get("companyResolutionResult", {}) company_info = jobs.get("companyDetails", {}).get("com.linkedin.voyager.deco.jobs.web.shared.WebCompactJobPostingCompany", {}).get("companyResolutionResult", {})
company_name = company_info.get("name", "Unknown") company_name = company_info.get("name", "Unknown")
company_url = company_info.get("url", "") company_url = company_info.get("url", "")
link = f'https://www.linkedin.com/jobs/view/{job_id}/' link = f'https://www.linkedin.com/jobs/view/{job_id}/'
# about =
workplace_types = jobs.get("workplaceTypesResolutionResults", {}) workplace_types = jobs.get("workplaceTypesResolutionResults", {})
@ -114,9 +115,12 @@ async def get_job(db: AsyncSession, job_id: str):
if job: if job:
logging.info(f"🔄 Обновление вакансии {job_id} в базе...") logging.info(f"🔄 Обновление вакансии {job_id} в базе...")
job.text = json.dumps(jobs) job.text = json.dumps(jobs)
job.about = text
job.link = link job.link = link
# job.days_posted = listed_ats
job.location = location job.location = location
job.job_company = company_name job.job_company = company_name
job.date_posted = listed_ats
job.link_company = company_url job.link_company = company_url
job.location_type = localized_name job.location_type = localized_name
else: else:

View File

@ -1,7 +1,9 @@
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select from sqlalchemy.future import select
from sqlalchemy.orm import joinedload
from sqlalchemy import or_
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
from model.database import Client from model.database import Client, AppliedJob, Job
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
@ -41,3 +43,81 @@ async def upsert_client(db: AsyncSession, user_id: str, user_login: str, user_n
except IntegrityError: except IntegrityError:
await db.rollback() # В случае ошибки откатываем изменения await db.rollback() # В случае ошибки откатываем изменения
raise raise
async def del_jobs(db: AsyncSession, user_id: str):
jobs = await db.execute(
select(AppliedJob).where(
AppliedJob.client_id == user_id,
or_(AppliedJob.status == "Scheduled", AppliedJob.status.is_(None))
)
)
jobs = jobs.scalars().all()
for job in jobs:
await db.delete(job)
await db.commit()
async def add_jobs(db: AsyncSession, user_id: str):
# Фильтруем вакансии по переданным параметрам
query = select(Job).filter(Job.active == 3)
result = await db.execute(query)
jobs = result.scalars().all() # Получаем список вакансий
if not jobs:
return {"message": "Нет вакансий по данному фильтру"}
# Создаём записи в AppliedJob
applied_jobs = [
AppliedJob(client_id=user_id, job_id=job.job_id)
for job in jobs
]
db.add_all(applied_jobs) # Добавляем в сессию
await db.commit() # Фиксируем изменения
return {"message": f"{len(applied_jobs)} вакансий добавлено в AppliedJob"}
async def get_applied_jobs(db, client_id: int):
query = (
select(AppliedJob)
.options(joinedload(AppliedJob.job)) # Подгружаем данные о вакансии
.where(AppliedJob.client_id == client_id)
)
result = await db.execute(query)
applied_jobs = result.scalars().all()
if not applied_jobs:
return {"message": "Нет откликов на вакансии"}
jobs_list = []
for applied in applied_jobs:
job = applied.job # Получаем объект Job из отношения AppliedJob.job
jobs_list.append({
"id": job.job_id,
"title": job.job_title,
"company": job.job_company,
"postedDate": job.days_posted,
"location": job.location,
"jobType": job.job_type,
"salary": f"${job.minimum_annual_salary}K" if job.minimum_annual_salary else "Not specified",
"level": job.job_level,
"status": applied.status if applied.status else "Scheduled",
"requiredSkills": "",
"aboutJob": job.about,
"jobLink": job.link
})
return jobs_list