Esempio n. 1
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=nr_model.id)), 400

            receipt_response = get_receipt(payment.payment_token)
            if receipt_response is None:
                return jsonify(message=MSG_NOT_FOUND
                               ), 404  # TODO: What if we have a record?

            response = make_response(receipt_response, 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)
Esempio n. 2
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)
Esempio n. 3
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()

                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)
Esempio n. 4
0
    def post(self, corp_num):
        try:
            authenticated, token = get_client_credentials(
                SBC_SVC_AUTH_URL, SBC_SVC_AUTH_CLIENT_ID,
                SBC_SVC_CLIENT_SECRET)
            if not authenticated:
                raise ColinServiceException(
                    message=MSG_CLIENT_CREDENTIALS_REQ_FAILED)

            # Get the profile
            print('\nCalling COLIN API using [corp_num: {corp_num}]'.format(
                corp_num=corp_num))
            colin_url = COLIN_SVC_URL.format(corp_num=corp_num)
            headers = {
                # 'x-api-key': COLIN_SVC_API_KEY,
                # 'Accept': 'application/xml'
                'Authorization': 'Bearer ' + token
            }

            print(colin_url)
            print(repr(headers))
            response = requests.get(colin_url, headers=headers)

            content = json.loads(response.text)
            if response.status_code != 200:
                return jsonify(content.get('message')), response.status_code
            return jsonify(content), response.status_code
        except ColinServiceException as err:
            return handle_exception(err, err.message, err.status_code)
        except Exception as err:
            return handle_exception(err, 'Internal Server Error', 500)
Esempio n. 5
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)
Esempio n. 6
0
    def patch(self, nr_id, action):
        """
        Roll back a Name Request to a usable state in case of a frontend error.
        :param nr_id:
        :param action:
        :return:
        """
        try:
            if not full_access_to_name_request(request):
                return {
                    "message": "You do not have access to this NameRequest."
                }, 403

            # 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

            # This could be moved out, but it's fine here for now
            def validate_patch_request(data):
                # TODO: Validate the data payload
                # Use the NR model state as the default, as the state change may not be included in the PATCH request
                is_valid = False
                msg = ''
                # This handles updates if the NR state is 'patchable'
                if NameRequestRollbackActions.has_value(action):
                    is_valid = True
                else:
                    msg = 'Invalid rollback action'

                return is_valid, msg

            is_valid_patch, validation_msg = validate_patch_request(
                self.request_data)
            validation_msg = validation_msg if not len(
                validation_msg) > 0 else 'Invalid request for PATCH'

            if not is_valid_patch:
                raise InvalidInputError(message=validation_msg)

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

            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)
Esempio n. 7
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)
Esempio n. 8
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)
Esempio n. 9
0
    def post(nr_num):
        try:
            # TODO: Validate NR string format
            # if not RequestDAO.validNRFormat(nr_num):
            #    return jsonify(message='NR number is not in a valid format \'NR 9999999\''), 400

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

            json_input = request.get_json()
            if not json_input:
                return jsonify(message=MSG_BAD_REQUEST_NO_JSON_BODY), 400
            elif isinstance(json_input, str):
                json_input = json.loads(json_input)

            # Grab the info we need off the request
            payment_info = json_input.get('paymentInfo')
            filing_info = json_input.get('filingInfo')
            business_info = json_input.get('businessInfo')

            # Create our payment request
            req = PaymentRequest(
                payment_info=payment_info,
                filing_info=filing_info,
                business_info=business_info
            )

            payment_response = create_payment(req)
            if not payment_response:
                raise PaymentServiceError(message=MSG_ERROR_CREATING_RESOURCE)

            if payment_response and payment_response.status_code == PaymentStatusCode.CREATED.value:
                # Save the payment info to Postgres
                payment = PaymentDAO()
                payment.nrId = nr_draft.id
                payment.payment_token = str(payment_response.id)
                payment.payment_completion_date = payment_response.created_on
                payment.payment_status_code = PaymentState.CREATED.value
                payment.save_to_db()

                data = jsonify(payment_response.to_dict())
                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, 500)
        except SBCPaymentError as err:
            return handle_exception(err, err.message, 500)
        except Exception as err:
            return handle_exception(err, err, 500)
Esempio n. 10
0
    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)
Esempio n. 11
0
    def post(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=nr_model.id)), 400

            receipt_info = get_receipt(payment.payment_token)
            name_choice = RequestDAO.find_name_by_choice(nr_model.id, 1)
            if not name_choice:
                return jsonify(
                    message='Could not find name choice for {nr_id}'.format(
                        nr_id=nr_model.id)), 400

            tz_aware_payment_completion_date = payment.payment_completion_date.replace(
                tzinfo=timezone('UTC'))
            localized_payment_completion_date = tz_aware_payment_completion_date.astimezone(
                timezone('US/Pacific'))
            receipt_req = ReceiptRequest(
                corpName=name_choice.name,
                filingDateTime=localized_payment_completion_date.strftime(
                    '%B %-d, %Y at %-I:%M %P Pacific time'))

            receipt_response = generate_receipt(payment.payment_token,
                                                receipt_req)

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

            return send_file(
                receipt_response,
                as_attachment=True,
                attachment_filename='payment-receipt-{id}.pdf'.format(
                    id=receipt_info.get('receiptNumber')))

        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)
Esempio n. 12
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)
Esempio n. 13
0
    def put(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 = clean_url_path_param(payment_id)

            json_input = request.get_json()
            if not json_input:
                return jsonify(message=MSG_BAD_REQUEST_NO_JSON_BODY), 400

            # Grab the info we need off the request
            payment_info = json_input.get('paymentInfo')
            filing_info = json_input.get('filingInfo')
            business_info = json_input.get('businessInfo')

            # Update our payment request
            req = PaymentRequest(payment_info=payment_info,
                                 filing_info=filing_info,
                                 business_info=business_info)

            payment_response = update_payment(payment_id, req)
            if not payment_response:
                raise PaymentServiceError(message=MSG_ERROR_CREATING_RESOURCE)

            data = jsonify(payment_response.to_dict())
            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)
Esempio n. 14
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)
Esempio n. 15
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)
Esempio n. 16
0
    def get(payment_identifier):
        try:
            payment_identifier = clean_url_path_param(payment_identifier)

            invoices = get_invoices(payment_identifier)

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

            data = jsonify(invoices.to_dict())
            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, 500)
        except SBCPaymentError as err:
            return handle_exception(err, err.message, 500)
        except Exception as err:
            return handle_exception(err, err, 500)
Esempio n. 17
0
    def post():
        try:
            json_input = request.get_json()
            if not json_input:
                return jsonify(message=MSG_BAD_REQUEST_NO_JSON_BODY), 400

            corp_type = json_input.get(
                'corp_type', 'NRO'
            )  # TODO: Maybe use a constant for this, it's the default corp_type, and I am not aware of a situation where it would be changed...
            filing_type_code = json_input.get(
                'filing_type_code'
            )  # TODO: Maybe throw an error if these don't exist, we can't really get fees without them
            jurisdiction = json_input.get(
                'jurisdiction', None
            )  # TODO: Maybe throw an error if these don't exist, we can't really get fees without them
            date = json_input.get('date', None)
            priority = json_input.get('priority', None)
            headers = json_input.get('headers', None)

            # Params are snake_case for this POST
            req = CalculateFeesRequest(corp_type=corp_type,
                                       filing_type_code=filing_type_code,
                                       jurisdiction=jurisdiction,
                                       date=date,
                                       priority=priority,
                                       headers=headers)

            fees = calculate_fees(req)
            data = jsonify(fees)
            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)
Esempio n. 18
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)
Esempio n. 19
0
    def post(payment_identifier):
        try:
            payment_identifier = clean_url_path_param(payment_identifier)

            json_input = request.get_json()
            if not json_input:
                return jsonify(message=MSG_BAD_REQUEST_NO_JSON_BODY), 400

            corp_name = json_input.get('corpName', None)
            business_number = json_input.get('businessNumber', None)
            recognition_date_time = json_input.get('recognitionDateTime', None)
            filing_identifier = json_input.get('filingIdentifier', None)
            filing_date_time = json_input.get('filingDateTime', None)
            file_name = json_input.get('fileName', None)

            req = PaymentReceiptInput(
                corp_name=corp_name,
                business_number=business_number,
                recognition_date_time=recognition_date_time,
                filing_identifier=filing_identifier,
                filing_date_time=filing_date_time,
                file_name=file_name
            )

            receipt = get_receipt(payment_identifier, req)

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

            return send_file(receipt, 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, 500)
        except SBCPaymentError as err:
            return handle_exception(err, err.message, 500)
        except Exception as err:
            return handle_exception(err, err, 500)
Esempio n. 20
0
    def get(payment_identifier, invoice_id):
        try:
            payment_identifier = clean_url_path_param(payment_identifier)
            invoice_id = invoice_id if invoice_id else None

            invoice = get_invoice(payment_identifier, invoice_id)

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

            data = jsonify(invoice.to_dict())
            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)
Esempio n. 21
0
    def post():
        try:
            json_input = request.get_json()
            if not json_input:
                return jsonify(message=MSG_BAD_REQUEST_NO_JSON_BODY), 400
            
            corp_type = json_input.get('corp_type')
            filing_type_code = json_input.get('filing_type_code')
            jurisdiction = json_input.get('jurisdiction', None)
            date = json_input.get('date', None)
            priority = json_input.get('priority', None)

            # Params are snake_case for this POST
            # Response data is also snake_case
            req = CalculateFeesRequest(
                corp_type=corp_type,
                filing_type_code=filing_type_code,
                jurisdiction=jurisdiction,
                date=date,
                priority=priority
            )

            fees = calculate_fees(req)
            if not fees:
                raise SBCPaymentError(message=MSG_ERROR_CREATING_RESOURCE)

            data = jsonify(fees.to_dict())
            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, 500)
        except SBCPaymentError as err:
            return handle_exception(err, err.message, 500)
        except Exception as err:
            return handle_exception(err, err, 500)
Esempio n. 22
0
    def put(payment_identifier):
        try:
            payment_identifier = clean_url_path_param(payment_identifier)

            json_input = request.get_json()
            if not json_input:
                return jsonify(message=MSG_BAD_REQUEST_NO_JSON_BODY), 400

            # Grab the info we need off the request
            payment_info = json_input.get('paymentInfo')
            filing_info = json_input.get('filingInfo')
            business_info = json_input.get('businessInfo')

            # Update our payment request
            req = PaymentRequest(
                payment_info=payment_info,
                filing_info=filing_info,
                business_info=business_info
            )

            payment_response = update_payment(payment_identifier, req)
            if not payment_response:
                raise PaymentServiceError(message=MSG_ERROR_CREATING_RESOURCE)

            data = jsonify(payment_response.to_dict())
            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, 500)
        except SBCPaymentError as err:
            return handle_exception(err, err.message, 500)
        except Exception as err:
            return handle_exception(err, err, 500)
Esempio n. 23
0
    def get(self, nr_id):
        try:
            if not full_access_to_name_request(request):
                return {
                    "message": "You do not have access to this NameRequest."
                }, 403

            nr_model = Request.query.get(nr_id)
            if not nr_model:
                return jsonify(message='{nr_id} not found'.format(
                    nr_id=nr_model.id)), HTTPStatus.NOT_FOUND

            if nr_model.stateCd not in [
                    State.APPROVED, State.CONDITIONAL, State.CONSUMED,
                    State.EXPIRED, State.REJECTED
            ]:
                return jsonify(message='Invalid NR state'.format(
                    nr_id=nr_model.id)), HTTPStatus.BAD_REQUEST

            authenticated, token = ReportResource._get_service_client_token()
            if not authenticated:
                return jsonify(message='Error in authentication'.format(nr_id=nr_model.id)),\
                       HTTPStatus.INTERNAL_SERVER_ERROR

            headers = {
                'Authorization': 'Bearer {}'.format(token),
                'Content-Type': 'application/json'
            }
            data = {
                'reportName':
                ReportResource._get_report_filename(nr_model),
                'template':
                "'" + base64.b64encode(bytes(self._get_template(),
                                             'utf-8')).decode() + "'",
                'templateVars':
                ReportResource._get_template_data(nr_model)
            }
            response = requests.post(
                url=current_app.config.get('REPORT_SVC_URL'),
                headers=headers,
                data=json.dumps(data))

            if response.status_code != HTTPStatus.OK:
                return jsonify(
                    message=str(response.content)), response.status_code
            return response.content, response.status_code
        except Exception as err:
            return handle_exception(err, 'Error retrieving the report.', 500)
    def get():
        try:
            service = WaitTimeStatsService()
            response = service.get_statistics()

            if not response:
                raise ApiServiceException(
                    message='WaitTimeStatsService did not return a result')

            return jsonify(response), HTTPStatus.OK

        except ValueError as err:
            return jsonify('Wait time stats not found: ' + repr(err)), 200
        except ApiServiceException as err:
            return handle_exception(err, err.message, 400)
        except Exception as err:
            return jsonify('Internal Server Error\n' + repr(err)), 500
Esempio n. 25
0
    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)
Esempio n. 26
0
    def get(self, province, corp_num):
        try:
            # Get the jurisdiction
            print(
                'Calling MRAS Jurisdictions API using [corp_num: {corp_num}]'.
                format(corp_num=corp_num))
            mras_url = MRAS_SVC_PROFILE_JUR_URL.format(profile_id=corp_num)
            headers = {
                'x-api-key': MRAS_SVC_API_KEY,
                'Accept': 'application/xml'
            }

            print(mras_url)
            print(repr(headers))
            response = requests.get(mras_url, headers=headers)

            if not response.status_code == 200:
                mras_errors = load_xml_response_content(
                    response, './/mras_error')
                mras_error = {
                    'error_code':
                    mras_errors[0].find('error_code').text,
                    'internal_error_code':
                    mras_errors[0].find('internal_error_code').text,
                    'internal_error_message':
                    mras_errors[0].find('internal_error_message').text
                }

                raise MrasServiceException(
                    mras_error=mras_error,
                    message='Error retrieving MRAS profile jurisdictions')

            jurisdiction_id_els = load_xml_response_content(
                response, './/mras:JurisdictionID')
            jurisdiction_ids = [j.text for j in jurisdiction_id_els
                                ]  # All we care about are the codes / IDs

            if province not in jurisdiction_ids:
                return jsonify(
                    message='Invalid request, province jurisdiction is incorrect'
                ), HTTPStatus.BAD_REQUEST
            else:
                print('Valid jurisdiction IDs')
                print(repr(jurisdiction_ids))

            # Get the profile
            print(
                '\nCalling MRAS Profile API using [corp_num: {corp_num}], [province: {province}]'
                .format(corp_num=corp_num, province=province))
            mras_url = MRAS_SVC_PROFILE_URL.format(
                profile_id=corp_num, source_jurisdiction_id=province)
            # headers = {
            #     'x-api-key': MRAS_SVC_API_KEY,
            #     'Accept': 'application/xml'
            # }
            headers = {
                'x-api-key': MRAS_SVC_API_KEY,
                'Accept': 'application/json'
            }

            print(mras_url)
            print(repr(headers))
            response = requests.get(mras_url, headers=headers)

            # Return the auth response if an error occurs
            if not response.status_code == HTTPStatus.OK:
                return jsonify({
                    'error':
                    'No profile found for the jurisdiction, registration number pair.'
                }), HTTPStatus.NOT_FOUND
                # mras_errors = load_xml_response_content(response, './/mras_error')
                # mras_error = {
                #     'error_code': mras_errors[0].find('error_code').text,
                #     'internal_error_code': mras_errors[0].find('internal_error_code').text,
                #     'internal_error_message': mras_errors[0].find('internal_error_message').text
                # }

                # raise MrasServiceException(mras_error=mras_error)

            # Just return true or false, the profile either exists or it doesn't
            return jsonify(response.json()), HTTPStatus.OK
        except MrasServiceException as err:
            return handle_exception(err, err.message, err.error_code)
        except Exception as err:
            return handle_exception(err, 'Internal Server Error',
                                    HTTPStatus.INTERNAL_SERVER_ERROR)
Esempio n. 27
0
    def post(self, nr_id, payment_action=NameRequestActions.COMPLETE.value):
        """
        At this point, the Name Request will still be using a TEMPORARY NR number.
        Confirming the payment on the frontend triggers this endpoint. Here, we:
        - Save the request to NRO which gives us a real NR.
        - Create the payment via SBC Pay.
        - If payment creation is successful, create a corresponding payment record in our system.
        :param nr_id:
        :param payment_action:
        :return:
        """
        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='Name Request {nr_id} not found'.format(
                    nr_id=nr_id)), 400

            if not payment_action:
                return jsonify(
                    message='Invalid payment action, {action} not found'.
                    format(action=payment_action)), 400

            valid_payment_action = payment_action in [
                NameRequestActions.COMPLETE.value,
                NameRequestActions.UPGRADE.value,
                NameRequestActions.REAPPLY.value
            ]

            if not valid_payment_action:
                return jsonify(
                    message='Invalid payment action [{action}]'.format(
                        action=payment_action)), 400

            # We only handle payments if the NR is in the following states
            valid_payment_states = [
                State.DRAFT, State.COND_RESERVE, State.RESERVED,
                State.CONDITIONAL, State.APPROVED
            ]
            valid_nr_state = nr_model.stateCd in valid_payment_states
            if not valid_nr_state:
                return jsonify(message='Invalid NR state'.format(
                    action=payment_action)), 400

            if valid_payment_action and valid_nr_state:
                if payment_action in [NameRequestActions.COMPLETE.value]:
                    # Save the record to NRO, which swaps the NR-L Number for a real NR
                    update_solr = True
                    nr_model = self.add_records_to_network_services(
                        nr_model, update_solr)

            json_input = request.get_json()
            payment_request = {}
            if not json_input:
                # return jsonify(message=MSG_BAD_REQUEST_NO_JSON_BODY), 400
                # Grab the data from the NR, if it exists
                payment_request = build_payment_request(nr_model)
            elif isinstance(json_input, dict):
                payment_request = merge_payment_request(nr_model, json_input)
            elif isinstance(json_input, str):
                payment_request = merge_payment_request(
                    nr_model, json.loads(json_input))

            # Grab the info we need off the request
            payment_info = payment_request.get('paymentInfo')
            filing_info = payment_request.get('filingInfo')
            business_info = payment_request.get('businessInfo')

            # Create our payment request
            req = PaymentRequest(payment_info=payment_info,
                                 filing_info=filing_info,
                                 business_info=business_info)

            payment_response = create_payment(req)

            if not payment_response:
                raise PaymentServiceError(message=MSG_ERROR_CREATING_RESOURCE)

            if payment_response and payment_response.status_code == PaymentStatusCode.CREATED.value:
                # Save the payment info to Postgres
                payment = PaymentDAO()
                payment.nrId = nr_model.id
                payment.payment_token = str(payment_response.id)
                payment.payment_completion_date = payment_response.created_on
                payment.payment_status_code = PaymentState.CREATED.value
                payment.save_to_db()

                # 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.to_dict()
                })

                # Record the event
                nr_svc = self.nr_service
                # EventRecorder.record(nr_svc.user, Event.PATCH + ' [payment ID: {id}]'.format(id=payment.id), nr_model, data)

                response = make_response(data, 201)
                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)
Esempio n. 28
0
    def get_waiting_time_dict(cls):
        try:
            if not (oldest_draft := Request.get_oldest_draft()):
                oldest_draft_date = datetime.now().astimezone()
            else:
                oldest_draft_date = oldest_draft.submittedDate

            # add one to waiting time to account for current day
            delta = datetime.now().astimezone(
            ) - oldest_draft_date + timedelta(days=1)
            response_data = {
                'oldest_draft': oldest_draft_date.isoformat(),
                'waiting_time': delta.days
            }
        except Exception as err:
            return handle_exception(err, repr(err), 500)

        return response_data

    @classmethod
    def get_statistics(cls):
        # For now not using this to improve performance
        # response_values = [cls.get_approved_names_counter(),
        #                    cls.get_waiting_time_priority_queue(unit=UnitTime.HR.value),
        #                    cls.get_waiting_time_regular_queue(unit=UnitTime.DAY.value)]

        oldest_draft = Request.get_oldest_draft()
        todays_date = get_utc_now().date()
        submitted_date = oldest_draft.submittedDate.date()

        # note that busday_count does not count the end date provided
Esempio n. 29
0
    def patch(self, nr_id, payment_id, payment_action):
        """
        :param nr_id:
        :param payment_id:
        :param payment_action:
        :return:
        """
        try:
            # Find the existing name request
            nr_model = RequestDAO.query.get(nr_id)

            # Creates a new NameRequestService, validates the app config, and sets request_data to the NameRequestService instance
            # Override the default self.initialize method
            def initialize(_self):
                # The request payload will be empty when making this call,
                # but we still want to process names, so we need to add
                # them to the request, otherwise they won't be processed!
                _self.request_data = {
                    'names': [n.as_dict() for n in nr_model.names.all()]
                }
                # Set the request data to the service
                _self.nr_service.request_data = self.request_data

            initialize(self)

            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
            ]

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

                return is_valid, msg

            is_valid_patch, validation_msg = validate_patch_request(nr_model)
            validation_msg = validation_msg if not len(
                validation_msg) > 0 else 'Invalid request for PATCH'

            if not is_valid_patch:
                raise PaymentServiceError(message=validation_msg)

            process_payment = has_active_payment(nr_model, payment_id)
            if nr_model.stateCd in valid_update_states and not process_payment:
                pass
            elif process_payment:
                # This handles updates if the NR state is 'patchable'
                nr_model = self.handle_payment_actions(payment_action,
                                                       nr_model, payment_id)

            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 PaymentServiceError as err:
            return handle_exception(err, err.message, 500)
        except Exception as err:
            return handle_exception(err, repr(err), 500)
Esempio n. 30
0
    def patch(self, nr_id, nr_action: str):
        """
        Update a specific set of fields and/or a provided action. Fields excluded from the payload will not be updated.
        The following data format is expected when providing a data payload:
        { 'stateCd': 'CANCELLED' }  # Fields to update

        We use this to:
        - Edit a subset of NR fields
        - Cancel an NR
        - Change the state of an NR
        :param nr_id:
        :param nr_action: One of [CHECKOUT, CHECKIN, EDIT, CANCEL, RESEND]
        :return:
        """
        try:
            if not full_access_to_name_request(request):
                return {
                    "message": "You do not have access to this NameRequest."
                }, 403

            nr_action = str(nr_action).upper(
            )  # Convert to upper-case, just so we can support lower case action strings
            nr_action = NameRequestPatchActions[nr_action].value \
                if NameRequestPatchActions.has_value(nr_action) \
                else NameRequestPatchActions.EDIT.value

            # Find the existing name request
            nr_model = Request.query.get(nr_id)

            def initialize(_self):
                _self.validate_config(current_app)
                request_json = request.get_json()

                if nr_action:
                    _self.nr_action = nr_action

                if nr_action is NameRequestPatchActions.CHECKOUT.value:
                    # Make sure the NR isn't already checked out
                    checked_out_by_different_user = nr_model.checkedOutBy is not None and nr_model.checkedOutBy != request_json.get(
                        'checkedOutBy', None)
                    if checked_out_by_different_user:
                        raise NameRequestIsInProgressError()

                    # set the user id of the request to name_request_service_account
                    service_account_user = User.find_by_username(
                        'name_request_service_account')
                    nr_model.userId = service_account_user.id

                    # The request payload will be empty when making this call, add them to the request
                    _self.request_data = {
                        # Doesn't have to be a UUID but this is easy and works for a pretty unique token
                        'checkedOutBy': str(uuid4()),
                        'checkedOutDt': datetime.now()
                    }
                    # Set the request data to the service
                    _self.nr_service.request_data = self.request_data
                elif nr_action is NameRequestPatchActions.CHECKIN.value:
                    # The request payload will be empty when making this call, add them to the request
                    _self.request_data = {
                        'checkedOutBy': None,
                        'checkedOutDt': None
                    }
                    # Set the request data to the service
                    _self.nr_service.request_data = self.request_data
                else:
                    super().initialize()

            initialize(self)

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

            # This could be moved out, but it's fine here for now
            def validate_patch_request(data):
                # Use the NR model state as the default, as the state change may not be included in the PATCH request
                request_state = data.get('stateCd', nr_model.stateCd)
                is_valid = False
                msg = ''

                # Handles updates if the NR state is 'patchable'
                if request_state in request_editable_states:
                    is_valid = True
                elif request_state in contact_editable_states:
                    is_valid = True
                else:
                    msg = 'Invalid state change requested - the Name Request state cannot be changed to [' + data.get(
                        'stateCd', '') + ']'

                # Check the action, make sure it's valid
                if not NameRequestPatchActions.has_value(nr_action):
                    is_valid = False
                    msg = 'Invalid Name Request PATCH action, please use one of [' + ', '.join(
                        [action.value
                         for action in NameRequestPatchActions]) + ']'
                return is_valid, msg

            is_valid_patch, validation_msg = validate_patch_request(
                self.request_data)
            validation_msg = validation_msg if not len(
                validation_msg) > 0 else 'Invalid request for PATCH'

            if not is_valid_patch:
                raise InvalidInputError(message=validation_msg)

            def handle_patch_actions(action, model):
                return {
                    NameRequestPatchActions.CHECKOUT.value:
                    self.handle_patch_checkout,
                    NameRequestPatchActions.CHECKIN.value:
                    self.handle_patch_checkin,
                    NameRequestPatchActions.EDIT.value:
                    self.handle_patch_edit,
                    NameRequestPatchActions.CANCEL.value:
                    self.handle_patch_cancel,
                    NameRequestPatchActions.RESEND.value:
                    self.handle_patch_resend,
                    NameRequestPatchActions.REQUEST_REFUND.value:
                    self.handle_patch_request_refund
                }.get(action)(model)

            # This handles updates if the NR state is 'patchable'
            nr_model = handle_patch_actions(nr_action, nr_model)

            current_app.logger.debug(nr_model.json())
            response_data = nr_model.json()

            # Don't return the whole response object if we're checking in or checking out
            if nr_action == NameRequestPatchActions.CHECKOUT.value:
                response_data = {
                    'id': nr_id,
                    'checkedOutBy': response_data.get('checkedOutBy'),
                    'checkedOutDt': response_data.get('checkedOutDt'),
                    'state': response_data.get('state', ''),
                    'stateCd': response_data.get('stateCd', ''),
                    'actions': nr_svc.current_state_actions
                }
                return jsonify(response_data), 200

            if nr_action == NameRequestPatchActions.CHECKIN.value:
                response_data = {
                    'id': nr_id,
                    'state': response_data.get('state', ''),
                    'stateCd': response_data.get('stateCd', ''),
                    'actions': nr_svc.current_state_actions
                }
                return jsonify(response_data), 200

            # Add the list of valid Name Request actions for the given state to the response
            if (nr_action == NameRequestPatchActions.REQUEST_REFUND.value):
                response_data['actions'] = []
            else:
                response_data['actions'] = nr_svc.current_state_actions
            return jsonify(response_data), 200

        except NameRequestIsInProgressError as err:
            # Might as well use the Mozilla WebDAV HTTP Locked status, it's pretty close
            return handle_exception(err, err.message, 423)
        except NameRequestException as err:
            return handle_exception(err, err.message, 500)
        except Exception as err:
            return handle_exception(err, repr(err), 500)