Add fields AppliedDate

This commit is contained in:
Xander 2025-04-15 14:34:33 +03:00
parent 6d56ad49e4
commit c296ee8caa
16 changed files with 60317 additions and 68821 deletions

17113
logs/app.log

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -20,6 +20,8 @@ from sqlalchemy import func
from routers.auth import get_current_user from routers.auth import get_current_user
from model.database import get_async_session, Job, Client, AppliedJob, User from model.database import get_async_session, Job, Client, AppliedJob, User
from datetime import datetime
router = APIRouter() router = APIRouter()
templates = Jinja2Templates(directory="templates") templates = Jinja2Templates(directory="templates")
@ -394,10 +396,20 @@ async def update_status(data: StatusUpdate,
job = await session.execute(select(AppliedJob).where(AppliedJob.id == data.job_id)) job = await session.execute(select(AppliedJob).where(AppliedJob.id == data.job_id))
job = job.scalars().first() job = job.scalars().first()
if not job: if not job:
raise HTTPException(status_code=404, detail="Job not found") raise HTTPException(status_code=404, detail="Job not found")
# job.status = data.status
# print(data.status)
# await session.commit()
job.status = data.status job.status = data.status
# Устанавливаем дату, если статус становится "Applied"
if data.status.lower() == "applied" and job.applied_on is None:
job.applied_on = datetime.utcnow()
await session.commit() await session.commit()
return {"message": "Статус обновлён", "job_id": job.id, "new_status": job.status} return {"message": "Статус обновлён", "job_id": job.id, "new_status": job.status}

File diff suppressed because it is too large Load Diff

View File

@ -123,6 +123,7 @@
<div class="mt-2"> <div class="mt-2">
<!-- <select data-placeholder="Select Status" class="select2 w-full" multiple name="status">--> <!-- <select data-placeholder="Select Status" class="select2 w-full" multiple name="status">-->
<select data-placeholder="Select Status" class="select2 w-full" multiple name="status"> <select data-placeholder="Select Status" class="select2 w-full" multiple name="status">
<option value="Backlogged">Backlogged</option>
<option value="Scheduled">Scheduled</option> <option value="Scheduled">Scheduled</option>
<option value="Requested">Requested</option> <option value="Requested">Requested</option>
<option value="In-Progress">In-Progress</option> <option value="In-Progress">In-Progress</option>

View File

@ -40,84 +40,10 @@
{% include "filtr.html" %} {% include "filtr.html" %}
{% include "tabl.html" %}
<!-- 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="text-blue-500">{{ 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.strftime('%Y-%m-%d')}}</td>
<td class="text-center border-b">{{job.job.date_posted.strftime('%Y-%m-%d')}}</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="Paused" {% if job.status == "Paused" %}selected{% endif %} disabled>Paused</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">
{% if job.applied_on %}
{{ job.applied_on.strftime('%Y-%m-%d') }}
{% else %}
-
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- END: Datatable -->
<!-- Включаем модалку --> <!-- Включаем модалку -->
<!-- Модальное окно --> <!-- Модальное окно -->
{% include "modal.html" %} {% include "modal.html" %}

View File

@ -185,7 +185,7 @@
<label>Status</label> <label>Status</label>
<div class="mt-2"> <div class="mt-2">
<select data-placeholder="Select Status" class="select2 w-full" multiple name="status"> <select data-placeholder="Select Status" class="select2 w-full" multiple name="status">
{% for option in ["Scheduled", "Requested", "In-Progress", "Paused", "Applied", "Issues Applying", "Cancelled"] %} {% for option in ["Backlogged", "Scheduled", "Requested", "In-Progress", "Paused", "Applied", "Issues Applying", "Cancelled"] %}
<option value="{{ option }}" {% if option in status %}selected{% endif %}>{{ option }}</option> <option value="{{ option }}" {% if option in status %}selected{% endif %}>{{ option }}</option>
{% endfor %} {% endfor %}
</select> </select>
@ -230,75 +230,7 @@ document.addEventListener('DOMContentLoaded', function() {
}); });
</script> </script>
<!-- BEGIN: Datatable --> {% include "tabl.html" %}
<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="text-blue-500">{{ 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.strftime('%Y-%m-%d')}}</td>
<td class="text-center border-b">{{job.job.date_posted.strftime('%Y-%m-%d')}}</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="Paused" {% if job.status == "Paused" %}selected{% endif %}>Paused</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">
{% if job.applied_on %}
{{ job.applied_on.strftime('%Y-%m-%d') }}
{% else %}
-
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- END: Datatable -->
<!-- Включаем модалку --> <!-- Включаем модалку -->
<!-- Модальное окно --> <!-- Модальное окно -->
{% include "modal.html" %} {% include "modal.html" %}

View File

@ -28,74 +28,7 @@
</style> </style>
{% include "filtr.html" %} {% include "filtr.html" %}
<!-- BEGIN: Datatable --> {% include "tabl.html" %}
<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 &#10760;</th>
<th class="border-b-2 text-center whitespace-no-wrap">Assignee &#10760;</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="text-blue-500">{{ 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.strftime('%Y-%m-%d')}}</td>
<td class="text-center border-b">{{job.job.date_posted.strftime('%Y-%m-%d')}}</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">
{% if job.applied_on %}
{{ job.applied_on.strftime('%Y-%m-%d') }}
{% else %}
-
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- END: Datatable -->
<!-- Включаем модалку --> <!-- Включаем модалку -->
<!-- Модальное окно --> <!-- Модальное окно -->
{% include "modal.html" %} {% include "modal.html" %}

View File

@ -31,74 +31,7 @@
{% include "filtr.html" %} {% include "filtr.html" %}
<!-- BEGIN: Datatable --> {% include "tabl.html" %}
<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 &#10760;</th>
<th class="border-b-2 text-center whitespace-no-wrap">Assignee &#10760;</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="text-blue-500">{{ 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.strftime('%Y-%m-%d')}}</td>
<td class="text-center border-b">{{job.job.date_posted.strftime('%Y-%m-%d')}}</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">
{% if job.applied_on %}
{{ job.applied_on.strftime('%Y-%m-%d') }}
{% else %}
-
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- END: Datatable -->
<!-- Включаем модалку --> <!-- Включаем модалку -->
<!-- Модальное окно --> <!-- Модальное окно -->
{% include "modal.html" %} {% include "modal.html" %}

View File

@ -30,74 +30,7 @@
{% include "filtr.html" %} {% include "filtr.html" %}
<!-- BEGIN: Datatable --> {% include "tabl.html" %}
<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 &#10760;</th>
<th class="border-b-2 text-center whitespace-no-wrap">Assignee &#10760;</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="text-blue-500">{{ 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.strftime('%Y-%m-%d')}}</td>
<td class="text-center border-b">{{job.job.date_posted.strftime('%Y-%m-%d')}}</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">
{% if job.applied_on %}
{{ job.applied_on.strftime('%Y-%m-%d') }}
{% else %}
-
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- END: Datatable -->
<!-- Включаем модалку --> <!-- Включаем модалку -->
<!-- Модальное окно --> <!-- Модальное окно -->
{% include "modal.html" %} {% include "modal.html" %}

77
templates/tabl.html Normal file
View File

@ -0,0 +1,77 @@
<!-- 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="text-blue-500">{{ 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.strftime('%Y-%m-%d')}}</td>
<td class="text-center border-b">{{job.job.date_posted.strftime('%Y-%m-%d')}}</td>
<td class="text-center border-b">
<select class="select2" onchange="updateStatus(this, '{{ job.id }}')">
<option value="" {% if job.status is none %}selected{% endif %} disabled></option>
<option value="Paused" {% if job.status == "Backlogged" %}selected{% endif %} disabled>Backlogged</option>
<option value="Scheduled" {% if job.status == "Scheduled" %}selected{% endif %} disabled>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="Paused" {% if job.status == "Paused" %}selected{% endif %} disabled>Paused</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">
{% if job.applied_on %}
{{ job.applied_on.strftime('%Y-%m-%d') }}
{% else %}
-
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- END: Datatable -->

View File

@ -18,6 +18,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select from sqlalchemy.future import select
# from model.database import create_async_engine, Job # from model.database import create_async_engine, Job
from model.database import get_async_session, Job from model.database import get_async_session, Job
from utils.telega import erro
from dotenv import load_dotenv from dotenv import load_dotenv
import os import os
@ -39,9 +40,11 @@ password = os.getenv('PASSWD')
# Authenticate using any Linkedin user account credentials # Authenticate using any Linkedin user account credentials
api = Linkedin(username, password)
api = Linkedin(username, password)
print(api)
async def pars_jobs(geo): async def pars_jobs(geo):
try:
search_jobs = api.search_jobs(location_geo_id = geo) search_jobs = api.search_jobs(location_geo_id = geo)
search_jobes = [ search_jobes = [
{ {
@ -63,6 +66,9 @@ async def pars_jobs(geo):
# json.dump(search_jobs, json_file, indent=4, ensure_ascii=False) # json.dump(search_jobs, json_file, indent=4, ensure_ascii=False)
print(f"Результаты успешно сохранены в {file_path}") print(f"Результаты успешно сохранены в {file_path}")
except Exception as e:
print(e)
def add_to_bd(): def add_to_bd():
@ -250,13 +256,15 @@ async def process_jobs():
async def main(): async def main():
try:
geo_list = ['100025096', '101174742', '103644278'] # ON, Canada, USA geo_list = ['100025096', '101174742', '103644278'] # ON, Canada, USA
for geo in geo_list: for geo in geo_list:
await pars_jobs(geo) await pars_jobs(geo)
await get_vakansi() await get_vakansi()
await process_jobs() # Вызываем обработку вакансий await process_jobs() # Вызываем обработку вакансий
except Exception as e:
print(e)
if __name__ == "__main__": if __name__ == "__main__":
asyncio.run(main()) asyncio.run(main())

View File

@ -116,7 +116,10 @@ async def del_jobs(db: AsyncSession, user_id: str):
jobs = await db.execute( jobs = await db.execute(
select(AppliedJob).where( select(AppliedJob).where(
AppliedJob.client_id == user_id, AppliedJob.client_id == user_id,
or_(AppliedJob.status == "Scheduled", AppliedJob.status.is_(None)) or_(
AppliedJob.status.in_(["Scheduled", "Backlogged"]),
AppliedJob.status.is_(None)
)
) )
) )
jobs = jobs.scalars().all() jobs = jobs.scalars().all()
@ -152,7 +155,7 @@ async def del_jobs(db: AsyncSession, user_id: str):
async def add_jobs(db: AsyncSession, user_id: str): async def add_jobs(db: AsyncSession, user_id: str):
# Получаем все активные вакансии (предполагаю, что ты хотел использовать True, а не 3) # Получаем все активные вакансии (предполагаю, что ты хотел использовать True, а не 3)
query = select(Job).filter(Job.active == 3) query = select(Job).where(Job.active == 3)
result = await db.execute(query) result = await db.execute(query)
jobs = result.scalars().all() jobs = result.scalars().all()
@ -160,9 +163,10 @@ async def add_jobs(db: AsyncSession, user_id: str):
return {"message": "Нет вакансий по данному фильтру"} return {"message": "Нет вакансий по данному фильтру"}
applied_jobs = [] applied_jobs = []
scheduled_count = 0
for job in jobs: for job in jobs:
# Проверка, существует ли уже AppliedJob с таким client_id и job_id # Проверяем, существует ли уже такая пара client_id + job_id
check_query = select(AppliedJob).where( check_query = select(AppliedJob).where(
and_( and_(
AppliedJob.client_id == user_id, AppliedJob.client_id == user_id,
@ -173,16 +177,20 @@ 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"
applied_jobs.append( applied_jobs.append(
AppliedJob(client_id=user_id, job_id=job.job_id, status="Scheduled") AppliedJob(client_id=user_id, job_id=job.job_id, status=status)
) )
if status == "Scheduled":
scheduled_count += 1
if applied_jobs: if applied_jobs:
db.add_all(applied_jobs) db.add_all(applied_jobs)
await db.commit() await db.commit()
print (f'{"message": f"{len(applied_jobs)} вакансий добавлено в AppliedJob"}') return {"message": f"{len(applied_jobs)} вакансий добавлено в AppliedJob (Scheduled: {scheduled_count})"}
else: else:
print (f'{"message": "Все вакансии уже были добавлены ранее"}') return {"message": "Все вакансии уже были добавлены ранее"}
async def get_applied_jobs(db, client_id: int): async def get_applied_jobs(db, client_id: int):
@ -208,6 +216,7 @@ async def get_applied_jobs(db, client_id: int):
"title": job.job_title, "title": job.job_title,
"company": job.job_company, "company": job.job_company,
"postedDate": job.date_posted, "postedDate": job.date_posted,
"AppliedDate": applied.applied_on,
"location": job.location, "location": job.location,
"jobType": job.job_type, "jobType": job.job_type,
"salary": f"${job.minimum_annual_salary}K" if job.minimum_annual_salary else "Not specified", "salary": f"${job.minimum_annual_salary}K" if job.minimum_annual_salary else "Not specified",

71
utils/fon_status.py Normal file
View File

@ -0,0 +1,71 @@
import sys
import os
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from model.database import AppliedJob, Job, async_session
import asyncio
from sqlalchemy import select, update, func
from sqlalchemy.orm import joinedload
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
# from model.database import AppliedJob, Job
from sqlalchemy.sql import and_
from sqlalchemy.orm import sessionmaker
from dotenv import load_dotenv
import os
# Загружаем переменные окружения
load_dotenv()
# Правильная строка подключения
DATABASE_URL = os.getenv('DATABASE_URL') # Должно быть "mysql+aiomysql://..." или "postgresql+asyncpg://..."
# Создаём асинхронный движок
# async_engine = create_async_engine(DATABASE_URL, echo=True)
async_engine = create_async_engine(DATABASE_URL, echo=True, pool_recycle=1800, pool_size=10, pool_pre_ping=True )
# Создаём фабрику сессий
async_session = sessionmaker(async_engine, class_=AsyncSession, expire_on_commit=False)
async def promote_backlogged_to_scheduled(db: async_session):
# Получаем всех уникальных client_id, у которых есть Backlogged
result = await db.execute(
select(AppliedJob.client_id)
.where(AppliedJob.status == "Backlogged")
.distinct()
)
client_ids = [row[0] for row in result.fetchall()]
for client_id in client_ids:
# Выбираем до 5 самых новых Backlogged вакансий для клиента
result = await db.execute(
select(AppliedJob)
.join(AppliedJob.job) # ⬅️ Явно присоединяем таблицу jobs
.options(joinedload(AppliedJob.job)) # Чтобы подгрузить Job в объект
.where(
and_(
AppliedJob.client_id == client_id,
AppliedJob.status == "Backlogged"
)
)
.order_by(Job.date_posted.desc())
.limit(5)
)
jobs_to_update = result.scalars().all()
for job in jobs_to_update:
job.status = "Scheduled" # Меняем статус
await db.commit()
return {"message": f"Обновлено клиентов: {len(client_ids)}"}
async def main():
async with async_session() as session:
await promote_backlogged_to_scheduled(session)
if __name__ == "__main__":
asyncio.run(main())

26
utils/telega.py Normal file
View File

@ -0,0 +1,26 @@
import requests
from dotenv import load_dotenv
import os
load_dotenv()
api_key = os.getenv('TGAPI_KEY')
chat = os.getenv('TGCHAT_ID')
# text = '=> Народ 🥺 упал обмен с контактами не забудь поднять'
text1 = ' => Упс 🆘 <ins><b>TECT </b></ins> ! 🥺"'
# erro(text1=' => Упс 🆘 <ins><b>TECT </b></ins> ! 🥺')
def erro(text1):
a = requests.get('https://api.telegram.org/bot{}/sendMessage'.format(api_key), params=dict(
chat_id=chat,
text= str(text1),
parse_mode='HTML'))
# if __name__ == '__main__':
# erro(text1)