def retrial_request_bcall_get_vehicledata(self, msisdn, programcode: ProgramCode, payload, action): validjsonresponse = None dataresponse = None response = None for i in range(self._config.max_retries): self._logger.info( "GetVehicleData: Requesting BCALL Data for msisdn {}. Retry attempt :: {}" .format(msisdn, i), extra={ "msisdn": msisdn, "programcode": programcode, "cts-version": CtsVersion.ONE_DOT_ZERO, "action": action, }, ) # Requesting FCA External telematics BCALL to push data to us for the requested msisdn response = request_bcall_data(self, msisdn, programcode, payload, action) validjsonresponse = (response.headers.get("content-type") is not None and "json" in response.headers.get("content-type").lower()) if (response.status_code == HTTP_200_OK or response.status_code == HTTP_202_ACCEPTED) and validjsonresponse: responsejson = response.json() # After successful request for FCA External telematics BCALL to push data to us and # Data push call from FCA calls Save Vehicle data endpoint # to save data in database so we search here again in database to look for data. db_response = get_vehicledata_response(self, msisdn, programcode) if db_response is not None: responsemessage = (responsejson["message"] if checkjsonnode( "message", responsejson) else "Successfully retrieved") dataresponse = create_vehicledata_response( db_response, msisdn, programcode, InternalStatusType.SUCCESS, responsemessage, ) self._logger.info( "GetVehicleData: Received BCALL Data from FCA from msisdn {} in Retry attempt :: {}" .format(msisdn, i), extra={ "msisdn": msisdn, "programcode": programcode, "cts-version": CtsVersion.ONE_DOT_ZERO, "action": action, }, ) break sleep(self._config.delay_for_each_retry) return response, validjsonresponse, dataresponse
def get_vehicledata(self, msisdn: str, programcode: ProgramCode): try: self._logger.info( "GetVehicleData: Payload received for msisdn: {} programcode: {}" .format(msisdn, programcode), extra={ "programcode": programcode, "msisdn": msisdn, "action": "GetVehicleData", "cts-version": CtsVersion.TWO_DOT_ZERO, }, ) if not self._config.base_url.endswith("/"): self._config.base_url = "{url}{suffix}".format( url=self._config.base_url, suffix="/") dataresponse = None # check and get data from database based of db check flag if self._config.dynamodb_check_enable: dataresponse = get_data_from_database(self, msisdn, programcode, CtsVersion.TWO_DOT_ZERO) if dataresponse is not None: return dataresponse else: response = requests.get( "{serviceurl}{msisdn}".format( serviceurl=self._config.base_url, msisdn=msisdn), verify=self._config.root_cert, ) self._logger.info( "GetVehicleData: Response from vordel for msisdn: {} is: " "status_code: {}, response_text: {}, response_reason: {}". format(msisdn, response.status_code, response.text, response.reason), extra={ "programcode": programcode, "msisdn": msisdn, "response": str(response), "action": "GetVehicleData", "cts-version": CtsVersion.TWO_DOT_ZERO, }, ) validjsonresponse = ( response.headers.get("content-type") is not None and "json" in response.headers.get("content-type").lower()) if (response.status_code == HTTP_200_OK and validjsonresponse and checkjsonnode("data", response.json())): responsejson = response.json()["data"] self._logger.info( "GetVehicleData: Successfully received response for msisdn:{} status:{} programcode:{} response_payload:{}" .format(msisdn, Status.SUCCESS, programcode, responsejson), extra={ "programcode": programcode, "msisdn": msisdn, "action": "GetVehicleData", "cts-version": CtsVersion.TWO_DOT_ZERO, }, ) vehicledata = VehicleData( status=InternalStatusType.SUCCESS, responsemessage="Successfully retrieved", msisdn=msisdn, programcode=programcode, event_datetime=get_utc_epoch(), calldate=responsejson["callDate"], calltime=responsejson["callTime"], timestamp=datetime.strptime( "{} {}".format(responsejson["callDate"], responsejson["callTime"]), "%Y-%m-%d %H:%M", ), odometer=responsejson["odometer"], odometerscale=OdometerScale( responsejson["odometerScale"]), activationtype=responsejson["activationType"], latitude=responsejson["location"]["latitude"], longitude=responsejson["location"]["longitude"], headingdirection=responsejson["location"] ["headingDirection"], vin=responsejson["vehicle"]["vin"], brand=responsejson["vehicle"]["brand"], modelname=responsejson["vehicle"]["modelName"], modelyear=responsejson["vehicle"]["modelYear"], modelcode=responsejson["vehicle"]["modelCode"], modeldesc=responsejson["vehicle"]["modelDesc"], market=responsejson["vehicle"]["ocuSim"]["market"], ) # Save the data in dynamodb for audit and return the model on success self.save_vehicledata(msisdn, programcode, vehicledata) return vehicledata errorjson = (response.json()["error"] if validjsonresponse and checkjsonnode("error", response.json()) else seterrorjson(response.reason, response.text)) errorstatus = internalstatustype_conversion( errorjson["status"]) self._logger.error( "GetVehicleData: Error occurred for msisdn:{} status:{} programcode:{} error_response_payload:{}" .format( msisdn, errorstatus, programcode, errorjson if validjsonresponse else "ErrorResponse {}".format(response), ), exc_info=True, stack_info=True, extra={ "programcode": programcode, "msisdn": msisdn, "action": "GetVehicleData", "cts-version": CtsVersion.TWO_DOT_ZERO, }, ) return VehicleData( status=errorstatus, responsemessage="{code}{description}".format( code=errorjson["errorCode"] if checkjsonnode( "errorCode", errorjson) else "", description=", {}".format( errorjson["errorDescription"]) if checkjsonnode( "errorDescription", errorjson) else "", ), ) except Exception as e: self._logger.error( "GetVehicleData: Gateway error: Aeris: Error Occured: {} for msisdn: {}" .format(e, msisdn), exc_info=True, stack_info=True, extra={ "programcode": programcode, "msisdn": msisdn, "action": "GetVehicleData", "cts-version": CtsVersion.TWO_DOT_ZERO, }, ) return VehicleData( status=InternalStatusType.INTERNALSERVERERROR, responsemessage=e.args[0] if e.args.__len__() > 0 else None, )
def save_vehicledata(self, msisdn, programcode, savevehicledata): if (savevehicledata is None or checkjsonnode("gpsData", savevehicledata) == False or checkjsonnode("userData", savevehicledata) == False or checkjsonnode("vehicleData", savevehicledata) == False): self._logger.error( "SaveVehicleData: Json payload: {} is invalid for msisdn: {}". format(savevehicledata, msisdn), exc_info=True, stack_info=True, extra={ "programcode": programcode, "cts-version": CtsVersion.ONE_DOT_ZERO, "action": "SaveVehicleData", }, ) return VehicleData( msisdn=msisdn, status=InternalStatusType.BADREQUEST, responsemessage= "SaveVehicleData: Json payload is invalid for msisdn: {}". format(msisdn), ) try: self._logger.info( "SaveVehicleData: Vehicle data for msisdn: {} data: {}".format( msisdn, savevehicledata), extra={ "programcode": programcode, "cts-version": CtsVersion.ONE_DOT_ZERO, "action": "SaveVehicleData", }, ) vehicledata = self.populate_vehicledata(msisdn, programcode, savevehicledata) vehicle_table = map_primarytable(msisdn, programcode, vehicledata, self._Table, savevehicledata) vehicle_table.save() self._logger.info( "SaveVehicleData: Successfully saved Vehicle data onto main table {} for msisdn: {}" .format(vehicledata, msisdn), extra={ "programcode": programcode, "cts-version": CtsVersion.ONE_DOT_ZERO, "action": "SaveVehicleData", }, ) save_supplementdata(self, msisdn, programcode, vehicledata) return VehicleData( msisdn=msisdn, status=InternalStatusType.SUCCESS, responsemessage= "Successfully saved the vehicledata for msisdn: {}".format( msisdn), ) except Exception as e: self._logger.error( "SaveVehicleData: Error occured while saving vehicledata onto primary table: {} for msisdn: {}" .format(e, msisdn), exc_info=True, stack_info=True, extra={ "programcode": programcode, "cts-version": CtsVersion.ONE_DOT_ZERO, "payload": savevehicledata, "action": "SaveVehicleData", }, ) return VehicleData( msisdn=msisdn, status=InternalStatusType.INTERNALSERVERERROR, responsemessage="Unable to save the vehicledata for msisdn: {}" .format(msisdn), )
def get_vehicledata(self, msisdn: str, programcode: ProgramCode): try: msisdn = reformat_msisdn(msisdn, self._config.max_ani_length) self._logger.info( "GetVehicleData: Vehicle data for msisdn: {} programcode: {}". format(msisdn, programcode), extra={ "msisdn": msisdn, "programcode": programcode, "cts-version": CtsVersion.ONE_DOT_ZERO, "action": "GetVehicleData", }, ) dataresponse = None # get data from database db_response = get_vehicledata_response(self, msisdn, programcode) if db_response is not None: dataresponse = create_vehicledata_response( db_response, msisdn, programcode, InternalStatusType.SUCCESS, "Successfully retrieved", ) self._logger.info( "GetVehicleData: Successfully retrieved response from database for msisdn:{} status:{} programcode:{}" .format(msisdn, Status.SUCCESS, programcode), extra={ "msisdn": msisdn, "programcode": programcode, "cts-version": CtsVersion.ONE_DOT_ZERO, "action": "GetVehicleData", }, ) return dataresponse else: payload = {"msisdn": msisdn} response = None validjsonresponse = None ( response, validjsonresponse, dataresponse, ) = retrial_request_bcall_get_vehicledata( self, msisdn, programcode, payload, "GetVehicleData") if dataresponse is not None: return dataresponse if (response.status_code == HTTP_200_OK or response.status_code == HTTP_202_ACCEPTED) and validjsonresponse: self._logger.error( "GetVehicleData: Request BCall Data Successful, but no record found from database for msisdn:{} status:{} programcode:{}" .format(msisdn, Status.NOT_FOUND, programcode), extra={ "msisdn": msisdn, "programcode": programcode, "cts-version": CtsVersion.ONE_DOT_ZERO, "action": "GetVehicleData", }, ) return VehicleData( msisdn=msisdn, status=InternalStatusType.NOTFOUND, responsemessage="No data is available for msisdn: {}". format(msisdn), ) elif validjsonresponse: responsejson = response.json()[0] errorjson = seterrorjson( responsejson["detailedErrorCode"] if checkjsonnode( "detailedErrorCode", responsejson) else (responsejson["error"] if checkjsonnode( "error", responsejson) else "NA"), responsejson["message"] if checkjsonnode( "message", responsejson) else "NA", ) else: errorjson = seterrorjson(response.reason, response.text) errorstatus = internalstatus_conversion(errorjson["status"]) self._logger.info( "GetVehicleData: Error occurred in FCA BData call for msisdn:{} status:{} error_response_payload:{}" .format( msisdn, errorstatus, errorjson if validjsonresponse else "{}, missing json response from external fca service". format(response), ), extra={ "msisdn": msisdn, "programcode": programcode, "cts-version": CtsVersion.ONE_DOT_ZERO, "action": "GetVehicleData", }, ) return VehicleData( msisdn=msisdn, status=errorstatus, responsemessage="{code}{description}".format( code=errorjson["errorCode"] if checkjsonnode( "errorCode", errorjson) else "", description=", {}".format( errorjson["errorDescription"]) if checkjsonnode( "errorDescription", errorjson) else "", ), ) except Exception as e: self._logger.error( "GetVehicleData: Gateway error: FCA: Error Occured: {} for msisdn {}" .format(e, msisdn), exc_info=True, stack_info=True, extra={ "msisdn": msisdn, "programcode": programcode, "cts-version": CtsVersion.ONE_DOT_ZERO, "action": "GetVehicleData", }, ) return VehicleData( status=InternalStatusType.INTERNALSERVERERROR, responsemessage=e.args[0] if e.args.__len__() > 0 else None, )
def terminate(self, msisdn: str, programcode: ProgramCode, payload): if (payload is None or checkjsonnode("callstatus", payload) == False or isnull_whitespaceorempty(payload["callstatus"]) or payload["callstatus"] != CallStatus.TERMINATED): self._logger.error( "Terminate: Missing callstatus in payload: {} for msisdn {}". format(payload, msisdn), exc_info=True, stack_info=True, extra={ "programcode": programcode, "cts-version": CtsVersion.ONE_DOT_ZERO, "payload": payload, "action": "Terminate", }, ) return Terminate( msisdn=msisdn, status=InternalStatusType.BADREQUEST, responsemessage="callstatus in payload is missing or invalid", ) callstatus = payload["callstatus"] try: self._logger.info( "Terminate: Request for msisdn: {}".format(msisdn), extra={ "programcode": programcode, "cts-version": CtsVersion.ONE_DOT_ZERO, "action": "Terminate", "callstatus": callstatus, }, ) msisdn = reformat_msisdn(msisdn, self._config.max_ani_length) requestbody = {"msisdn": msisdn, "callStatus": callstatus} serviceurl = "{}{}".format(self._config.base_url, self._config.terminate_bcall_url) headers = { "content-type": "application/json", "APIKey": self._config.raw_api_key, } response = requests.post( serviceurl, headers=headers, json=requestbody, verify=self._config.root_cert, ) validjsonresponse = ( response.headers.get("content-type") is not None and "json" in response.headers.get("content-type").lower()) if (response.status_code == HTTP_200_OK or response.status_code == HTTP_202_ACCEPTED) and validjsonresponse: responsejson = response.json() self._logger.info( "Terminate: FCA response for msisdn:{} status:{} success_response_payload:{}" .format(msisdn, Status.CREATED, responsejson), extra={ "programcode": programcode, "cts-version": CtsVersion.ONE_DOT_ZERO, "action": "Terminate", "callstatus": callstatus, }, ) return Terminate( msisdn=msisdn, status=InternalStatusType.SUCCESS, responsemessage=responsejson["message"] if checkjsonnode( "message", responsejson) else "Successfully terminated the call", callstatus=callstatus, ) if validjsonresponse: responsejson = response.json()[0] errorjson = seterrorjson( responsejson["detailedErrorCode"] if checkjsonnode( "detailedErrorCode", responsejson) else (responsejson["error"] if checkjsonnode( "error", responsejson) else "NA"), responsejson["message"] if checkjsonnode( "message", responsejson) else "NA", ) else: errorjson = seterrorjson(response.reason, response.text) errorstatus = internalstatus_conversion(errorjson["status"]) self._logger.error( "Terminate: Error occurred in FCA Terminate call for msisdn:{} status:{} error_response_payload:{}" .format( msisdn, errorstatus, errorjson if validjsonresponse else "{}, missing json response from external fca service". format(response), ), extra={ "programcode": programcode, "cts-version": CtsVersion.ONE_DOT_ZERO, "action": "Terminate", "callstatus": callstatus, }, ) return Terminate( msisdn=msisdn, status=errorstatus, responsemessage="{code}{description}".format( code=errorjson["errorCode"] if checkjsonnode( "errorCode", errorjson) else "", description=", {}".format(errorjson["errorDescription"]) if checkjsonnode("errorDescription", errorjson) else "", callstatus=callstatus, ), ) except Exception as e: self._logger.error( "Terminate: Gateway error: External FCA: Error Occured: {} for msisdn {}" .format(e, msisdn), exc_info=True, stack_info=True, extra={ "programcode": programcode, "cts-version": CtsVersion.ONE_DOT_ZERO, "action": "Terminate", "callstatus": callstatus, }, ) return Terminate( msisdn=msisdn, status=InternalStatusType.INTERNALSERVERERROR, responsemessage=e.args[0] if e.args.__len__() > 0 else None, callstatus=callstatus, )
def test_checkjsonnode_returns_as_expected(jsonnode, expected): jsonstr = {"nodea": "value", "nodec": "value"} returnvalue = checkjsonnode(jsonnode, jsonstr) assert returnvalue == expected
def terminate(self, eventid: str, programcode: ProgramCode, payload): if (payload is None or checkjsonnode("eventId", payload) == False or isnull_whitespaceorempty(payload["eventId"]) or checkjsonnode("callEndIntentional", payload) == False or checkjsonnode("dispositionType", payload) == False): self._logger.error( "Terminate: Payload is missing or invalid: {} for eventid {}". format(payload, eventid), exc_info=True, stack_info=True, extra={ "programcode": programcode, "cts-version": CtsVersion.ONE_DOT_ZERO, "payload": payload, "action": "Terminate", }, ) return Terminate( eventid=eventid, status=InternalStatusType.BADREQUEST, responsemessage="Payload is missing or invalid", ) try: self._logger.info( "Terminate: Request for eventid: {}".format(eventid), extra={ "programcode": programcode, "cts-version": CtsVersion.ONE_DOT_ZERO, "payload": payload, "action": "Terminate", }, ) requestbody = payload serviceurl = "{}{}".format(self._config.base_url, self._config.terminate_url) headers = { "content-type": "application/json", } response = requests.post( serviceurl, headers=headers, json=requestbody, verify=self._config.root_cert, ) validjsonresponse = ( response.headers.get("content-type") is not None and "json" in response.headers.get("content-type").lower()) if (response.status_code == HTTP_200_OK or response.status_code == HTTP_202_ACCEPTED) and validjsonresponse: responsejson = response.json() self._logger.info( "Terminate: TMNA response for eventid:{} status:{} success_response_payload:{}" .format(eventid, InternalStatusType.SUCCESS, responsejson), extra={ "programcode": programcode, "cts-version": CtsVersion.ONE_DOT_ZERO, "payload": payload, "action": "Terminate", }, ) return Terminate( eventid=eventid, status=InternalStatusType.SUCCESS, responsemessage=responsejson["resultMessage"] if checkjsonnode("resultMessage", responsejson) else "Successfully terminated the call", ) if validjsonresponse: responsejson = response.json()[0] errorjson = seterrorjson( responsejson["resultCode"] if checkjsonnode( "resultCode", responsejson) else (responsejson["error"] if checkjsonnode( "error", responsejson) else "NA"), responsejson["resultMessage"] if checkjsonnode( "resultMessage", responsejson) else (responsejson["message"] if checkjsonnode( "message", responsejson) else "NA"), ) else: errorjson = seterrorjson(response.reason, response.text) errorstatus = internalstatus_conversion(errorjson["status"]) self._logger.error( "Terminate: Error occurred in TMNA Terminate call for eventid:{} status:{} error_response_payload:{}" .format( eventid, errorstatus, errorjson if validjsonresponse else "{}, missing json response from external TMNA service". format(response), ), extra={ "programcode": programcode, "cts-version": CtsVersion.ONE_DOT_ZERO, "payload": payload, "action": "Terminate", }, ) return Terminate( eventid=eventid, status=errorstatus, responsemessage="{code}{description}".format( code=errorjson["errorCode"] if checkjsonnode( "errorCode", errorjson) else "", description=", {}".format(errorjson["errorDescription"]) if checkjsonnode("errorDescription", errorjson) else "", ), ) except Exception as e: self._logger.error( "Terminate: Gateway error: External TMNA: Error Occured: {} for eventid {}" .format(e, eventid), exc_info=True, stack_info=True, extra={ "programcode": programcode, "cts-version": CtsVersion.ONE_DOT_ZERO, "payload": payload, "action": "Terminate", }, ) return Terminate( eventid=eventid, status=InternalStatusType.INTERNALSERVERERROR, responsemessage=e.args[0] if e.args.__len__() > 0 else None, )