Exemplo n.º 1
0
def test_expired_event_history(client, jwt, app):
    from namex.models import Request as RequestDAO, State, Name as NameDAO, User, Event
    from namex.services import EventRecorder

    # add a user for the comment
    user = User('test-user', '', '', '43e6a245-0bf7-4ccf-9bd0-e7fb85fd18cc',
                'https://sso-dev.pathfinder.gov.bc.ca/auth/realms/sbc')
    user.save_to_db()

    # create JWT & setup header with a Bearer Token using the JWT
    token = jwt.create_jwt(claims, token_header)
    headers = {
        'Authorization': 'Bearer ' + token,
        'content-type': 'application/json'
    }

    nr = RequestDAO()
    nr.nrNum = 'NR 0000002'
    nr.stateCd = State.EXPIRED
    nr.requestId = 1460775
    name1 = NameDAO()
    name1.choice = 1
    name1.name = 'TEST NAME ONE'
    nr.names = [name1]
    nr.save_to_db()

    EventRecorder.record(user, Event.POST, nr, {})

    # get the resource (this is the test)
    rv = client.get('/api/v1/events/NR%200000002', headers=headers)
    assert rv.status_code == 200

    assert b'"user_action": "Expired by NRO"' in rv.data
Exemplo n.º 2
0
    def handle_patch_rollback(self, nr_model: Request, action: str):
        """
        Roll back the Name Request.
        :param nr_model:
        :param action:
        :return:
        """
        nr_svc = self.nr_service

        # This handles updates if the NR state is 'patchable'
        nr_model = self.update_nr(nr_model, State.CANCELLED,
                                  self.handle_nr_patch)
        # Only update the record in NRO if it's a real NR, otherwise the record won't exist
        if not is_temp_nr_num(nr_model.nrNum):
            # This handles the updates for NRO and Solr, if necessary
            # self.update_records_in_network_services(nr_model, update_solr=True)
            nr_model = self.update_request_in_nro(nr_model, self.save_nr)

        # Delete in solr for temp or real NR because it is cancelled
        if nr_model.entity_type_cd in [
                'CR', 'UL', 'BC', 'CP', 'PA', 'XCR', 'XUL', 'XCP', 'CC', 'FI',
                'XCR', 'XUL', 'XCP'
        ]:
            SOLR_CORE = 'possible.conflicts'
            self.delete_solr_doc(SOLR_CORE, nr_model.nrNum)

        # Record the event
        EventRecorder.record(nr_svc.user, Event.PATCH, nr_model,
                             nr_svc.request_data)

        return nr_model
Exemplo n.º 3
0
    def post(self):
        try:
            # Creates a new NameRequestService, validates the app config, and sets the request data to the NameRequestService instance
            self.initialize()
            nr_svc = self.nr_service

            # Create a new DRAFT name request
            nr_model = nr_svc.create_name_request()

            # Handle state changes
            # Use update_nr as it enforces the State change pattern
            # Transition the DRAFT to the state specified in the request:
            # eg. one of [State.DRAFT, State.COND_RESERVE, State.RESERVED]
            nr_model = self.update_nr(nr_model, nr_svc.request_state_code,
                                      self.handle_nr_create)

            # Record the event
            EventRecorder.record(nr_svc.user, Event.POST, nr_model,
                                 nr_svc.request_data)

            # Update Solr - note that we don't save DRAFT name requests to Solr for corp entities only
            if nr_model.stateCd in [State.COND_RESERVE, State.RESERVED] and \
                    nr_model.entity_type_cd in \
                    ['CR', 'UL', 'BC', 'CP', 'PA', 'XCR', 'XUL', 'XCP', 'CC', 'FI', 'XCR', 'XUL', 'XCP']:
                self.create_solr_nr_doc(SOLR_CORE, nr_model)

            current_app.logger.debug(nr_model.json())
            response_data = nr_model.json()
            # Add the list of valid Name Request actions for the given state to the response
            response_data['actions'] = nr_svc.current_state_actions
            return jsonify(response_data), 201
        except NameRequestException as err:
            return handle_exception(err, err.message, 500)
        except Exception as err:
            return handle_exception(err, repr(err), 500)
Exemplo n.º 4
0
    def handle_patch_request_refund(self, nr_model: Request):
        """
        Can the NR and request a refund for ALL associated Name Request payments.
        :param nr_model:
        :return:
        """
        nr_svc = self.nr_service

        # This handles updates if the NR state is 'patchable'
        nr_model = self.update_nr(nr_model, State.REFUND_REQUESTED,
                                  self.handle_nr_patch)

        # Handle the payments
        valid_states = [
            PaymentState.COMPLETED.value, PaymentState.PARTIAL.value
        ]
        # Cancel any payments associated with the NR
        for payment in nr_model.payments.all():
            if payment.payment_status_code in valid_states:
                # refund_payment(payment.payment_token, {'reason': 'Name Request user requested refund'})
                refund_payment(payment.payment_token, {})
                payment.payment_status_code = PaymentState.REFUND_REQUESTED.value
                payment.save_to_db()

        # This handles the updates for NRO and Solr, if necessary
        nr_model = self.update_records_in_network_services(nr_model,
                                                           update_solr=True)

        # Record the event
        EventRecorder.record(nr_svc.user, Event.PATCH + ' [request-refund]',
                             nr_model, nr_svc.request_data)

        return nr_model
Exemplo n.º 5
0
    def put(self, nr_id):
        """
        NOT used for Existing Name Request updates that only change the Name Request. Use 'patch' instead.
        State changes handled include state changes to [DRAFT, COND_RESERVE, RESERVED, COND_RESERVE to CONDITIONAL, RESERVED to APPROVED]
        :param nr_id:
        :return:
        """
        try:
            # Find the existing name request
            nr_model = Request.query.get(nr_id)

            # Creates a new NameRequestService, validates the app config, and sets request_data to the NameRequestService instance
            self.initialize()
            nr_svc = self.nr_service

            nr_svc.nr_num = nr_model.nrNum
            nr_svc.nr_id = nr_model.id

            valid_update_states = [
                State.DRAFT, State.COND_RESERVE, State.RESERVED,
                State.PENDING_PAYMENT
            ]

            # This could be moved out, but it's fine here for now
            def validate_put_request(data):
                is_valid = False
                msg = ''
                if data.get('stateCd') in valid_update_states:
                    is_valid = True

                return is_valid, msg

            is_valid_put, validation_msg = validate_put_request(
                self.request_data)
            validation_msg = validation_msg if not len(
                validation_msg) > 0 else 'Invalid request for PUT'

            if not is_valid_put:
                raise InvalidInputError(message=validation_msg)

            if nr_model.stateCd in valid_update_states:
                nr_model = self.update_nr(nr_model, nr_model.stateCd,
                                          self.handle_nr_update)

                # Record the event
                EventRecorder.record(nr_svc.user, Event.PUT, nr_model,
                                     nr_svc.request_data)

            current_app.logger.debug(nr_model.json())
            response_data = nr_model.json()
            # Add the list of valid Name Request actions for the given state to the response
            response_data['actions'] = nr_svc.current_state_actions
            return jsonify(response_data), 200
        except NameRequestException as err:
            return handle_exception(err, err.message, 500)
        except Exception as err:
            return handle_exception(err, repr(err), 500)
Exemplo n.º 6
0
    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
Exemplo n.º 7
0
    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, REN or REST, OR request type is 
        'RCR', 'RUL', 'BERE', 'RCC', 'RCP', 'RFI', 'XRCR', 'RLC', 'XRCP','RSO','XRSO'
        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:
                nr_model = nr_svc.extend_expiry_date(nr_model,
                                                     datetime.utcnow())
                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 + ' [payment completed] REAPPLY',
                             nr_model, nr_model.json())

        return nr_model
Exemplo n.º 8
0
def test_event_create_nrl(client, jwt, app):

    #add a user for the comment
    user = User('test-user', '', '', '43e6a245-0bf7-4ccf-9bd0-e7fb85fd18cc',
                'url')
    user.save_to_db()

    # create JWT & setup header with a Bearer Token using the JWT
    headers = create_header(jwt, [User.EDITOR])

    nr = create_base_nr()

    before_record_date = datetime.utcnow()
    EventRecorder.record(user, Event.POST, nr, nr.json())

    # get the resource (this is the test)
    rv = client.get('/api/v1/events/NR%200000002', headers=headers)
    assert rv.status_code == 200
    assert rv.data
    response = json.loads(rv.data)
    assert response['transactions']
    assert len(response['transactions']) == 1
    assert response['transactions'][0]['additionalInfo'] == 'test'
    assert response['transactions'][0]['consent_dt'] == None
    assert response['transactions'][0]['consentFlag'] == None
    assert response['transactions'][0][
        'eventDate'] > before_record_date.isoformat()
    assert response['transactions'][0]['expirationDate'] == None
    assert response['transactions'][0]['names'] == [{
        'choice': 1,
        'comment': None,
        'conflict1': '',
        'conflict1_num': '',
        'conflict2': '',
        'conflict2_num': '',
        'conflict3': '',
        'conflict3_num': '',
        'consumptionDate': None,
        'corpNum': None,
        'decision_text': '',
        'designation': None,
        'id': 1,
        'name': 'TEST NAME ONE',
        'name_type_cd': None,
        'state': 'NE'
    }]
    assert response['transactions'][0]['priorityCd'] == None
    assert response['transactions'][0]['requestTypeCd'] == 'CR'
    assert response['transactions'][0]['request_action_cd'] == 'NEW'
    assert response['transactions'][0]['stateCd'] == State.PENDING_PAYMENT
    assert response['transactions'][0]['user_action'] == 'Created NRL'
    assert response['transactions'][0]['user_name'] == 'test-user'
Exemplo n.º 9
0
    def handle_patch_resend(self, nr_model: Request):
        nr_svc = self.nr_service

        # This handles updates if the NR state is 'patchable'
        nr_model = self.update_nr(nr_model, nr_model.stateCd, self.handle_nr_patch)

        # This handles the updates for NRO and Solr, if necessary
        nr_model = self.update_records_in_network_services(nr_model, update_solr=False)

        # Record the event
        EventRecorder.record(nr_svc.user, Event.PATCH + ' [re-send]', nr_model, nr_svc.request_data)

        return nr_model
Exemplo n.º 10
0
    def update_nr(self, nr_model):
        nr_svc = self.nr_service

        # 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
        nr_model = nr_svc.apply_state_change(nr_model, nr_model.stateCd,
                                             self.handle_nr_update)

        # Record the event
        EventRecorder.record(nr_svc.user, Event.PUT, nr_model,
                             nr_svc.request_data)

        return nr_model
Exemplo n.º 11
0
    def handle_patch_request_refund(self, nr_model: Request):
        """
        Can the NR and request a refund for ALL associated Name Request payments.
        :param nr_model:
        :return:
        """
        nr_svc = self.nr_service

        # This handles updates if the NR state is 'patchable'
        nr_model = self.update_nr(nr_model, State.REFUND_REQUESTED,
                                  self.handle_nr_patch)

        # Handle the payments
        valid_states = [
            PaymentState.APPROVED.value, PaymentState.COMPLETED.value,
            PaymentState.PARTIAL.value
        ]

        refund_value = 0

        # Check for NR that has been renewed - do not refund any payments.
        # UI should not order refund for an NR renewed/reapplied it.
        if not any(
                payment.payment_action == Payment.PaymentActions.REAPPLY.value
                for payment in nr_model.payments.all()):
            # Try to refund all payments associated with the NR
            for payment in nr_model.payments.all():
                if payment.payment_status_code in valid_states:
                    # Some refunds may fail. Some payment methods are not refundable and return HTTP 400 at the refund.
                    # The refund status is checked from the payment_response and a appropriate message is displayed by the UI.
                    refund_payment(payment.payment_token, {})
                    payment_response = get_payment(payment.payment_token)
                    payment.payment_status_code = PaymentState.REFUND_REQUESTED.value
                    payment.save_to_db()
                    refund_value += payment_response.receipts[0][
                        'receiptAmount'] if len(
                            payment_response.receipts) else 0

        publish_email_notification(nr_model.nrNum, 'refund',
                                   '{:.2f}'.format(refund_value))

        # This handles the updates for NRO and Solr, if necessary
        nr_model = self.update_records_in_network_services(nr_model,
                                                           update_solr=True)

        # Record the event
        EventRecorder.record(nr_svc.user, Event.PATCH + ' [request-refund]',
                             nr_model, nr_model.json())

        return nr_model
Exemplo n.º 12
0
    def handle_patch_checkout(self, nr_model: Request):
        nr_svc = self.nr_service

        # This handles updates if the NR state is 'patchable'
        nr_model = self.update_nr(nr_model, State.INPROGRESS, self.handle_nr_patch)

        # Lock nro Request row (set status=H)
        nro_warnings = self.lock_request_in_nro(nr_model)
        if nro_warnings:
            on_success = False
            return self.on_nro_update_complete(nr_model, on_success, nro_warnings)

        EventRecorder.record(nr_svc.user, Event.PATCH + ' [checkout]', nr_model, {})
        return nr_model
Exemplo n.º 13
0
    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
Exemplo n.º 14
0
    def handle_patch_checkin(self, nr_model: Request):
        nr_svc = self.nr_service

        # This handles updates if the NR state is 'patchable'
        nr_model = self.update_nr(nr_model, State.DRAFT, self.handle_nr_patch)

        # Set status back to D after edit is complete
        nro_warnings = self.unlock_request_in_nro(nr_model)
        if nro_warnings:
            on_success = False
            return self.on_nro_update_complete(nr_model, on_success, nro_warnings)
        # Record the event
        EventRecorder.record(nr_svc.user, Event.PATCH + ' [checkin]', nr_model, {})

        return nr_model
Exemplo n.º 15
0
    def handle_patch_edit(self, nr_model):
        nr_svc = self.nr_service

        # This handles updates if the NR state is 'patchable'
        nr_model = self.update_nr_fields(nr_model, nr_model.stateCd)

        # This handles the updates for NRO and Solr, if necessary
        update_solr = False
        nr_model = self.update_records_in_network_services(
            nr_model, update_solr)

        # Record the event
        EventRecorder.record(nr_svc.user, Event.PATCH + ' [edit]', nr_model,
                             nr_svc.request_data)

        return nr_model
Exemplo n.º 16
0
    def handle_patch_cancel(self, nr_model: Request):
        """
        Cancel the Name Request.
        :param nr_model:
        :return:
        """
        nr_svc = self.nr_service

        # This handles updates if the NR state is 'patchable'
        nr_model = self.update_nr(nr_model, State.CANCELLED, self.handle_nr_patch)

        # This handles the updates for NRO and Solr, if necessary
        nr_model = self.update_records_in_network_services(nr_model, update_solr=True)

        # Record the event
        EventRecorder.record(nr_svc.user, Event.PATCH + ' [cancel]', nr_model, nr_svc.request_data)

        return nr_model
Exemplo n.º 17
0
    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()
                nr_svc = self.nr_service
                EventRecorder.record(
                    nr_svc.user, Event.DELETE +
                    f' [payment cancelled] {payment.payment_action}', nr_model,
                    nr_model.json())

                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)
Exemplo n.º 18
0
def test_get_inprogress_event_history(client, jwt, app):

    # add a user for the comment
    user = User('test-user', '', '', '43e6a245-0bf7-4ccf-9bd0-e7fb85fd18cc', 'url')
    user.save_to_db()

    # create JWT & setup header with a Bearer Token using the JWT
    headers = create_header(jwt, [User.EDITOR])

    nr = create_base_nr()
    nr.stateCd = State.DRAFT
    nr.save_to_db()
    EventRecorder.record(user, Event.POST + ' [payment completed] CREATE', nr, nr.json())

    nr.stateCd = State.INPROGRESS
    nr.save_to_db()
    EventRecorder.record(user, Event.PATCH, nr, { 'state': 'INPROGRESS' })
    # get the resource (this is the test)
    rv = client.get('/api/v1/events/NR%200000002', headers=headers)
    assert rv.status_code == 200

    assert b'"user_action": "Load NR"' in rv.data
Exemplo n.º 19
0
def test_decision_event_history(client, jwt, app):
    from namex.models import Request as RequestDAO, State, Name as NameDAO, User, Event
    from namex.services import EventRecorder

    # add a user for the comment
    user = User('test-user', '', '', '43e6a245-0bf7-4ccf-9bd0-e7fb85fd18cc',
                'https://sso-dev.pathfinder.gov.bc.ca/auth/realms/sbc')
    user.save_to_db()

    headers = create_header(jwt, [User.EDITOR])

    nr = create_base_nr()
    nr.stateCd = State.REJECTED
    nr.save_to_db()

    EventRecorder.record(user, Event.PATCH, nr, {'state': 'REJECTED'})

    # get the resource (this is the test)
    rv = client.get('/api/v1/events/NR%200000002', headers=headers)
    assert rv.status_code == 200

    assert b'"user_action": "Decision"' in rv.data
Exemplo n.º 20
0
def test_edit_event_history(client, jwt, app):
    from namex.models import Request as RequestDAO, State, Name as NameDAO, User, Event
    from namex.services import EventRecorder

    # add a user for the comment
    user = User('test-user', '', '', '43e6a245-0bf7-4ccf-9bd0-e7fb85fd18cc',
                'https://sso-dev.pathfinder.gov.bc.ca/auth/realms/sbc')
    user.save_to_db()

    headers = create_header(jwt, [User.EDITOR])

    nr = create_base_nr()
    nr.stateCd = State.INPROGRESS
    nr.additionalInfo = 'additional'
    nr.save_to_db()

    EventRecorder.record(user, Event.PUT, nr, nr.json())

    # get the resource (this is the test)
    rv = client.get('/api/v1/events/NR%200000002', headers=headers)
    assert rv.status_code == 200

    assert b'"user_action": "Edit NR Details (NameX)"' in rv.data
Exemplo n.º 21
0
def test_consumed_event_history(client, jwt, app):
    from namex.models import State, User, Event
    from namex.services import EventRecorder

    # add a user for the comment
    user = User('nro_service_account', '', '',
                '8ca7d47a-024e-4c85-a367-57c9c93de1cd',
                'https://sso-dev.pathfinder.gov.bc.ca/auth/realms/sbc')
    user.save_to_db()

    headers = create_header(jwt, [User.EDITOR])

    nr = create_base_nr()
    nr.stateCd = State.CONSUMED
    nr.save_to_db()

    EventRecorder.record_as_system(Event.UPDATE_FROM_NRO, nr, nr.json())

    # get the resource (this is the test)
    rv = client.get('/api/v1/events/NR%200000002', headers=headers)
    assert rv.status_code == 200

    assert b'"user_action": "Get NR Details from NRO"' in rv.data
Exemplo n.º 22
0
def job(user: User, max_rows: int, delay: int) -> (int, bool):
    row_count = 0

    try:

        reqs = db.session.query(Request). \
            filter(Request.stateCd == State.INPROGRESS). \
            filter(Request.lastUpdate <= text('(now() at time zone \'utc\') - INTERVAL \'{delay} SECONDS\''.format(delay=delay))). \
            order_by(Request.lastUpdate.asc()). \
            limit(max_rows). \
            with_for_update().all()

        for r in reqs:
            row_count += 1

            current_app.logger.debug('processing: {}'.format(r.nrNum))

            print ('nr {}, state: {} last_update:{}'.format(r.nrNum, r.stateCd, r.lastUpdate))

            # if this NR was previously in DRAFT, reset it to that state (ie: the user walked away from an open edit window)
            if r.previousStateCd == State.DRAFT:
                r.stateCd = State.DRAFT
                r.previousStateCd = None
            # otherwise put it on hold
            else:
                r.stateCd = State.HOLD

            db.session.add(r)
            EventRecorder.record(user, Event.MARKED_ON_HOLD, r, {}, save_to_session=True)

        db.session.commit()
        return row_count, True

    except Exception as err:
        current_app.logger.error(err)
        db.session.rollback()
        return -1, False
Exemplo n.º 23
0
 def cancel_payment(self, nr_model: RequestDAO, payment_id: int):
     # Cancel payment with specified id.
     valid_states = [PaymentState.CREATED.value]
     for payment in nr_model.payments.all():
         if payment.id == payment_id and payment.payment_status_code in valid_states:
             sbc_payment_response = get_payment(payment.payment_token)
             if sbc_payment_response.statusCode in [
                     PaymentStatusCode.COMPLETED.value,
                     PaymentStatusCode.APPROVED.value
             ]:
                 raise PaymentServiceError(
                     message=
                     'Error cancelling payment. Payment is in a completed state!'
                 )
             cancel_payment(payment.payment_token)
             payment.payment_status_code = PaymentState.CANCELLED.value
             payment.save_to_db()
             # record the event
             nr_svc = self.nr_service
             EventRecorder.record(
                 nr_svc.user, Event.DELETE +
                 f' [payment cancelled] {payment.payment_action}', nr_model,
                 nr_model.json())
     return nr_model
Exemplo n.º 24
0
    def handle_patch_rollback(self, nr_model, action):
        """
        Roll back the Name Request.
        :param nr_model:
        :param action:
        :return:
        """
        nr_svc = self.nr_service

        # This handles updates if the NR state is 'patchable'
        nr_model = self.update_nr_fields(nr_model, State.CANCELLED)
        # Only update the record in NRO if it's a real NR, otherwise the record won't exist
        if not is_temp_nr_num(nr_model.nrNum):
            # This handles the updates for NRO and Solr, if necessary
            self.update_records_in_network_services(nr_model, update_solr=True)
        else:
            temp_nr_num = nr_model.nrNum
            # Update SOLR
            self.update_solr_service(nr_model, temp_nr_num)
        # Record the event
        EventRecorder.record(nr_svc.user, Event.PATCH, nr_model,
                             nr_svc.request_data)

        return nr_model
Exemplo n.º 25
0
def test_edit_inprogress_event_history(client, jwt, app):
    from namex.models import Request as RequestDAO, State, Name as NameDAO, User, Event
    from namex.services import EventRecorder

    # add a user for the comment
    user = User('test-user', '', '', '43e6a245-0bf7-4ccf-9bd0-e7fb85fd18cc',
                'https://sso-dev.pathfinder.gov.bc.ca/auth/realms/sbc')
    user.save_to_db()

    headers = create_header(jwt, [User.EDITOR])

    nr = RequestDAO()
    nr.nrNum = 'NR 0000002'
    nr.stateCd = State.DRAFT
    nr.requestId = 1460775
    nr._source = 'NRO'
    name1 = NameDAO()
    name1.choice = 1
    name1.name = 'TEST NAME ONE'
    nr.names = [name1]
    nr.save_to_db()

    EventRecorder.record(user, Event.POST, nr, nr.json())

    nr.stateCd = State.INPROGRESS
    nr.save_to_db()
    EventRecorder.record(user, Event.PUT, nr, {
        "additional": "additional",
        "furnished": "N"
    })

    # get the resource (this is the test)
    rv = client.get('/api/v1/events/NR%200000002', headers=headers)
    assert rv.status_code == 200

    assert b'"user_action": "Edit NR Details (NameX)"' in rv.data
Exemplo n.º 26
0
def job(app, namex_db, nro_connection, user, max_rows=100):
    """Process the NRs that have been updated in the NamesDB.

    Most updates will go away as NRO (the legacy UI for the NamesDB) is decommissioned.

    The following states allow the following changes:

    - all changes allowed: DRAFT, PENDING_PAYMENT

    - no changes allowed: INPROGRESS, REFUND_REQUESTED, REJECTED, EXPIRED, HISTORICAL, COMPLETED

    - set cancelled state: CANCELLED

    - all changes, except for state: HOLD

    - consumed info only: RESERVED, COND_RESERVE, APPROVED, CONDITIONAL
    """
    row_count = 0

    try:
        ora_con = nro_connection
        # get the NRs from Oracle NamesDB of interest
        result, col_names = job_result_set(ora_con, max_rows)

        for r in result:

            row_count += 1

            row = ora_row_to_dict(col_names, r)

            nr_num = row['nr_num']
            nr = Request.find_by_nr(nr_num)
            action = row['action']

            current_app.logger.debug(
                'processing: {}, NameX state: {}, action: {}'.format(
                    nr_num, None if (not nr) else nr.stateCd, action))

            # NO CHANGES ALLOWED
            if nr and (nr.stateCd in [
                    State.INPROGRESS, State.REFUND_REQUESTED, State.REJECTED,
                    State.EXPIRED, State.HISTORICAL, State.COMPLETED
            ]):
                success = update_feeder_row(
                    ora_con,
                    row_id=row['id'],
                    status='C',
                    send_count=1 + 0 if
                    (row['send_count'] is None) else row['send_count'],
                    error_message='Ignored - Request: not processed')
                ora_con.commit()
                # continue to next row
                current_app.logger.info(
                    'skipping: {}, NameX state: {}, action: {}'.format(
                        nr_num, None if (not nr) else nr.stateCd, action))
                continue

            # ignore existing NRs not in a completed state or draft, or in a completed state and not furnished
            if nr and (
                    nr.stateCd not in State.COMPLETED_STATE + [State.DRAFT] or
                (nr.stateCd in State.COMPLETED_STATE and nr.furnished == 'N')):
                success = update_feeder_row(
                    ora_con,
                    row_id=row['id'],
                    status='C',
                    send_count=1 + 0 if
                    (row['send_count'] is None) else row['send_count'],
                    error_message='Ignored - Request: not processed')
                ora_con.commit()
                continue
            # for any NRs in a completed state or new NRs not existing in NameX
            else:  # pylint: disable=R1724: Unnecessary "else"
                try:
                    # get submitter
                    ora_cursor = ora_con.cursor()
                    nr_header = get_nr_header(ora_cursor, nr_num)
                    nr_submitter = get_nr_submitter(ora_cursor,
                                                    nr_header['request_id'])
                    # get pending payments
                    pending_payments = []
                    if nr:
                        pending_payments = [
                            x for x in nr.payments.all()
                            if x.payment_status_code ==
                            PaymentStatusCode.CREATED.value
                        ]
                    # ignore if:
                    # - NR does not exist and NR originated in namex (handles racetime condition for when it is still in the process of saving)
                    # - NR has a pending update from namex (pending payment)
                    if (not nr and nr_submitter
                            and nr_submitter.get('submitter', '')
                            == 'namex') or (nr and len(pending_payments) > 0):
                        success = update_feeder_row(
                            ora_con,
                            row_id=row['id'],
                            status='C',
                            send_count=1 + 0 if
                            (row['send_count'] is None) else row['send_count'],
                            error_message='Ignored - Request: not processed')
                        ora_con.commit()
                    else:
                        nr = nro.fetch_nro_request_and_copy_to_namex_request(
                            user, nr_number=nr_num, name_request=nr)

                        namex_db.session.add(nr)
                        EventRecorder.record(user,
                                             Event.UPDATE_FROM_NRO,
                                             nr,
                                             nr.json(),
                                             save_to_session=True)
                        current_app.logger.debug(
                            'EventRecorder should have been saved to by now, although not committed'
                        )
                        success = update_feeder_row(
                            ora_con,
                            row_id=row['id'],
                            status='C',
                            send_count=1 + 0 if
                            (row['send_count'] is None) else row['send_count'],
                            error_message=None)

                        if success:
                            ora_con.commit()
                            current_app.logger.debug('Oracle commit done')
                            namex_db.session.commit()
                            current_app.logger.debug('Postgresql commit done')
                        else:
                            raise Exception()

                except Exception as err:
                    current_app.logger.error(err.with_traceback(None))
                    success = update_feeder_row(
                        ora_con,
                        row_id=row['id'],
                        status=row['status'],
                        send_count=1 + 0 if
                        (row['send_count'] is None) else row['send_count'],
                        error_message=err.with_traceback(None))
                    namex_db.session.rollback()
                    ora_con.commit()

        return row_count

    except Exception as err:
        current_app.logger.error('Update Failed:', err.with_traceback(None))
        return -1
Exemplo n.º 27
0
    def move_control_of_request_from_nro(self, nr, user, closed_nr=False):
        """ HIGHLY DESTRUCTIVE CALL

        This will move the loci of control of a request from NRO to NameX
        In doing so it'll update the NameX record if it is out of sync with the NRO info
        with the CURRENT NRO information OVER-WRITING the NameX info
        It will set the NameX lastUpdate to NOW

        SAFETY checks:
        This WON'T do anything if the NRO record is not in Draft
        This WON'T do anything if the NameX record is not in Draft
        This WON'T do anything if the NameX lastUpdate is newer than the NameX.nroLastUpdate field

        :param nr:
        :param user:
        :param closed_nr: boolean
        :return:
        """
        warnings = []

        if not (nr and user):
            warnings.append({
                'type':
                'warn',
                'code':
                'unable_to_move_control_from_nro',
                'message':
                'NameRequest and User must be provided to attempt to move control from NRO.'
            })
            return warnings

        # save the current state, as we'll need to set it back to this before returning
        nr_saved_state = nr.stateCd
        # get the last modification timestamp before we alter the record
        try:
            nro_last_ts = self.get_last_update_timestamp(nr.requestId)
        except (NROServicesError, Exception) as err:
            nro_last_ts = None
            warnings.append({
                'type':
                'warn',
                'code':
                'unable_to_get_last_nro_ts',
                'message':
                'Unable to get last time the NR was updated in NRO'
            })
        if not closed_nr:
            current_app.logger.debug('set state to h')
            try:
                self.set_request_status_to_h(nr.nrNum, user.username)
            except (NROServicesError, Exception) as err:
                warnings.append({
                    'type':
                    'warn',
                    'code':
                    'unable_to_set_NR_status_in_NRO_to_H',
                    'message':
                    'Unable to set the NR in NRO to HOLD. '
                    'Please contact support to alert them of this issue'
                    ' and provide the Request #.'
                })

            current_app.logger.debug('get state')
            try:
                nro_req_state = self.get_current_request_state(nr.nrNum)
            except (NROServicesError, Exception) as err:
                nro_req_state = None

            if nro_req_state is not 'H':
                warnings.append({
                    'type':
                    'warn',
                    'code':
                    'unable_to_verify_NR_state_of_H',
                    'message':
                    'Unable to get the current state of the NRO Request'
                })
                current_app.logger.debug(
                    'nro state not set to H, nro-package call must have silently failed - ugh'
                )

        current_app.logger.debug('update records')
        current_app.logger.debug('nro_last_ts: {}'.format(nro_last_ts))
        current_app.logger.debug('nr.nroLastUpdate: {}'.format(
            nr.nroLastUpdate))
        if 'nro_last_ts' in locals() and nro_last_ts != nr.nroLastUpdate:
            current_app.logger.debug(
                'nro updated since namex was last updated')
            try:
                # mark the NR as being updated
                nr.stateCd = State.NRO_UPDATING
                nr.save_to_db()

                nrf = self.fetch_nro_request_and_copy_to_namex_request(
                    user, nr_number=nr.nrNum, name_request=nr)
                if nrf:
                    nr = nrf
                nr.stateCd = nr_saved_state
                nr.save_to_db()
                EventRecorder.record(user, Event.UPDATE_FROM_NRO, nr, {})

            except Exception as missed_error:
                warnings.append({
                    'type':
                    'warn',
                    'code':
                    'unable_to_update_request_from_NRO',
                    'message':
                    'Unable to update the Request from the NRO system,'
                    ' please manually verify record is up to date before'
                    ' approving/rejecting.'
                })
                current_app.logger.error(missed_error.with_traceback(None))
            finally:
                # set the NR back to its initial state
                nr.stateCd = nr_saved_state
                nr.save_to_db()

        return warnings if len(warnings) > 0 else None
Exemplo n.º 28
0
                        elif payment_action == PaymentDAO.PaymentActions.REAPPLY.value:
                            # TODO: handle this (refund payment and prevent action?)
                            if nr_model.stateCd != State.APPROVED \
                                    and nr_model.expirationDate + timedelta(hours=NAME_REQUEST_EXTENSION_PAD_HOURS) < datetime.utcnow():
                                msg = f'Extend NR for payment.id={payment.id} nr_model.state{nr_model.stateCd}, nr_model.expires:{nr_model.expirationDate}'
                                current_app.logger.debug(msg)

                            nr_model.expirationDate = nr_model.expirationDate + timedelta(
                                days=NAME_REQUEST_LIFESPAN_DAYS)
                            payment.payment_completion_date = datetime.utcnow()

                        nr_model.save_to_db()
                        payment.save_to_db()
                        EventRecorder.record(
                            nr_svc.user, Event.POST +
                            f' [payment completed { payment_action }]',
                            nr_model, nr_model.json())
                        if payment_action in [
                                payment.PaymentActions.UPGRADE.value,
                                payment.PaymentActions.REAPPLY.value
                        ]:
                            change_flags = {
                                'is_changed__request': True,
                                'is_changed__previous_request': False,
                                'is_changed__applicant': False,
                                'is_changed__address': False,
                                'is_changed__name1': False,
                                'is_changed__name2': False,
                                'is_changed__name3': False,
                                'is_changed__nwpta_ab': False,
                                'is_changed__nwpta_sk': False,
Exemplo n.º 29
0
def job(app, namex_db, nro_connection, user, max_rows=100):

    row_count = 0

    try:
        ora_con = nro_connection
        result, col_names = job_result_set(ora_con, max_rows)

        for r in result:

            row_count += 1

            row = ora_row_to_dict(col_names, r)

            nr_num = row['nr_num']
            nr = Request.find_by_nr(nr_num)
            action = row['action']

            current_app.logger.debug(
                'processing: {}, NameX state: {}, action: {}'.format(
                    nr_num, None if (not nr) else nr.stateCd, action))

            if nr and (nr.stateCd != State.DRAFT):
                if action != 'X':
                    success = update_feeder_row(
                        ora_con,
                        id=row['id'],
                        status='C',
                        send_count=1 + 0 if
                        (row['send_count'] is None) else row['send_count'],
                        error_message='Ignored - Request: not processed')
                    ora_con.commit()
                    continue
            try:
                nr = nro.fetch_nro_request_and_copy_to_namex_request(
                    user, nr_number=nr_num, name_request=nr)

                namex_db.session.add(nr)
                EventRecorder.record(user,
                                     Event.UPDATE_FROM_NRO,
                                     nr, {},
                                     save_to_session=True)

                success = update_feeder_row(
                    ora_con,
                    id=row['id'],
                    status='C',
                    send_count=1 + 0 if
                    (row['send_count'] is None) else row['send_count'],
                    error_message=None)

                if success:
                    ora_con.commit()
                    namex_db.session.commit()
                else:
                    raise Exception()

            except Exception as err:
                current_app.logger.error(err.with_traceback(None))
                success = update_feeder_row(
                    ora_con,
                    id=row['id'],
                    status=row['status'],
                    send_count=1 + 0 if
                    (row['send_count'] is None) else row['send_count'],
                    error_message=err.with_traceback(None))
                namex_db.session.rollback()
                ora_con.commit()

        return row_count

    except Exception as err:
        current_app.logger.error('Update Failed:', err.with_traceback(None))
        return -1
Exemplo n.º 30
0
    #
    current_app.logger.debug(str(q.statement.compile(
        dialect=postgresql.dialect(),
        compile_kwargs={"literal_binds": True}))
    )

    for r in q.all():
        row_count += 1

        current_app.logger.debug('processing: {}'.format(r.nrNum))

        try:

            nro_data_pump_update(r, ora_cursor, expires_days)
            db.session.add(r)
            EventRecorder.record(user, Event.NRO_UPDATE, r, r.json(), save_to_session=True)

            ora_con.commit()
            db.session.commit()
            JobTracker.job_detail(db, job_id, r.nrNum)

        except Exception as err:
            current_app.logger.error(err)
            current_app.logger.error('ERROR: {}'.format(r.nrNum))
            db.session.rollback()
            ora_con.rollback()
            JobTracker.job_detail_error(db, job_id, r.nrNum, str(err))

    JobTracker.end_job(db, job_id, datetime.utcnow(), 'success')

except Exception as err: