def test_nr_state_actions(): nr_model = Request() nr_model.expirationDate = datetime.utcnow() + timedelta(days=3) nr_model.priorityCd = None nr_model.priorityDate = None print('\n Draft state actions \n') print(repr(NameRequestDraftActions.list())) actions = get_nr_state_actions(State.DRAFT, nr_model) print(repr(actions)) print('\n Reserved state actions \n') print(repr(NameRequestReservedActions.list())) actions = get_nr_state_actions(State.RESERVED, nr_model) print(repr(actions)) print('\n Conditionally reserved state actions \n') print(repr(NameRequestReservedActions.list())) actions = get_nr_state_actions(State.COND_RESERVE, nr_model) print(repr(actions)) print('\n Conditional state actions \n') print(repr(NameRequestActiveActions.list())) actions = get_nr_state_actions(State.CONDITIONAL, nr_model) print(repr(actions)) print('\n Approved state actions \n') print(repr(NameRequestActiveActions.list())) actions = get_nr_state_actions(State.APPROVED, nr_model) print(repr(actions)) print('\n In Progress state actions \n') print(repr(NameRequestInProgressActions.list())) actions = get_nr_state_actions(State.INPROGRESS, nr_model) print(repr(actions)) print('\n Hold state actions \n') print(repr(NameRequestHoldActions.list())) actions = get_nr_state_actions(State.HOLD, nr_model) print(repr(actions)) print('\n Historical state actions \n') print(repr(NameRequestHistoricalActions.list())) actions = get_nr_state_actions(State.HISTORICAL, nr_model) print(repr(actions)) print('\n Cancelled state actions \n') print(repr(NameRequestCancelledActions.list())) actions = get_nr_state_actions(State.CANCELLED, nr_model) print(repr(actions)) print('\n Rejected state actions \n') print(repr(NameRequestActiveRejectedActions.list())) actions = get_nr_state_actions(State.REJECTED, nr_model) print(repr(actions))
def delete(self, nr_id, payment_id): try: # Find the existing name request nr_model = RequestDAO.query.get(nr_id) if not nr_model: return jsonify(message=f'No NR found with id: {nr_id}.'), 404 # Find the existing payment record payment = PaymentDAO.find_by_payment_token(payment_id) if not payment: return jsonify(message=f'No payment record with id: {payment_id}.'), 404 # check payment record state is CREATED current_payment_state = payment.payment_status_code if current_payment_state != PaymentStatusCode.CREATED.value: return jsonify(message=f'Unable to cancel a payment record in {current_payment_state} state.'), 400 try: # cancelling may change with refactor cancel_payment(payment.payment_token) payment.payment_status_code = PaymentState.CANCELLED.value payment.save_to_db() response_data = nr_model.json() # Add the list of valid Name Request actions for the given state to the response response_data['actions'] = get_nr_state_actions(nr_model.stateCd, nr_model) return jsonify(response_data), 200 except PaymentServiceError as err: # should only get here if there was a conflict (payment went through before cancel happened) return handle_exception(err, err.message, 409) except Exception as err: return handle_exception(err, repr(err), 500)
def get(self, nr_id): return {"message": "Not Implemented"}, 503 try: nr_model = Request.query.get(nr_id) if nr_model.requestTypeCd and (not nr_model.entity_type_cd or not nr_model.request_action_cd): # If requestTypeCd is set, but a request_entity (entity_type_cd) and a request_action (request_action_cd) # are not, use get_mapped_entity_and_action_code to map the values from the requestTypeCd entity_type, request_action = get_mapped_entity_and_action_code( nr_model.requestTypeCd) nr_model.entity_type_cd = entity_type nr_model.request_action_cd = request_action response_data = nr_model.json() # If draft, get the wait time and oldest queued request if nr_model.stateCd == 'DRAFT': service = WaitTimeStatsService() wait_time_response = service.get_waiting_time_dict() response_data.update(wait_time_response) # Add the list of valid Name Request actions for the given state to the response response_data['actions'] = get_nr_state_actions( nr_model.stateCd, nr_model) return jsonify(response_data), 200 except Exception as err: current_app.logger.debug(repr(err)) return handle_exception(err, 'Error retrieving the NR.', 500)
def complete_reapply_payment(self, nr_model: RequestDAO, payment_id: int): """ Invoked when re-applying for an existing Name Request reservation. Extend the Name Request's expiration date by 56 days. If the request action is set to REH or REST, extend the expiration by an additional year (plus the default 56 days). :param nr_model: :param payment_id: :return: """ nr_svc = self.nr_service # Update the state of the payment payment = get_active_payment(nr_model, payment_id) sbc_payment_response = get_payment(payment.payment_token) # TODO: Throw errors if this fails! if sbc_payment_response.statusCode in [ PaymentStatusCode.COMPLETED.value, PaymentStatusCode.APPROVED.value ]: payment.payment_status_code = sbc_payment_response.statusCode payment.payment_completion_date = sbc_payment_response.createdOn payment.save_to_db() if nr_model.submitCount < 3: if nr_model.request_action_cd in [ RequestAction.REH.value, RequestAction.REN.value ]: # If request action is REH or REST extend by 1 year (+ 56 default) days, starting tomorrow nr_model = nr_svc.extend_expiry_date(nr_model, datetime.utcnow(), days=421) nr_model = nr_svc.update_request_submit_count(nr_model) else: # Extend expiry date by (default) 56 days, starting tomorrow nr_model = nr_svc.extend_expiry_date(nr_model, datetime.utcnow(), days=56) nr_model = nr_svc.update_request_submit_count(nr_model) nr_model.save_to_db() else: # TODO: Make a custom exception for this? raise PaymentServiceError( message= 'Submit count maximum of 3 retries has been reached!') # This (optionally) handles the updates for NRO and Solr, if necessary update_solr = False nr_model = self.update_records_in_network_services( nr_model, update_solr) # Update the actions, as things change once the payment is successful self.nr_service.current_state_actions = get_nr_state_actions( nr_model.stateCd, nr_model) # Record the event # EventRecorder.record(nr_svc.user, Event.PATCH + ' [re-apply]', nr_model, nr_svc.request_data) return nr_model
def complete_reservation_payment(self, nr_model, payment_id): """ Invoked when completing an in-progress Name Request reservation. :param nr_model: :param payment_id: :return: """ nr_svc = self.nr_service # Update the state of the payment payment = get_active_payment(nr_model, payment_id) sbc_payment_response = get_payment(payment.payment_token) # TODO: Throw errors if this fails! if sbc_payment_response.status_code in [ PaymentStatusCode.COMPLETED.value ]: payment.payment_status_code = PaymentState.COMPLETED.value payment.payment_completion_date = sbc_payment_response.created_on payment.save_to_db() # Use apply_state_change to change state, as it enforces the State change pattern # apply_state_change takes the model, updates it to the specified state, and executes the callback handler # This handles updates if the NR state is DRAFT, COND_RESERVE or RESERVED # If the state is COND_RESERVE update state to CONDITIONAL # If the state is RESERVED update state to APPROVED # Then update the name request as required if nr_model.stateCd == State.DRAFT: # If the state is DRAFT, leave it as a DRAFT nr_model = nr_svc.apply_state_change(nr_model, State.DRAFT, self.handle_nr_approval) if nr_model.stateCd == State.COND_RESERVE: # If the state is COND_RESERVE update state to CONDITIONAL, and update the name request as required nr_model = nr_svc.apply_state_change(nr_model, State.CONDITIONAL, self.handle_nr_approval) elif nr_model.stateCd == State.RESERVED: # If the state is RESERVED update state to APPROVED, and update the name request as required nr_model = nr_svc.apply_state_change(nr_model, State.APPROVED, self.handle_nr_approval) # Save the name request nr_model.save_to_db() # Update the actions, as things change once the payment is successful self.nr_service.current_state_actions = get_nr_state_actions( nr_model.stateCd, nr_model) # Record the event # EventRecorder.record(nr_svc.user, Event.PATCH + ' [upgrade]', nr_model, nr_svc.request_data) return nr_model
def complete_reservation_payment(self, nr_model: RequestDAO, payment_id: int): """ Invoked when completing an in-progress Name Request reservation. :param nr_model: :param payment_id: :return: """ nr_svc = self.nr_service # Update the state of the payment payment = get_active_payment(nr_model, payment_id) sbc_payment_response = get_payment(payment.payment_token) # TODO: Throw errors if this fails! if sbc_payment_response.statusCode in [ PaymentStatusCode.COMPLETED.value, PaymentStatusCode.APPROVED.value ]: payment.payment_status_code = sbc_payment_response.statusCode payment.payment_completion_date = sbc_payment_response.createdOn payment.save_to_db() # This handles updates if the NR state is DRAFT, COND_RESERVE or RESERVED # If the state is COND_RESERVE update state to CONDITIONAL # If the state is RESERVED update state to APPROVED # Then update the name request as required if nr_model.stateCd == State.DRAFT: # If the state is DRAFT, leave it as a DRAFT nr_model = self.update_nr(nr_model, State.DRAFT, self.handle_nr_approve) if nr_model.stateCd == State.COND_RESERVE: # If the state is COND_RESERVE update state to CONDITIONAL, and update the name request as required nr_model = self.update_nr(nr_model, State.CONDITIONAL, self.handle_nr_approve) elif nr_model.stateCd == State.RESERVED: # If the state is RESERVED update state to APPROVED, and update the name request as required nr_model = self.update_nr(nr_model, State.APPROVED, self.handle_nr_approve) # Save the name request nr_model.save_to_db() # Record the event EventRecorder.record(nr_svc.user, Event.PATCH + ' [payment completed] RESERVE', nr_model, nr_model.json()) # Update the actions, as things change once the payment is successful self.nr_service.current_state_actions = get_nr_state_actions( nr_model.stateCd, nr_model) return nr_model
def complete_upgrade_payment(self, nr_model: RequestDAO, payment_id: int): """ Invoked when upgrading an existing Name Request reservation to PRIORITY status. :param nr_model: :param payment_id: :return: """ nr_svc = self.nr_service if nr_model.stateCd not in [State.DRAFT, State.PENDING_PAYMENT]: raise PaymentServiceError( message= 'Error upgrading Name Request, request is in an invalid state!' ) # Update the state of the payment payment = get_active_payment(nr_model, payment_id) sbc_payment_response = get_payment(payment.payment_token) # TODO: Throw errors if this fails! if sbc_payment_response.statusCode in [ PaymentStatusCode.COMPLETED.value, PaymentStatusCode.APPROVED.value ]: payment.payment_status_code = sbc_payment_response.statusCode payment.payment_completion_date = sbc_payment_response.createdOn payment.save_to_db() nr_model.priorityCd = 'Y' nr_model.priorityDate = datetime.utcnow() # Save the name request nr_model.save_to_db() # This (optionally) handles the updates for NRO and Solr, if necessary update_solr = False nr_model = self.update_records_in_network_services( nr_model, update_solr) # Update the actions, as things change once the payment is successful self.nr_service.current_state_actions = get_nr_state_actions( nr_model.stateCd, nr_model) # Record the event EventRecorder.record(nr_svc.user, Event.PATCH + ' [payment completed] UPGRADE', nr_model, nr_model.json()) return nr_model
def get(self, nr_id): try: nr_model = Request.query.get(nr_id) if nr_model.requestTypeCd and (not nr_model.entity_type_cd or not nr_model.request_action_cd): # If requestTypeCd is set, but a request_entity (entity_type_cd) and a request_action (request_action_cd) # are not, use get_mapped_entity_and_action_code to map the values from the requestTypeCd entity_type, request_action = get_mapped_entity_and_action_code(nr_model.requestTypeCd) nr_model.entity_type_cd = entity_type nr_model.request_action_cd = request_action response_data = nr_model.json() # Add the list of valid Name Request actions for the given state to the response response_data['actions'] = get_nr_state_actions(nr_model.stateCd, nr_model) return jsonify(response_data), 200 except Exception as err: return handle_exception(err, 'Error retrieving the NR.', 500)
def get(self): try: filters = [] # Validate the request if len(request.args) == 0: raise InvalidInputError( message='No query parameters were specified in the request' ) nr_num_query_str = get_query_param_str('nrNum') email_address_query_str = get_query_param_str('emailAddress') phone_number_query_str = get_query_param_str('phoneNumber') if not nr_num_query_str: raise InvalidInputError(message='An nrNum must be provided') else: if not email_address_query_str and not phone_number_query_str: raise InvalidInputError( message= 'Either an emailAddress or phoneNumber must be provided' ) # Continue nr_num = parse_nr_num(nr_num_query_str) email_address = email_address_query_str phone_number = get_query_param_str('phoneNumber') # Filter on addresses # address_line = get_query_param_str('addrLine1') if nr_num: filters.append(func.lower(Request.nrNum) == nr_num.lower()) if phone_number: strip_phone_number_chars_regex = r"[^0-9]" filters.append( Request.applicants.any( func.regexp_replace( Applicant.phoneNumber, strip_phone_number_chars_regex, '', 'g').contains( re.sub(strip_phone_number_chars_regex, '', phone_number)))) if email_address: filters.append( Request.applicants.any( func.lower(Applicant.emailAddress).startswith( email_address.lower()))) ''' Filter on addresses if address_line: filters.append( Request.applicants.any( func.lower(Applicant.addrLine1).startswith(address_line.lower()) ) ) ''' criteria = RequestQueryCriteria(nr_num=nr_num, filters=filters) results = Request.find_by_criteria(criteria) if not results: results = [] except InvalidInputError as err: return handle_exception(err, err.message, 400) except Exception as err: return handle_exception(err, 'Error retrieving the NR from the db.', 500) if nr_num and len(results) == 1: nr_model = results[0] if nr_model.requestTypeCd and (not nr_model.entity_type_cd or not nr_model.request_action_cd): # If requestTypeCd is set, but a request_entity (entity_type_cd) and a request_action (request_action_cd) # are not, use get_mapped_entity_and_action_code to map the values from the requestTypeCd entity_type, request_action = get_mapped_entity_and_action_code( nr_model.requestTypeCd) nr_model.entity_type_cd = entity_type nr_model.request_action_cd = request_action response_data = nr_model.json() # Add the list of valid Name Request actions for the given state to the response response_data['actions'] = get_nr_state_actions( results[0].stateCd, results[0]) return jsonify(response_data), 200 elif len(results) > 0: # We won't add the list of valid Name Request actions for the given state to the response if we're sending back a list # If the user / client accessing this data needs the Name Request actions, GET the individual record using NameRequest.get # This method, NameRequests.get is for Existing NR Search return jsonify(list(map(lambda result: result.json(), results))), 200 # We won't add the list of valid Name Request actions for the given state to the response if we're sending back a list # If the user / client accessing this data needs the Name Request actions, GET the individual record using NameRequest.get # This method, NameRequests.get is for Existing NR Search return jsonify(results), 200
def get(self): try: if not full_access_to_name_request(request): return {"message": "You do not have access to this NameRequest."}, 403 filters = [] nr_num_query_str = request.headers['Bcreg-Nr'] or request.headers['Bcreg-Nrl'] email_address_query_str = request.headers['Bcreg-User-Email'] phone_number_query_str = request.headers['Bcreg-User-Phone'] if not nr_num_query_str: raise InvalidInputError(message='An nrNum must be provided') else: if not email_address_query_str and not phone_number_query_str: raise InvalidInputError(message='Either an emailAddress or phoneNumber must be provided') # Continue nr_num = parse_nr_num(nr_num_query_str) email_address = email_address_query_str phone_number = phone_number_query_str # Filter on addresses # address_line = get_query_param_str('addrLine1') if nr_num: filters.append(func.lower(Request.nrNum) == nr_num.lower()) if phone_number: strip_phone_number_chars_regex = r"[^0-9]" filters.append( Request.applicants.any( func.regexp_replace(Applicant.phoneNumber, strip_phone_number_chars_regex, '', 'g').contains(re.sub(strip_phone_number_chars_regex, '', phone_number)) ) ) if email_address: filters.append( Request.applicants.any( func.lower(Applicant.emailAddress).startswith(email_address.lower()) ) ) ''' Filter on addresses if address_line: filters.append( Request.applicants.any( func.lower(Applicant.addrLine1).startswith(address_line.lower()) ) ) ''' criteria = RequestQueryCriteria( nr_num=nr_num, filters=filters ) results = Request.find_by_criteria(criteria) if not results: results = [] except InvalidInputError as err: return handle_exception(err, err.message, 400) except Exception as err: return handle_exception(err, 'Error retrieving the NR from the db.', 500) if nr_num and len(results) == 1: nr_model = results[0] if nr_model.requestTypeCd and (not nr_model.entity_type_cd or not nr_model.request_action_cd): # If requestTypeCd is set, but a request_entity (entity_type_cd) and a request_action (request_action_cd) # are not, use get_mapped_entity_and_action_code to map the values from the requestTypeCd entity_type, request_action = get_mapped_entity_and_action_code(nr_model.requestTypeCd) nr_model.entity_type_cd = entity_type nr_model.request_action_cd = request_action response_data = nr_model.json() # If draft, get the wait time and oldest queued request if nr_model.stateCd == 'DRAFT': service = WaitTimeStatsService() wait_time_response = service.get_waiting_time_dict() response_data.update(wait_time_response) # Add the list of valid Name Request actions for the given state to the response response_data['actions'] = get_nr_state_actions(results[0].stateCd, results[0]) return jsonify(response_data), 200 elif len(results) > 0: # We won't add the list of valid Name Request actions for the given state to the response if we're sending back a list # If the user / client accessing this data needs the Name Request actions, GET the individual record using NameRequest.get # This method, NameRequests.get is for Existing NR Search return jsonify(list(map(lambda result: result.json(), results))), 200 # We won't add the list of valid Name Request actions for the given state to the response if we're sending back a list # If the user / client accessing this data needs the Name Request actions, GET the individual record using NameRequest.get # This method, NameRequests.get is for Existing NR Search return jsonify(results), 200