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 @@
"""NX AI - FastAPI, Python, Postgres, tsvector"""

# Current Version
__version__ = "2.0.1"
__version__ = "2.0.2"
3 changes: 3 additions & 0 deletions app/api/prospects/database/alter_add_flag_hide.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-- Migration: Add flag and hide columns to prospects table
ALTER TABLE prospects ADD COLUMN IF NOT EXISTS flag BOOLEAN DEFAULT FALSE;
ALTER TABLE prospects ADD COLUMN IF NOT EXISTS hide BOOLEAN DEFAULT FALSE;
24 changes: 24 additions & 0 deletions app/api/prospects/database/run_migration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Run SQL migration to add 'flag' and 'hide' columns to prospects table
from app.utils.db import get_db_connection

SQL_PATH = "app/api/prospects/database/alter_add_flag_hide.sql"

def run_migration():
with open(SQL_PATH, "r") as f:
sql = f.read()
conn_gen = get_db_connection()
conn = next(conn_gen)
cur = conn.cursor()
try:
cur.execute(sql)
conn.commit()
print("Migration successful: 'flag' and 'hide' columns added.")
except Exception as e:
print(f"Migration failed: {e}")
conn.rollback()
finally:
cur.close()
conn.close()

if __name__ == "__main__":
run_migration()
52 changes: 51 additions & 1 deletion app/api/prospects/prospects.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from app import __version__
import os
from app.utils.make_meta import make_meta
from fastapi import APIRouter, Query, Path
from fastapi import APIRouter, Query, Path, Body, HTTPException
from app.utils.db import get_db_connection

router = APIRouter()
Expand Down Expand Up @@ -61,6 +61,13 @@ def prospects_read(

from typing import Optional

# Schema for update
from pydantic import BaseModel

class ProspectUpdate(BaseModel):
flag: Optional[bool] = None
hide: Optional[bool] = None

# endpoint: /prospects/search
@router.get("/prospects/search")
def prospects_search(query: Optional[str] = Query(None, description="Search query string"),
Expand Down Expand Up @@ -194,6 +201,7 @@ def slugify(text):
return {"meta": meta, "data": data}


# endpoint: /prospects/{id}
# endpoint: /prospects/{id}
@router.get("/prospects/{id}")
def prospects_read_one(id: int = Path(..., description="ID of the prospect to retrieve")) -> dict:
Expand Down Expand Up @@ -221,4 +229,46 @@ def prospects_read_one(id: int = Path(..., description="ID of the prospect to re
finally:
cur.close()
conn.close()
return {"meta": meta, "data": data}


# PATCH endpoint to update flag/hide
@router.patch("/prospects/{id}")
def update_prospect(id: int = Path(..., description="ID of the prospect to update"), update: ProspectUpdate = Body(...)) -> dict:
"""Update flag and/or hide fields for a prospect by id."""
meta = make_meta("success", f"Updated prospect with id {id}")
conn_gen = get_db_connection()
conn = next(conn_gen)
cur = conn.cursor()
fields = []
values = []
if update.flag is not None:
fields.append("flag = %s")
values.append(update.flag)
if update.hide is not None:
fields.append("hide = %s")
values.append(update.hide)
if not fields:
raise HTTPException(status_code=400, detail="No fields to update.")
values.append(id)
try:
cur.execute(f"UPDATE prospects SET {', '.join(fields)} WHERE id = %s RETURNING *;", tuple(values))
if cur.description is not None:
row = cur.fetchone()
if row is not None:
columns = [desc[0] for desc in cur.description]
data = dict(zip(columns, row))
else:
data = None
meta = make_meta("error", f"No prospect found with id {id}")
else:
data = None
meta = make_meta("error", f"No prospect found with id {id}")
conn.commit()
except Exception as e:
data = None
meta = make_meta("error", f"Failed to update prospect: {str(e)}")
finally:
cur.close()
conn.close()
return {"meta": meta, "data": data}
Loading