Пример #1
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 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
Пример #2
0
    def get(self, nr_id):
        try:
            nr_model = RequestDAO.query.get(nr_id)
            nr_payments = nr_model.payments.all()

            response_data = []
            # Wrap our payment
            for payment in nr_payments:
                payment_response = get_payment(payment.payment_token)
                receipts = payment_response.receipts
                # Wrap the response, providing info from both the SBC Pay response and the payment we created
                response_data.append({
                    'id': payment.id,
                    'nrId': payment.nrId,
                    'token': payment.payment_token,
                    'statusCode': payment.payment_status_code,
                    'action': payment.payment_action,
                    'completionDate': payment.payment_completion_date,
                    'payment': payment.as_dict(),
                    'sbcPayment': payment_response.as_dict(),
                    'receipts': list(map(lambda r: map_receipt(r), receipts))
                })

            return jsonify(response_data), 200
        except PaymentServiceError as err:
            return handle_exception(err, err.message, 500)
        except SBCPaymentException as err:
            return handle_exception(err, err.message, err.status_code)
        except SBCPaymentError as err:
            return handle_exception(err, err.message, 500)
        except Exception as err:
            return handle_exception(err, err, 500)
Пример #3
0
    def get(self, nr_id):
        try:
            nr_model = RequestDAO.query.get(nr_id)
            nr_payments = nr_model.payments.all()

            response_data = []
            # Wrap our payment
            for payment in nr_payments:
                payment_response = get_payment(payment.payment_token)
                receipts = payment_response.receipts
                if not receipts and payment_response.statusCode == PaymentState.APPROVED.value:
                    # generate temp receipts for approved payments
                    current_app.logger.debug('adding temporary receipt details.')
                    receipts = [
                        {
                            'id': payment.payment_token,
                            'receiptAmount': None,
                            'receiptDate': None,
                            'receiptNumber': 'Pending'
                        }
                    ]
                    payment_response.receipts = receipts
                    response_data.append({
                        'id': payment.id,
                        'nrId': payment.nrId,
                        'token': payment.payment_token,
                        'statusCode': payment.payment_status_code,
                        'action': payment.payment_action,
                        'completionDate': payment.payment_completion_date,
                        'payment': payment.as_dict(),
                        'sbcPayment': payment_response.as_dict(),
                        'receipts': receipts
                    })
                else:
                    # Wrap the response, providing info from both the SBC Pay response and the payment we created
                    response_data.append({
                        'id': payment.id,
                        'nrId': payment.nrId,
                        'token': payment.payment_token,
                        'statusCode': payment.payment_status_code,
                        'action': payment.payment_action,
                        'completionDate': payment.payment_completion_date,
                        'payment': payment.as_dict(),
                        'sbcPayment': payment_response.as_dict(),
                        'receipts': list(map(lambda r: map_receipt(r), receipts))
                    })

            return jsonify(response_data), 200
        except PaymentServiceError as err:
            return handle_exception(err, err.message, 500)
        except SBCPaymentException as err:
            return handle_exception(err, err.message, err.status_code)
        except SBCPaymentError as err:
            return handle_exception(err, err.message, 500)
        except Exception as err:
            return handle_exception(err, err, 500)
Пример #4
0
    def _should_refund_sbc_payment(payment_token) -> bool:
        refund_sbc_payment = True
        payment_response = get_payment(payment_token)
        if payment_response.routingSlip:
            refund_sbc_payment = False
        elif len(payment_response.lineItems
                 ) == 1 and payment_response.lineItems[0]['waivedBy']:
            refund_sbc_payment = False

        return refund_sbc_payment
Пример #5
0
    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
Пример #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
Пример #7
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
Пример #8
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]:
                 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()
     return nr_model
Пример #9
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
Пример #10
0
    def get(payment_identifier):
        try:
            payment_identifier = clean_url_path_param(payment_identifier)

            payment = get_payment(payment_identifier)

            if not payment:
                return jsonify(message=MSG_NOT_FOUND), 404

            data = jsonify(payment.to_dict())
            response = make_response(data, 200)
            return response

        except Exception as err:
            return jsonify(message=MSG_SERVER_ERROR + ' ' + str(err)), 500
Пример #11
0
    def get(self, nr_id, payment_id):
        try:
            # Find the existing name request
            nr_model = RequestDAO.query.get(nr_id)

            if not nr_model:
                # Should this be a 400 or 404... hmmm
                return jsonify(message='{nr_id} not found'.format(
                    nr_id=nr_id)), 400

            payment_id = int(clean_url_path_param(payment_id))
            payment = PaymentDAO.query.get(payment_id)

            payment_response = get_payment(payment.payment_token)
            receipts = payment_response.receipts
            # Wrap the response, providing info from both the SBC Pay response and the payment we created
            data = jsonify({
                'id':
                payment.id,
                'nrId':
                payment.nrId,
                'token':
                payment.payment_token,
                'statusCode':
                payment.payment_status_code,
                'completionDate':
                payment.payment_completion_date,
                'payment':
                payment.as_dict(),
                'sbcPayment':
                payment_response.as_dict(),
                'receipts':
                list(map(lambda r: map_receipt(r), receipts))
            })

            response = make_response(data, 200)
            return response

        except PaymentServiceError as err:
            return handle_exception(err, err.message, 500)
        except SBCPaymentException as err:
            return handle_exception(err, err.message, err.status_code)
        except SBCPaymentError as err:
            return handle_exception(err, err.message, 500)
        except Exception as err:
            return handle_exception(err, err, 500)
Пример #12
0
    def get(payment_id):
        try:
            payment = PaymentDAO.query.get(payment_id)
            # Find the existing name request
            nr_model = RequestDAO.query.get(payment.nrId)

            if not nr_model:
                # Should this be a 400 or 404... hmmm
                return jsonify(message='{nr_id} not found'.format(
                    nr_id=payment.nrId)), 400

            payment_response = get_payment(payment.payment_token)
            # TODO: Make sure we pick the right one... use the first choice
            corp_name = nr_model.names.all()[0].name

            req = PaymentReceiptInput(
                corp_name=corp_name,
                business_number=None,
                recognition_date_time=None,
                filing_identifier=None,
                filing_date_time=payment_response.created_on,
                file_name=None)

            receipt_response = get_receipt(payment.payment_token, req)

            if not receipt_response:
                return jsonify(message=MSG_NOT_FOUND
                               ), 404  # TODO: What if we have a record?

            return send_file(receipt_response,
                             mimetype='application/pdf',
                             as_attachment=True)

        except PaymentServiceError as err:
            return handle_exception(err, err.message, 500)
        except SBCPaymentException as err:
            return handle_exception(err, err.message, err.status_code)
        except SBCPaymentError as err:
            return handle_exception(err, err.message, 500)
        except Exception as err:
            return handle_exception(err, err, 500)
Пример #13
0
    def get(payment_identifier):
        try:
            payment_identifier = clean_url_path_param(payment_identifier)

            payment = get_payment(payment_identifier)

            if not payment:
                return jsonify(message=MSG_NOT_FOUND), 404

            data = jsonify(payment)
            response = make_response(data, 200)
            return response

        except PaymentServiceError as err:
            return handle_exception(err, err.message, 500)
        except SBCPaymentException as err:
            return handle_exception(err, err.message, err.status_code)
        except SBCPaymentError as err:
            return handle_exception(err, err.message, 500)
        except Exception as err:
            return handle_exception(err, err, 500)
Пример #14
0
    def get(self, nr_id):
        try:
            nr_model = RequestDAO.query.get(nr_id)
            nr_payments = nr_model.payments.all()

            response_data = []
            # Wrap our payment
            for payment in nr_payments:
                payment_response = get_payment(payment.payment_token)
                # TODO: Replace this when we're ready!
                invoices_response = []  # get_invoices(payment.payment_token)

                if not payment_response:
                    return None
                # Don't blow up just because we can't get the invoices
                if not invoices_response or isinstance(invoices_response,
                                                       list) is False:
                    invoices_response = []

                # Wrap the response, providing info from both the SBC Pay response and the payment we created
                response_data.append({
                    'id': payment.id,
                    'nrId': payment.nrId,
                    'token': payment.payment_token,
                    'statusCode': payment.payment_status_code,
                    'completionDate': payment.payment_completion_date,
                    'invoices': invoices_response,
                    'payment': payment.as_dict(),
                    'sbcPayment': payment_response.to_dict()
                })

            return jsonify(response_data), 200
        except PaymentServiceError as err:
            return handle_exception(err, err.message, 500)
        except SBCPaymentException as err:
            return handle_exception(err, err.message, err.status_code)
        except SBCPaymentError as err:
            return handle_exception(err, err.message, 500)
        except Exception as err:
            return handle_exception(err, err, 500)
Пример #15
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
Пример #16
0
    def get(self, nr_id, payment_id):
        try:
            # Find the existing name request
            nr_model = RequestDAO.query.get(nr_id)

            if not nr_model:
                # Should this be a 400 or 404... hmmm
                return jsonify(message='{nr_id} not found'.format(
                    nr_id=nr_id)), 400

            payment_id = int(clean_url_path_param(payment_id))
            payment = PaymentDAO.query.get(payment_id)

            payment_response = get_payment(payment.payment_token)
            receipts = payment_response.receipts
            data = []
            if not receipts and payment_response.statusCode == PaymentState.APPROVED.value:
                # generate temp receipts for approved payments
                current_app.logger.debug('adding temporary receipt details.')
                receipts = [{
                    'id': payment.payment_token,
                    'receiptAmount': None,
                    'receiptDate': None,
                    'receiptNumber': 'Pending'
                }]
                payment_response.receipts = receipts
                data.append({
                    'id': payment.id,
                    'nrId': payment.nrId,
                    'token': payment.payment_token,
                    'statusCode': payment.payment_status_code,
                    'action': payment.payment_action,
                    'completionDate': payment.payment_completion_date,
                    'payment': payment.as_dict(),
                    'sbcPayment': payment_response.as_dict(),
                    'receipts': receipts
                })
            else:
                # Wrap the response, providing info from both the SBC Pay response and the payment we created
                data.append({
                    'id':
                    payment.id,
                    'nrId':
                    payment.nrId,
                    'token':
                    payment.payment_token,
                    'statusCode':
                    payment.payment_status_code,
                    'action':
                    payment.payment_action,
                    'completionDate':
                    payment.payment_completion_date,
                    'payment':
                    payment.as_dict(),
                    'sbcPayment':
                    payment_response.as_dict(),
                    'receipts':
                    list(map(lambda r: map_receipt(r), receipts))
                })

            return jsonify(data), 200

        except PaymentServiceError as err:
            return handle_exception(err, err.message, 500)
        except SBCPaymentException as err:
            return handle_exception(err, err.message, err.status_code)
        except SBCPaymentError as err:
            return handle_exception(err, err.message, 500)
        except Exception as err:
            return handle_exception(err, err, 500)