88import datetime
99
1010from database .session import get_db
11- from models .db_models import Satellite , Debris
11+ from models .db_models import Satellite , Debris , SpaceObject
1212from app .core .exceptions import (
1313 ExternalServiceError ,
1414 NotFoundError ,
@@ -114,6 +114,30 @@ def _serialize_debris(deb: Debris) -> Dict[str, Any]:
114114 }
115115
116116
117+ @router .get ("/objects" , response_model = APIResponse [List [Dict [str , Any ]]])
118+ def _serialize_space_object (obj : SpaceObject ) -> Dict [str , Any ]:
119+ epoch = obj .epoch
120+ raan , arg_of_perigee , mean_anomaly = _orbital_angles (obj .tle_line2 , obj )
121+ return {
122+ "id" : str (obj .id ),
123+ "name" : obj .objectName or "" ,
124+ "catalog_number" : obj .noradId or "" ,
125+ "cospar_id" : obj .cospar_id ,
126+ "classification" : obj .objectType or "UNKNOWN" ,
127+ "epoch" : epoch if isinstance (epoch , str ) else (epoch .isoformat () if epoch else None ),
128+ "inclination" : obj .inclination ,
129+ "eccentricity" : obj .eccentricity ,
130+ "semimajor_axis" : obj .semimajor_axis ,
131+ "raan" : raan ,
132+ "arg_of_perigee" : arg_of_perigee ,
133+ "mean_anomaly" : mean_anomaly ,
134+ "mean_motion" : obj .mean_motion ,
135+ "period" : obj .period ,
136+ "has_tle" : bool (obj .tle_line1 and obj .tle_line2 ),
137+ "updated_at" : obj .updated_at .isoformat () if obj .updated_at else None ,
138+ }
139+
140+
117141@router .get ("/objects" , response_model = APIResponse [List [Dict [str , Any ]]])
118142def list_space_objects (
119143 page : int = Query (1 , ge = 1 ),
@@ -123,43 +147,36 @@ def list_space_objects(
123147 db : Session = Depends (get_db ),
124148):
125149 if classification and classification .upper () not in VALID_CLASSIFICATIONS :
126- raise ValidationError (
127- f"'{ classification } ' is not a valid object classification." ,
150+ raise ValidationError (f"'{ classification } ' is not a valid object classification." ,
128151 details = {"field" : "classification" , "value" : classification , "allowed" : list (VALID_CLASSIFICATIONS )},
129152 )
130153
131154 cls = classification .upper () if classification else None
132155 pattern = f"%{ search } %" if search else None
133156
134- all_docs : List [Dict [str , Any ]] = []
135-
136- if cls != "DEBRIS" :
137- q = db .query (Satellite )
138- if cls :
139- q = q .filter (Satellite .objectType == cls )
140- if pattern :
141- q = q .filter (Satellite .objectName .ilike (pattern ) | Satellite .noradId .ilike (pattern ))
142- all_docs .extend (_serialize_sat (s ) for s in q .all ())
143-
144- if cls in (None , "DEBRIS" ):
145- q = db .query (Debris )
146- if pattern :
147- q = q .filter (Debris .objectName .ilike (pattern ) | Debris .noradId .ilike (pattern ))
148- all_docs .extend (_serialize_debris (d ) for d in q .all ())
157+ # FIX: Query the unified SpaceObject schema to enable DB-level pagination
158+ query = db .query (SpaceObject )
159+
160+ if cls :
161+ query = query .filter (SpaceObject .objectType == cls )
162+ if pattern :
163+ query = query .filter (SpaceObject .objectName .ilike (pattern ) | SpaceObject .noradId .ilike (pattern ))
149164
150- total = len ( all_docs )
165+ total = query . count ( )
151166 offset = (page - 1 ) * size
152- pages = (total + size - 1 ) // size if total else 1
167+
168+ # FIX: Apply offset and limit directly to the SQL query
169+ records = query .offset (offset ).limit (size ).all ()
170+
171+ # FIX: Correct the pagination math
172+ pages = (total + size - 1 ) // size
153173
154174 return APIResponse (
155175 success = True ,
156176 message = f"Orbital catalog — { total } objects tracked" ,
157- data = all_docs [ offset : offset + size ],
177+ data = [ _serialize_space_object ( r ) for r in records ],
158178 pagination = PaginationSchema (page = page , size = size , total = total , pages = pages ),
159179 )
160-
161-
162- @router .get ("/objects/{catalog_number}" , response_model = APIResponse [Dict [str , Any ]])
163180def get_space_object (catalog_number : str , db : Session = Depends (get_db )):
164181 if catalog_number .isdecimal ():
165182 catalog_number = str (int (catalog_number ))
0 commit comments