This commit is contained in:
Xander 2025-03-31 15:10:20 +03:00
parent af30da1f6d
commit 456ad55d01
10 changed files with 97480 additions and 52569 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

50491
logs/app.log.2 Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,6 @@
from fastapi import FastAPI, HTTPException, APIRouter, Request, Header, Depends
from fastapi.responses import JSONResponse
import json
from fastapi.templating import Jinja2Templates
from sqlalchemy.ext.asyncio import async_sessionmaker
from typing import Dict
@ -7,7 +8,7 @@ from pydantic import BaseModel
from sqlalchemy.orm import Session
import json
from model.database import get_async_session, Client
from utils.clients import upsert_client, del_jobs, add_jobs, get_applied_jobs, get_filtered_jobs
from utils.clients import upsert_client, del_jobs, add_jobs, get_applied_jobs, get_filtered_jobs, client_list
from typing import Union
import asyncio
@ -36,8 +37,11 @@ clients = {
44: {"username": "Jane Smith", "email": "jane@example.com", "phone": "+987654321"}
}
@router.get("/get_client/{client_id}", include_in_schema=False)
async def get_client_modal(client_id: int):
client = clients.get(client_id) # Используй clients вместо clients_db
async def get_client_modal(client_id: int, db: Session = Depends(get_async_session)):
# client = clients.get(client_id) # Используй clients вместо clients_db
# print(f"==============================={type(client)}")
client = await client_list(client_id, db)
if not client:
raise HTTPException(status_code=404, detail="Client not found")
return JSONResponse(content=client)
@ -118,12 +122,46 @@ async def client(data: JsonData, x_api_key: str = Header(...), db: Session = Dep
# print(f"Неверный формат данных: {type(data.json_data)}")
raise HTTPException(status_code=400, detail="Invalid data format")
return {"message": "JSON получен", "data": jobs }
return {"status": "ok", "message": "JSON получен"}
@router.post("/client_update")
async def client_update(data: JsonData, x_api_key: str = Header(...), db: Session = Depends(get_async_session)):
if x_api_key != "4545454":
raise HTTPException(status_code=403, detail="Invalid API Key")
# Если json_data строка, декодируем её в словарь
if isinstance(data.json_data, str):
try:
data.json_data = json.loads(data.json_data) # Декодируем строку в словарь
except json.JSONDecodeError:
raise HTTPException(status_code=400, detail="Invalid JSON format")
if isinstance(data.json_data, dict):
try:
user_id = data.json_data['user_id']
print(f"Полученные заявки: {get_jobs}")
except KeyError as e:
print(f"Ошибка при извлечении данных: {e}")
raise HTTPException(status_code=400, detail="Missing required field in json_data")
else:
print(f"Неверный формат данных: {type(data.json_data)}")
raise HTTPException(status_code=400, detail="Invalid data format")
return {"status": "ok", "message": "JSON получен" }
@router.post("/client_jobs/")
async def client(data: JsonData, x_api_key: str = Header(...), db: Session = Depends(get_async_session)):
async def client_jobs(data: JsonData, x_api_key: str = Header(...), db: Session = Depends(get_async_session)):
if x_api_key != "4545454":
raise HTTPException(status_code=403, detail="Invalid API Key")
@ -154,3 +192,73 @@ async def client(data: JsonData, x_api_key: str = Header(...), db: Session = Dep
raise HTTPException(status_code=400, detail="Invalid data format")
return {"message": "JSON получен", "data": get_jobs}
@router.post("/avtopilot")
async def avtopilot(data: JsonData, x_api_key: str = Header(...), db: Session = Depends(get_async_session)):
if x_api_key != "4545454":
raise HTTPException(status_code=403, detail="Invalid API Key")
# Если json_data строка, декодируем её в словарь
if isinstance(data.json_data, str):
try:
data.json_data = json.loads(data.json_data) # Декодируем строку в словарь
except json.JSONDecodeError:
raise HTTPException(status_code=400, detail="Invalid JSON format")
if isinstance(data.json_data, dict):
try:
user_id = data.json_data['user_id']
print(f"Полученные заявки: {get_jobs}")
except KeyError as e:
print(f"Ошибка при извлечении данных: {e}")
raise HTTPException(status_code=400, detail="Missing required field in json_data")
else:
print(f"Неверный формат данных: {type(data.json_data)}")
raise HTTPException(status_code=400, detail="Invalid data format")
return {"status": "ok", "message": "JSON получен" }
@router.post("/jobs_delete")
async def jobs_delete(data: JsonData, x_api_key: str = Header(...), db: Session = Depends(get_async_session)):
if x_api_key != "4545454":
raise HTTPException(status_code=403, detail="Invalid API Key")
# Если json_data строка, декодируем её в словарь
if isinstance(data.json_data, str):
try:
data.json_data = json.loads(data.json_data) # Декодируем строку в словарь
except json.JSONDecodeError:
raise HTTPException(status_code=400, detail="Invalid JSON format")
if isinstance(data.json_data, dict):
try:
user_id = data.json_data['user_id']
print(f"Полученные заявки: {get_jobs}")
except KeyError as e:
print(f"Ошибка при извлечении данных: {e}")
raise HTTPException(status_code=400, detail="Missing required field in json_data")
else:
print(f"Неверный формат данных: {type(data.json_data)}")
raise HTTPException(status_code=400, detail="Invalid data format")
return {"status": "ok", "message": "JSON получен" }

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
<!-- Модальное окно &times;-->
<div id="client-modal" class="fixed inset-0 hidden bg-gray-800 bg-opacity-75 flex items-center justify-center z-50">
<div class="bg-white rounded-lg p-6 w-1/3 relative shadow-2xl">
<div class="bg-white rounded-lg p-6 w-4/5 relative shadow-2xl">
<span id="close-modal" class="absolute top-2 right-4 text-xl cursor-pointer"></span>
<h2 class="modal__content">Client Details</h2>
<div class="post intro-y overflow-hidden box mt-5">
@ -16,36 +16,54 @@
</div>
<div class="post__content tab-content">
<div class="tab-content__pane p-5 active" id="content">
<div class="border border-gray-200 rounded-md p-5 mt-5">
<p><strong>Name:</strong> <span id="client-name"></span></p>
<p><strong>Email:</strong> <span id="client-email"></span></p>
<p><strong>Phone:</strong> <span id="client-phone"></span></p>
</div>
<div class="tab-content__pane p-5 active" id="content">
<h2 class="font-medium text-base mr-auto"> INFO</h2>
<div class="border border-gray-200 rounded-md p-5 mt-5">
<p class="font-medium"><strong>Name:</strong> <span id="client-name"></span></p>
<p class="font-medium"><strong>Email:</strong> <span id="client-email"></span></p>
<p class="font-medium"><strong>Phone:</strong> <span id="client-phone"></span></p>
</div>
</div>
</div>
<div class="tab-content__pane p-5 " id="prom">
<div class="border border-gray-200 rounded-md p-5 mt-5">
</div>
</div>
<div class="tab-content__pane p-5" id="rozetka">
<div class="border border-gray-200 rounded-md p-5 mt-5">
<div class="tab-content__pane p-5 " id="prom">
<div class="border border-gray-200 rounded-md p-5 mt-5">
<div class="grid grid-cols-12 gap-6">
<div class="intro-y box px-5 pt-5 mt-5">
<div class="flex flex-col lg:flex-row border-b border-gray-200 pb-5 -mx-5">
<div class="flex flex-1 px-5 items-center justify-center lg:justify-start">
<div class="ml-5">
<div class="w-24 sm:w-40 truncate sm:whitespace-normal font-medium text-lg"><span id="client-name2"></span></div>
<div class="text-gray-600">Frontend Engineer</div>
</div>
</div>
</div>
</div>
<!--<div class="intro-y box col-span-12 lg:col-span-6">
<div class="flex items-center p-5 border-b border-gray-200">
<h2 class="font-medium text-base mr-auto">
Top Categories
</h2>
</div>
</div>-->
</div>
</div>
</div>
<div class="tab-content__pane p-5" id="rozetka">
<div class="border border-gray-200 rounded-md p-5 mt-5">
</div>
</div>
@ -77,9 +95,13 @@ document.addEventListener("DOMContentLoaded", () => {
fetch(`/get_client/${clientId}`)
.then(response => response.json())
.then(data => {
document.getElementById("client-name").textContent = data.username;
document.getElementById("client-email").textContent = data.email;
document.getElementById("client-phone").textContent = data.phone;
console.log("Ответ от сервера:", data); // Проверяем, что данные пришли
console.log("Перед выборкой элементов DOM");
document.getElementById("client-name").textContent = data.first_name+ ' ' + data.last_name;
document.getElementById("client-email").textContent = data.email_addr;
document.getElementById("client-phone").textContent = data.phone_num;
document.getElementById("client-name2").textContent = data.first_name+ ' ' + data.last_name;
modal.classList.remove("hidden");
})
.catch(err => console.error("Error fetching client data:", err));

View File

@ -8,7 +8,7 @@
<h2 class="text-lg font-medium mr-auto">
Tasks
</h2>
<!-- BEGIN: Inbox Filter
<!-- BEGIN: Inbox Filter -->
<div class="intro-y flex flex-col-reverse sm:flex-row items-center">
<div class="w-full sm:w-auto relative mr-auto mt-3 sm:mt-0">
<i class="w-4 h-4 absolute my-auto inset-y-0 ml-3 left-0 z-10 text-gray-700" data-feather="search"></i>
@ -60,7 +60,7 @@
</div>
<div class="col-span-6">
<div class="text-xs">Assignee</div>
<select class="input w-full border mt-2 flex-1">
<select class="select2 w-full" multiple>
<option value="" selected disabled>Выберите</option>
<option>-</option>
<option>-</option>
@ -70,8 +70,8 @@
</div>
<div class="col-span-6">
<div class="text-xs">Status</div>
<select class="input w-full border mt-2 flex-1">
<option value="" selected disabled>Выберите</option>
<select class="select2 w-full" multiple>
<option>Scheduled</option>
<option>Requested</option>
<option>Applying</option>
@ -95,7 +95,7 @@
</div>
</div>
</div>
END: Inbox Filter -->
<!-- END: Inbox Filter -->
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productuj'">Unasigned Jobs</button>
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productmj'">My Jobs</button>

172
templates/products.html Normal file
View File

@ -0,0 +1,172 @@
{% extends "base.html" %}
{% block title %}Главная{% endblock %}
{% block content %}
<div class="intro-y flex flex-col sm:flex-row items-center mt-8">
<h2 class="text-lg font-medium mr-auto">
Tasks
</h2>
<!-- BEGIN: Inbox Filter
<div class="intro-y flex flex-col-reverse sm:flex-row items-center">
<div class="w-full sm:w-auto relative mr-auto mt-3 sm:mt-0">
<i class="w-4 h-4 absolute my-auto inset-y-0 ml-3 left-0 z-10 text-gray-700" data-feather="search"></i>
<input type="text" class="input w-full sm:w-64 box px-10 text-gray-700 placeholder-theme-13" placeholder="Filter">
<div class="inbox-filter dropdown absolute inset-y-0 mr-3 right-0 flex items-center">
<i class="dropdown-toggle w-4 h-4 cursor-pointer text-gray-700" data-feather="chevron-down"></i>
<div class="inbox-filter__dropdown-box dropdown-box mt-10 absolute top-0 left-0 z-20">
<div class="dropdown-box__content box p-5">
<div class="grid grid-cols-12 gap-4 row-gap-3">
<div class="col-span-6">
<div class="text-xs">Requested o</div>
<select class="input w-full border mt-2 flex-1">
<option value="" selected disabled>Выберите</option>
<option>Сегодня</option>
<option>Последние 7 дней</option>
<option>За все время</option>
<option>От даты - до даты.</option>
</select>
</div>
<div class="col-span-6">
<div class="text-xs">Posted on</div>
<select class="input w-full border mt-2 flex-1">
<option value="" selected disabled>Выберите</option>
<option>Сегодня</option>
<option>Последние 7 дней</option>
<option>За все время</option>
<option>От даты - до даты.</option>
</select>
</div>
<div class="col-span-6">
<div class="text-xs">Applied on</div>
<select class="input w-full border mt-2 flex-1">
<option value="" selected disabled>Выберите</option>
<option>Сегодня</option>
<option>Последние 7 дней</option>
<option>За все время</option>
<option>От даты - до даты.</option>
</select>
</div>
<div class="col-span-6">
<div class="text-xs">Client</div>
<select class="input w-full border mt-2 flex-1">
<option value="" selected disabled>Выберите</option>
<option>-</option>
<option>-</option>
<option>-</option>
<option>-</option>
</select>
</div>
<div class="col-span-6">
<div class="text-xs">Assignee</div>
<select class="select2 w-full" multiple>
<option value="" selected disabled>Выберите</option>
<option>-</option>
<option>-</option>
<option>-</option>
<option>-</option>
</select>
</div>
<div class="col-span-6">
<div class="text-xs">Status</div>
<select class="select2 w-full" multiple>
<option>Scheduled</option>
<option>Requested</option>
<option>Applying</option>
<option>Applied</option>
</select>
</div>
<div class="col-span-12 flex items-center mt-3">
<button class="button w-32 justify-center block bg-theme-1 text-white ml-2">Search</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="w-full sm:w-auto flex">
<div class="dropdown relative">
</div>
</div>
</div>
END: Inbox Filter -->
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productuj'">Unasigned Jobs</button>
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productmj'">My Jobs</button>
<button class="button text-white bg-red-500 hover:bg-red-700 shadow-md mr-2" onclick="window.location.href='/product'">All Jobs</button>
<button class="button text-white bg-theme-1 shadow-md mr-2" onclick="window.location.href='/productoj'">Outstanding Jobs</button>
</div>
<!-- BEGIN: Datatable -->
<div class="intro-y datatable-wrapper box p-5 mt-5">
<table class="table table-report table-report--bordered display datatable w-full">
<thead>
<tr>
<th class="border-b-2 whitespace-no-wrap">TITLE &#10760;</th>
<th class="border-b-2 text-center whitespace-no-wrap">COMPANY &#10760;</th>
<th class="border-b-2 text-center whitespace-no-wrap">CLIENT &#10760;</th>
<th class="border-b-2 text-center whitespace-no-wrap">Requested on &#10760;</th>
<th class="border-b-2 text-center whitespace-no-wrap">Posted on &#10760;</th>
<th class="border-b-2 text-center whitespace-no-wrap">STATUS</th>
<th class="border-b-2 text-center whitespace-no-wrap">Assignee</th>
<th class="border-b-2 text-center whitespace-no-wrap">Applied on</th>
</tr>
</thead>
<tbody>
{% for job in jobs %}
<tr>
<td class="border-b">
<a href="{{ job.job.link }}" target="_blank" class="font-medium whitespace-no-wrap">{{ job.job.job_title [:50] }}</a>
<div class="text-gray-600 text-xs whitespace-no-wrap">{{ job.job.job_id }}</div>
</td>
<td class="text-center border-b">{{job.job.job_company}}</td>
<td class="text-center border-b">
<a href="#" class="client-link text-blue-500" data-client-id="{{ job.client.id }}">{{ job.client.user_nicename }}</a>
</td>
<td class="text-center border-b">{{job.job.data_requested}}</td>
<td class="text-center border-b">{{job.job.date_posted}}</td>
<td class="text-center border-b">
<select class="select2" onchange="updateStatus(this, '{{ job.id }}')">
<option value="" {% if job.status is none %}selected{% endif %}>— Not selected —</option>
<option value="Scheduled" {% if job.status == "Scheduled" %}selected{% endif %}>Scheduled</option>
<option value="Requested" {% if job.status == "Requested" %}selected{% endif %}>Requested</option>
<option value="In-Progress" {% if job.status == "In-Progress" %}selected{% endif %}>In-Progress</option>
<option value="Applied" {% if job.status == "Applied" %}selected{% endif %}>Applied</option>
<option value="Issues Applying" {% if job.status == "Issues Applying" %}selected{% endif %}>Issues Applying</option>
<option value="Cancelled" {% if job.status == "Cancelled" %}selected{% endif %}>Cancelled</option>
</select>
</td>
<td class="text-center border-b">
<select class="select2" onchange="updateAssignee(this, '{{ job.id }}')">
<option value="" {% if job.assignee is none %}selected{% endif %}>— Not selected —</option>
{% for user in users %}
<option value="{{ user.id }}" {% if job.assignee == user.id %}selected{% endif %}>
{{ user.username }}
</option>
{% endfor %}
</select>
</td>
<td class="text-center border-b">-</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- END: Datatable -->
<!-- Включаем модалку -->
<!-- Модальное окно -->
{% include "modal.html" %}
<script src="/static/dist/js/prod.js"></script>
{% endblock %}

View File

@ -152,6 +152,7 @@ async def get_job(db: AsyncSession, job_id: str):
job.location_type = localized_name
job.job_level = level
job.job_type = job_type
job.days_posted = 5
else:
logging.info(f"🆕 Добавление вакансии {job_id} в базу...")
job = Job(
@ -195,7 +196,9 @@ async def get_or_create_jobs(db: AsyncSession, job_id: int, titles: str):
if not job:
job = Job(
job_id=job_id,
job_title=titles
job_title=titles,
days_posted=7
)
db.add(job)
await db.commit()
@ -216,7 +219,9 @@ async def get_vakansi():
with open(file_path, "r", encoding="utf-8") as json_file:
data = json.load(json_file)
async with async_session_maker() as session: # Создаём сессию здесь!
# async with async_session_maker() as session: # Создаём сессию здесь!
async for session in get_async_session():
for d in data:
title = d.get("title", "")
job_id = d.get("entityUrn", "")
@ -229,10 +234,8 @@ async def get_vakansi():
geo = '100025096'
# geo = '100025096'
# pars_jobs(geo)
# pars_jobs(geo)
# get_vakansi()
@ -240,12 +243,24 @@ geo = '100025096'
# await get_vakansi()
#[]TODO!!!
async def main():
async for db in get_async_session(): # Асинхронный генератор сессий
query = select(Job).filter(Job.days_posted == 7)
result = await db.execute(query)
jobs = result.scalars().all() # Получаем ВСЕ записи в виде списка
for job in jobs:
print(job.job_id)
await get_job(db, job.job_id)
# if __name__ == "__main__":
# asyncio.run(main())
if __name__ == "__main__":
asyncio.run(main())
# from sqlalchemy.orm import sessionmaker, declarative_base
# from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
@ -282,18 +297,6 @@ geo = '100025096'
async def main():
async for db in get_async_session(): # Асинхронный генератор сессий
query = select(Job).filter(Job.active == 6)
result = await db.execute(query)
jobs = result.scalars().all() # Получаем ВСЕ записи в виде списка
for job in jobs:
print(job.job_id)
await get_job(db, job.job_id)
if __name__ == "__main__":
asyncio.run(main())

View File

@ -1,3 +1,6 @@
import json
import ast
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from sqlalchemy.orm import joinedload
@ -173,4 +176,22 @@ async def get_applied_jobs(db, client_id: int):
async def client_list(client_id: int, db):
result = await db.execute(
select(Client).filter((Client.id == client_id))# | (Client.user_email == user_email))
)
clients = result.scalars().first()
clients_str= clients.json_data
# Если клиент найден
if clients:
client_dict = ast.literal_eval(clients_str)
# result = {client_id: client_dict}
print(f"===============================!!!!!{type(client_dict)}")
return client_dict
else:
# Если клиент не найден, возвращаем None или обрабатываем ошибку
# return None
print("NOTTTTTTTTTTTTTTTTTTTTTTTTTTTTT")