Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""Python - FastAPI, Postgres, tsvector"""

# Current Version
__version__ = "2.2.4"
__version__ = "2.2.5"
19 changes: 18 additions & 1 deletion app/api/queue/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,20 @@
"""Queue Routes"""

from .queue import router as queue_router

from fastapi import APIRouter
from .routes.drop import router as drop_router
from .routes.empty import router as empty_router
from .routes.get import router as get_router

from .routes.create import router as create_router

from .routes.import_linkedin import router as import_linkedin_router
from .routes.alter import router as alter_router

router = APIRouter()
router.include_router(drop_router)
router.include_router(empty_router)
router.include_router(get_router)
router.include_router(create_router)
router.include_router(import_linkedin_router)
router.include_router(alter_router)
File renamed without changes.
File renamed without changes.
File renamed without changes.
11 changes: 11 additions & 0 deletions app/api/queue/csv/linkedin/linkedin_sample.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
First Name,Last Name,URL,Email Address,Company,Position,Connected On
Manny,Okene,https://www.linkedin.com/in/manny-o-462924138,,Premier Group Recruitment,Associate Director,29 Mar 2026
Mark Keers -,Pulse IT Recruitment Ltd,https://www.linkedin.com/in/markkeers,,Pulse IT Recruitment Ltd,IT Recruiter & Managing Director - 07500 734616,26 Mar 2026
Shaun,O'Donnell,https://www.linkedin.com/in/shaunodonnell,,Erin Associates Ltd,Director,12 Mar 2026
Kai,Kemp,https://www.linkedin.com/in/kaikemp97,,Technify Talent,Principal Consultant,04 Mar 2026
James,Ward,https://www.linkedin.com/in/james-ward-echopay,,EchoPay Technology Ltd,Managing Director,04 Mar 2026
Graham,Feegan,https://www.linkedin.com/in/grahamfeegan,,Charles Jenson Recruitment,Recruitment Director,18 Feb 2026
Nabil,Cook,https://www.linkedin.com/in/nabilcook,,OMEGA Solutions,Co-Founder & Technical Director,11 Feb 2026
Oliver,Ward,https://www.linkedin.com/in/oliver-ward-6057a1262,,EchoPay,Customer Success Manager,11 Feb 2026
🟢 Brad,Leaman,https://www.linkedin.com/in/bradleaman,,F5 Consultants,Principal Recruitment Consultant & Co-Founder,08 Feb 2026
Rupal,Gupta,https://www.linkedin.com/in/rupal-gupta-a66975214,,PRACYVA ,Senior IT Recruiter (UK/EU),04 Feb 2026
15 changes: 4 additions & 11 deletions app/api/queue/queue.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
import os
from fastapi import APIRouter, HTTPException, Query, Request, Depends
from app.utils.make_meta import make_meta
from app.utils.db import get_db_connection_direct
from app.utils.api_key_auth import get_api_key

router = APIRouter()


@router.get("/queue")
def read_queue() -> dict:
"""GET /queue: """
return {"meta": make_meta("success", "Hello from queue"), "data": {"do": "it"}}
from .routes.drop import router as drop_router
from .routes.empty import router as empty_router
from .routes.get import router as get_router
from .routes.create import router as create_router


25 changes: 25 additions & 0 deletions app/api/queue/routes/alter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
from fastapi import APIRouter, HTTPException, Body
from app.utils.make_meta import make_meta
from app.utils.db import get_db_connection_direct

router = APIRouter()

@router.post("/queue/alter/add-column")
def add_column_to_queue(
column_name: str = Body(..., embed=True),
column_type: str = Body(..., embed=True)
) -> dict:
"""POST /queue/alter/add-column: Add a new column to the queue table."""
try:
conn = get_db_connection_direct()
cursor = conn.cursor()
sql = f'ALTER TABLE queue ADD COLUMN "{column_name}" {column_type};'
cursor.execute(sql)
conn.commit()
conn.close()
return {"meta": make_meta("success", f"Column '{column_name}' added as {column_type}")}
except Exception as e:
msg = str(e)
if 'already exists' in msg:
return {"meta": make_meta("error", f"Column '{column_name}' exists")}
raise HTTPException(status_code=500, detail=msg)
25 changes: 25 additions & 0 deletions app/api/queue/routes/create.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import os
from fastapi import APIRouter, HTTPException
from app.utils.make_meta import make_meta
from app.utils.db import get_db_connection_direct

router = APIRouter()

@router.post("/queue/create")
def create_queue_table() -> dict:
"""POST /queue/create: Create the queue table from SQL script."""
try:
sql_path = os.path.join(os.path.dirname(__file__), "../sql/create_queue_table.sql")
with open(sql_path, "r") as f:
sql = f.read()
conn = get_db_connection_direct()
cursor = conn.cursor()
# Split SQL script into individual statements for PostgreSQL
statements = [s.strip() for s in sql.split(';') if s.strip()]
for statement in statements:
cursor.execute(statement)
conn.commit()
conn.close()
return {"meta": make_meta("success", "Queue table created")}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
19 changes: 19 additions & 0 deletions app/api/queue/routes/drop.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import os
from fastapi import APIRouter, HTTPException
from app.utils.make_meta import make_meta
from app.utils.db import get_db_connection_direct

router = APIRouter()

@router.post("/queue/drop")
def drop_queue_table() -> dict:
"""POST /queue/drop: Drop the queue table."""
try:
conn = get_db_connection_direct()
cursor = conn.cursor()
cursor.execute("DROP TABLE IF EXISTS queue;")
conn.commit()
conn.close()
return {"meta": make_meta("success", "Queue table dropped")}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
19 changes: 19 additions & 0 deletions app/api/queue/routes/empty.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import os
from fastapi import APIRouter, HTTPException
from app.utils.make_meta import make_meta
from app.utils.db import get_db_connection_direct

router = APIRouter()

@router.post("/queue/empty")
def empty_queue_table() -> dict:
"""POST /queue/empty: Remove all records from the queue table."""
try:
conn = get_db_connection_direct()
cursor = conn.cursor()
cursor.execute("DELETE FROM queue;")
conn.commit()
conn.close()
return {"meta": make_meta("success", "Queue table emptied")}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
47 changes: 47 additions & 0 deletions app/api/queue/routes/get.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import os
from fastapi import APIRouter, HTTPException
from app.utils.make_meta import make_meta
from app.utils.db import get_db_connection_direct

router = APIRouter()

@router.get("/queue")
def read_queue() -> dict:
"""GET /queue: Return queue table info, schema, and most recent record."""
try:
conn = get_db_connection_direct()
cursor = conn.cursor()

# 1. Count records
cursor.execute("SELECT COUNT(*) FROM queue;")
count_row = cursor.fetchone()
record_count = count_row[0] if count_row else 0

# 2. Get table schema
cursor.execute("SELECT column_name, data_type, is_nullable FROM information_schema.columns WHERE table_name = 'queue';")
schema = [
{
"name": row[0],
"type": row[1]
}
for row in cursor.fetchall()
]

# 3. Get most recently updated record
cursor.execute("SELECT * FROM queue ORDER BY updated DESC LIMIT 1;")
columns = [desc[0] for desc in cursor.description] if cursor.description else []
row = cursor.fetchone()
most_recent = dict(zip(columns, row)) if row and columns else None

conn.close()

return {
"meta": make_meta("success", "Queue table info"),
"data": {
"queued": record_count,
"most_recent": most_recent,
# "schema": schema
}
}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
46 changes: 46 additions & 0 deletions app/api/queue/routes/import_linkedin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import os
import csv
import time
from fastapi import APIRouter, HTTPException
from app.utils.make_meta import make_meta
from app.utils.db import get_db_connection_direct

router = APIRouter()

@router.post("/queue/import/linkedin")
def import_linkedin_csv() -> dict:
"""POST /queue/import/linkedin: Import data from linkedin_sample.csv into the queue table."""
csv_path = os.path.join(os.path.dirname(__file__), "../csv/linkedin/linkedin_sample.csv")
if not os.path.exists(csv_path):
raise HTTPException(status_code=404, detail="linkedin_sample.csv not found")
try:
conn = get_db_connection_direct()
cursor = conn.cursor()
with open(csv_path, newline='', encoding='utf-8') as csvfile:
reader = csv.DictReader(row for row in csvfile if not row.startswith('Notes:'))
now = int(time.time())
for row in reader:
cursor.execute(
"""
INSERT INTO queue (first_name, last_name, url, email_address, company, position, connected_on, created, updated, hidden, collection)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
""",
[
row.get('First Name'),
row.get('Last Name'),
row.get('URL'),
row.get('Email Address'),
row.get('Company'),
row.get('Position'),
row.get('Connected On'),
now,
now,
False,
'prospects'
]
)
conn.commit()
conn.close()
return {"meta": make_meta("success", "LinkedIn CSV imported")}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
2 changes: 1 addition & 1 deletion app/api/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from app.api.prompt.drop import router as drop_router
from app.api.prospects.prospects import router as prospects_router
from app.api.orders.orders import router as orders_router
from app.api.queue.queue import router as queue_router
from app.api.queue import router as queue_router

router.include_router(root_router)
router.include_router(resend_router)
Expand Down
Loading
Loading