99from typing import Any , List
1010
1111from asgiref .sync import async_to_sync
12- from django . conf import settings
13- from gpp_client import GPPClient , GPPDirector
14- from gpp_client .api . enums import AttachmentType
15- from gpp_client . api . input_types import (
12+ from gpp_client import GPPClient
13+ from gpp_client . generated . enums import AttachmentType
14+ from gpp_client .generated . input_types import (
15+ CloneObservationInput ,
1616 TargetEnvironmentInput ,
1717)
1818from rest_framework import permissions , status
@@ -74,6 +74,12 @@ class StageMessage:
7474 message : str
7575
7676
77+ def _format_workflow_state (workflow_state ) -> str :
78+ state = getattr (workflow_state , "state" , None )
79+ value = getattr (state , "value" , None )
80+ return value or "unknown"
81+
82+
7783def build_failure_response (
7884 stage : Stage ,
7985 error : Exception | str ,
@@ -187,9 +193,11 @@ def _process_finder_charts(
187193 f"Failed to delete finder chart '{ attachment_id } ': { e } "
188194 ) from e
189195 try :
190- attachment_data = async_to_sync (client .attachment .get_all_by_observation )(
191- observation_id = observation_id ,
192- observation_reference = None ,
196+ attachment_result = async_to_sync (
197+ client .attachment .get_all_by_observation_id
198+ )(observation_id = observation_id )
199+ attachment_data = (
200+ attachment_result .model_dump (by_alias = True ).get ("observation" ) or {}
193201 )
194202 except Exception as e :
195203 raise ValueError (
@@ -293,36 +301,36 @@ def list(self, request: Request, *args, **kwargs) -> Response:
293301
294302 try :
295303 # Setup client to communicate with GPP.
296- client = GPPClient (env = settings .GPP_ENV , token = credentials .token )
297- director = GPPDirector (client )
304+ client = GPPClient (token = credentials .token )
298305 if program_id is not None :
299306 logger .debug (
300307 "Retrieving GPP observations for program ID: %s" , program_id
301308 )
302- payload = async_to_sync (director .goats .observation . get_all )(
309+ payload = async_to_sync (client .goats .get_observations_by_program_id )(
303310 program_id = program_id
304311 )
312+ data = payload .model_dump (by_alias = True )["observations" ]
305313 # Filter the observations into too and normal categories.
306- matches = payload .get ("matches" , [])
314+ matches = data .get ("matches" , [])
307315 too_obs = [o for o in matches if self .is_too (o )]
308316 normal_obs = [o for o in matches if not self .is_too (o )]
309317
310- # Build the custom payload response.
318+ # Build the custom data response.
311319 return Response (
312320 {
313321 "matches" : {
314322 "too" : {"count" : len (too_obs ), "results" : too_obs },
315323 "normal" : {"count" : len (normal_obs ), "results" : normal_obs },
316324 },
317- "hasMore" : payload .get ("hasMore" , False ),
325+ "hasMore" : data .get ("hasMore" , False ),
318326 }
319327 )
320328 else :
321329 logger .debug (
322330 "Retrieving all GPP observations for user: %s" , request .user
323331 )
324332 payload = async_to_sync (client .observation .get_all )()
325- return Response (payload )
333+ return Response (payload . model_dump ( by_alias = True ) )
326334 except Exception as e :
327335 logger .exception ("Error retrieving GPP observations" )
328336 return Response ({"detail" : str (e )}, status = status .HTTP_400_BAD_REQUEST )
@@ -388,11 +396,11 @@ def retrieve(self, request: Request, *args, **kwargs) -> Response:
388396
389397 # Setup client to communicate with GPP.
390398 try :
391- client = GPPClient (env = settings . GPP_ENV , token = credentials .token )
392- observation = async_to_sync (client .observation .get_by_id )(
399+ client = GPPClient (token = credentials .token )
400+ data = async_to_sync (client .observation .get_by_id )(
393401 observation_id = observation_id
394402 )
395- return Response (observation )
403+ return Response (data . model_dump ( by_alias = True )[ " observation" ] )
396404 except Exception as e :
397405 logger .exception ("Error retrieving GPP observation" )
398406 return Response ({"detail" : str (e )}, status = status .HTTP_400_BAD_REQUEST )
@@ -508,7 +516,8 @@ def update_only(self, request: Request, *args, **kwargs) -> Response:
508516 A DRF Response object containing the details of the updated observation.
509517 """
510518 messages : list [StageMessage ] = []
511- data : dict [str , Any ] = {}
519+ updated_target_id : str | None = None
520+ updated_observation_id : str | None = None
512521
513522 logger .info ("Updating observation on GPP" )
514523
@@ -549,7 +558,7 @@ def update_only(self, request: Request, *args, **kwargs) -> Response:
549558 client = None
550559 try :
551560 # Setup client to communicate with GPP.
552- client = GPPClient (env = settings . GPP_ENV , token = credentials .token )
561+ client = GPPClient (token = credentials .token )
553562
554563 # Validate and extract required IDs for observation update.
555564 context_serializer = ContextSerializer (data = normalized_data )
@@ -598,16 +607,17 @@ def update_only(self, request: Request, *args, **kwargs) -> Response:
598607 logger .debug ("Updating sidereal target in GPP" )
599608 try :
600609 update_target_result = async_to_sync (client .target .update_by_id )(
601- target_id = gpp_target_id , properties = target_properties
610+ gpp_target_id , properties = target_properties
602611 )
603- updated_target_id = update_target_result .get ("id" )
612+ update_target_dump = update_target_result .model_dump (by_alias = True )
613+ targets = update_target_dump .get ("updateTargets" , {}).get ("targets" , [])
614+ updated_target_id = targets [0 ].get ("id" ) if targets else None
604615
605616 if updated_target_id is None :
606617 raise ValueError (
607618 "Failed to retrieve updated target ID from update result."
608619 )
609620
610- data ["updatedTargetId" ] = updated_target_id
611621 messages .append (
612622 StageMessage (
613623 stage = Stage .UPDATE_TARGET ,
@@ -629,9 +639,9 @@ def update_only(self, request: Request, *args, **kwargs) -> Response:
629639 # Update observation.
630640 logger .debug ("Updating observation in GPP" )
631641 try :
632- finder_charts = normalized_data .get ("finderCharts" , None )
642+ finder_charts = normalized_data .get ("finderCharts" ) or {}
633643
634- if finder_charts :
644+ if finder_charts . get ( "toAdd" ) or finder_charts . get ( "toDelete" ) :
635645 finder_chart_ids = self ._process_finder_charts (
636646 client = client ,
637647 observation_id = gpp_observation_id ,
@@ -645,14 +655,21 @@ def update_only(self, request: Request, *args, **kwargs) -> Response:
645655 update_observation_result = async_to_sync (client .observation .update_by_id )(
646656 observation_id = gpp_observation_id , properties = observation_properties
647657 )
648- updated_observation_id = update_observation_result .get ("id" )
658+ update_observation_dump = update_observation_result .model_dump (
659+ by_alias = True
660+ )
661+ observations_list = update_observation_dump .get (
662+ "updateObservations" , {}
663+ ).get ("observations" , [])
664+ updated_observation_id = (
665+ observations_list [0 ].get ("id" ) if observations_list else None
666+ )
649667
650668 if updated_observation_id is None :
651669 raise ValueError (
652670 "Failed to retrieve updated observation ID from update result."
653671 )
654672
655- data ["updatedObservationId" ] = updated_observation_id
656673 messages .append (
657674 StageMessage (
658675 stage = Stage .UPDATE_OBSERVATION ,
@@ -689,7 +706,8 @@ def update_only(self, request: Request, *args, **kwargs) -> Response:
689706 StageMessage (
690707 stage = Stage .UPDATE_WORKFLOW_STATE ,
691708 status = MessageStatus .SUCCESS ,
692- message = f"Workflow state set to { new_workflow_state ['state' ]} ." ,
709+ message = "Workflow state set to "
710+ f"{ _format_workflow_state (new_workflow_state )} ." ,
693711 )
694712 )
695713
@@ -702,13 +720,19 @@ def update_only(self, request: Request, *args, **kwargs) -> Response:
702720 message = str (e ),
703721 )
704722 )
705-
706723 if client is not None :
707724 try :
708725 async_to_sync (client .close )()
709726 except Exception :
710727 logger .debug ("Failed to close GPP client." , exc_info = True )
711- return self ._build_structured_response (messages = messages , data = data )
728+
729+ return self ._build_structured_response (
730+ messages = messages ,
731+ data = {
732+ "updatedTargetId" : updated_target_id ,
733+ "updatedObservationId" : updated_observation_id ,
734+ },
735+ )
712736
713737 @action (detail = False , methods = ["post" ], url_path = "create-and-save" )
714738 def create_and_save_observation (
@@ -732,7 +756,9 @@ def create_and_save_observation(
732756 A DRF Response object containing the details of the created observation.
733757 """
734758 messages : list [StageMessage ] = []
735- data : dict [str , Any ] = {}
759+ new_target_id : str | None = None
760+ new_observation_id : str | None = None
761+ goats_observation : dict [str , Any ] | None = None
736762
737763 logger .info (
738764 "Creating observation on GPP and saving observation to GOATS database"
@@ -775,7 +801,7 @@ def create_and_save_observation(
775801 client = None
776802 try :
777803 # Setup client to communicate with GPP.
778- client = GPPClient (env = settings . GPP_ENV , token = credentials .token )
804+ client = GPPClient (token = credentials .token )
779805
780806 # Validate and extract required IDs for observation creation.
781807 context_serializer = ContextSerializer (data = normalized_data )
@@ -823,14 +849,16 @@ def create_and_save_observation(
823849 logger .debug ("Creating sidereal target in GPP" )
824850 try :
825851 clone_target_result = async_to_sync (client .target .clone )(
826- target_id = gpp_target_id , properties = target_properties
852+ gpp_target_id , properties = target_properties
853+ )
854+ clone_target_dump = clone_target_result .model_dump (by_alias = True )
855+ new_target_id = (
856+ clone_target_dump .get ("cloneTarget" , {}).get ("newTarget" , {}).get ("id" )
827857 )
828- new_target_id = clone_target_result .get ("newTarget" , {}).get ("id" )
829858
830859 if new_target_id is None :
831860 raise ValueError ("Failed to retrieve new target ID from clone result." )
832861
833- data ["newTargetId" ] = new_target_id
834862 messages .append (
835863 StageMessage (
836864 stage = Stage .CREATE_TARGET ,
@@ -849,8 +877,8 @@ def create_and_save_observation(
849877 asterism = [new_target_id ]
850878 )
851879
852- finder_charts = normalized_data .get ("finderCharts" , None )
853- if finder_charts :
880+ finder_charts = normalized_data .get ("finderCharts" ) or {}
881+ if finder_charts . get ( "toAdd" ) or finder_charts . get ( "toDelete" ) :
854882 finder_chart_ids = self ._process_finder_charts (
855883 client = client ,
856884 observation_id = gpp_observation_id ,
@@ -859,18 +887,24 @@ def create_and_save_observation(
859887 )
860888 observation_properties .attachments = finder_chart_ids
861889
890+ clone_input = CloneObservationInput (
891+ observation_id = gpp_observation_id ,
892+ set_ = observation_properties ,
893+ )
862894 clone_observation_result = async_to_sync (client .observation .clone )(
863- observation_id = gpp_observation_id , properties = observation_properties
895+ input = clone_input ,
896+ )
897+ clone_observation_dump = clone_observation_result .model_dump (by_alias = True )
898+ new_observation = clone_observation_dump .get ("cloneObservation" , {}).get (
899+ "newObservation" , {}
864900 )
865- new_observation = clone_observation_result .get ("newObservation" , {})
866901 new_observation_id = new_observation .get ("id" )
867902
868903 if new_observation_id is None :
869904 raise ValueError (
870905 "Failed to retrieve new observation ID from clone result."
871906 )
872907
873- data ["newObservationId" ] = new_observation_id
874908 messages .append (
875909 StageMessage (
876910 stage = Stage .CREATE_OBSERVATION ,
@@ -905,7 +939,8 @@ def create_and_save_observation(
905939 StageMessage (
906940 stage = Stage .UPDATE_WORKFLOW_STATE ,
907941 status = MessageStatus .SUCCESS ,
908- message = f"Workflow state set to { new_workflow_state ['state' ]} ." ,
942+ message = f"Workflow state set to "
943+ f"{ _format_workflow_state (new_workflow_state )} ." ,
909944 )
910945 )
911946
@@ -940,7 +975,7 @@ def create_and_save_observation(
940975 raise ValueError (tom_response .data )
941976
942977 else :
943- data [ "goatsObservation" ] = tom_response .data
978+ goats_observation = tom_response .data
944979 messages .append (
945980 StageMessage (
946981 stage = Stage .GOATS_OBSERVATION_SAVE ,
@@ -958,12 +993,20 @@ def create_and_save_observation(
958993 )
959994 )
960995
996+ response_data : dict [str , Any ] = {
997+ "newTargetId" : new_target_id ,
998+ "newObservationId" : new_observation_id ,
999+ }
1000+ if goats_observation is not None :
1001+ response_data ["goatsObservation" ] = goats_observation
1002+
9611003 if client is not None :
9621004 try :
9631005 async_to_sync (client .close )()
9641006 except Exception :
9651007 logger .debug ("Failed to close GPP client." , exc_info = True )
966- return self ._build_structured_response (messages = messages , data = data )
1008+
1009+ return self ._build_structured_response (messages = messages , data = response_data )
9671010
9681011 def _create_goats_observation (
9691012 self ,
0 commit comments