Compare commits

...

2 Commits

Author SHA1 Message Date
4e619ae414
Added routes descriptions and healthcheck schema 2023-09-21 23:13:57 +03:00
439170af4f
Added geocoded results for string search 2023-09-21 23:08:40 +03:00
6 changed files with 62 additions and 7 deletions

View File

@ -8,6 +8,8 @@ from sqlalchemy.orm import Session
from sqlalchemy.sql import operators from sqlalchemy.sql import operators
from sqlalchemy.sql.expression import BinaryExpression from sqlalchemy.sql.expression import BinaryExpression
from rosseti_parser import get_building_id
from . import models, schemas from . import models, schemas
@ -81,6 +83,11 @@ def search_all(db: Session, prompt: str) -> List[schemas.Record]:
'res' 'res'
), contains_lower('comment', prompt)) ), contains_lower('comment', prompt))
building_id, *_ = get_building_id(prompt)
if building_id is not None:
query |= models.Record.building_id == building_id
res = db.query(models.Record).filter(query).all() res = db.query(models.Record).filter(query).all()
return res return res

View File

@ -4,7 +4,7 @@ import datetime
from fastapi import FastAPI from fastapi import FastAPI
import schedule import schedule
from . import models, router from . import models, router, schemas
from .database import engine from .database import engine
from .scheduler import run_continuously, run_threaded from .scheduler import run_continuously, run_threaded
from .job import job from .job import job
@ -30,8 +30,8 @@ app = FastAPI(lifespan=lifespan)
app.include_router(router.router) app.include_router(router.router)
@app.get('/') @app.get('/', response_model=schemas.Healthcheck)
def root(): def Healthcheck():
return { return {
"up_since": start_stamp "up_since": start_stamp
} }

View File

@ -10,24 +10,65 @@ from .database import SessionLocal, get_db
router = APIRouter(prefix='/api') router = APIRouter(prefix='/api')
@router.get('/list', response_model=List[schemas.Record]) @router.get('/list', response_model=List[schemas.Record], summary="Search by filters")
def list_rows( def list_rows(
filters: Annotated[schemas.RecordRequest, Depends()], filters: Annotated[schemas.RecordRequest, Depends()],
db: Session = Depends(get_db) db: Session = Depends(get_db)
): ):
"""
Searches rows with specified filters.
Case insensitive contains:
- **region**
- **area**
- **town**
- **street**
- **start**
- **finish**
- **branch**
- **res**
- **comment**
Exact match:
- **index**
- **building_id**
- **lat**
- **lng**
Later or earlier than respectively:
- **start**
- **finish**
"""
return controller.search_each(db, filters) return controller.search_each(db, filters)
@router.get('/search', response_model=List[schemas.Record]) @router.get('/search', response_model=List[schemas.Record], summary="Search by query")
def search_rows(query: str, db: Session = Depends(get_db)): def search_rows(query: str, db: Session = Depends(get_db)):
"""
Selects rows with cells containing case insensitive prompt as its part.
In addition, geocoding is being applied to prompt and if building_id found, corresponding row is being returned.
Rows to be searched:
- **region**
- **area**
- **town**
- **street**
- **branch**
- **res**
- **comment**
"""
return controller.search_all(db, query) return controller.search_all(db, query)
@router.get('/check', response_model=schemas.CheckResponse) @router.get('/check', response_model=schemas.CheckResponse, summary="Check when outage ends")
def check(building_id: int, db: Session = Depends(get_db)): def check(building_id: int, db: Session = Depends(get_db)):
"""
Checks if there is an active outage for building_id and if there is, also returns when will it end
"""
return controller.check_outage(db, building_id) return controller.check_outage(db, building_id)
@router.put('/create', response_model=schemas.Record) @router.put('/create', response_model=schemas.Record)
def create_record(record: schemas.RecordCreate, db: Session = Depends(get_db)): def create_record(record: schemas.RecordCreate, db: Session = Depends(get_db)):
"""
Not for public usage
"""
return controller.create_record(db, record) return controller.create_record(db, record)

View File

@ -37,3 +37,6 @@ class RecordCreate(BaseRecord):
class CheckResponse(BaseModel): class CheckResponse(BaseModel):
is_outage: bool is_outage: bool
when_finish: Optional[datetime.datetime] = None when_finish: Optional[datetime.datetime] = None
class Healthcheck(BaseModel):
up_since: datetime.datetime

View File

@ -29,6 +29,10 @@ class RossetiParser:
```python ```python
def split_addresses(df: pd.DataFrame) -> pd.DataFrame def split_addresses(df: pd.DataFrame) -> pd.DataFrame
``` ```
- `get_building_id`:
```python
def get_building_id(street: str) -> Tuple[Optional[int], Optional[float], Optional[float]]
```
- `fetch_builing_ids`: - `fetch_builing_ids`:
```python ```python
def fetch_builing_ids(df: pd.DataFrame) -> pd.DataFrame def fetch_builing_ids(df: pd.DataFrame) -> pd.DataFrame

View File

@ -1,5 +1,5 @@
from .rosseti import RossetiParser from .rosseti import RossetiParser
from .address import split_addresses from .address import split_addresses
from .building_id import fetch_builing_ids, async_fetch_building_ids, concurrent_fetch_builing_ids from .building_id import get_building_id, fetch_builing_ids, async_fetch_building_ids, concurrent_fetch_builing_ids
from .preprocess import preprocess_df, COL_NS, ICOL_NS, preprocess_read_df, group_by_index from .preprocess import preprocess_df, COL_NS, ICOL_NS, preprocess_read_df, group_by_index
from .util import pipeline from .util import pipeline