def find_by_corp_type_and_filing_type( # pylint: disable=too-many-arguments cls, corp_type: str, filing_type_code: str, valid_date: date, jurisdiction: str, priority: bool, ): """Calculate fees for the filing by using the arguments.""" current_app.logger.debug('<get_fees_by_corp_type_and_filing_type') if not corp_type and not filing_type_code: raise BusinessException(Error.PAY001) if jurisdiction or priority: current_app.logger.warn( 'Not using Jurisdiction and priority now!!!') fee_schedule_dao = FeeScheduleModel.find_by_filing_type_and_corp_type( corp_type, filing_type_code, valid_date) if not fee_schedule_dao: raise BusinessException(Error.PAY002) fee_schedule = FeeSchedule() fee_schedule._dao = fee_schedule_dao # pylint: disable=protected-access current_app.logger.debug('>get_fees_by_corp_type_and_filing_type') return fee_schedule
def delete_account(cls, auth_account_id: str) -> PaymentAccount: """Delete the payment account.""" current_app.logger.debug('<delete_account') pay_account: PaymentAccountModel = PaymentAccountModel.find_by_auth_account_id( auth_account_id) cfs_account: CfsAccountModel = CfsAccountModel.find_effective_by_account_id( pay_account.id) # 1 - Check if account have any credits # 2 - Check if account have any PAD transactions done in last N (10) days. if pay_account.credit and pay_account.credit > 0: raise BusinessException(Error.OUTSTANDING_CREDIT) # Check if account is frozen. cfs_status: str = cfs_account.status if cfs_account else None if cfs_status == CfsAccountStatus.FREEZE.value: raise BusinessException(Error.FROZEN_ACCOUNT) if InvoiceModel.find_outstanding_invoices_for_account( pay_account.id, get_outstanding_txns_from_date()): # Check if there is any recent PAD transactions in N days. raise BusinessException(Error.TRANSACTIONS_IN_PROGRESS) # If CFS Account present, mark it as INACTIVE. if cfs_status and cfs_status != CfsAccountStatus.INACTIVE.value: cfs_account.status = CfsAccountStatus.INACTIVE.value # If account is active or pending pad activation stop PAD payments. if pay_account.payment_method == PaymentMethod.PAD.value \ and cfs_status in [CfsAccountStatus.ACTIVE.value, CfsAccountStatus.PENDING_PAD_ACTIVATION.value]: CFSService.suspend_cfs_account(cfs_account) cfs_account.save() if pay_account.statement_notification_enabled: pay_account.statement_notification_enabled = False pay_account.save()
def create(**kwargs): """Create a subclass of PaymentSystemService based on input params.""" current_app.logger.debug('<create') user: UserContext = kwargs['user'] total_fees: int = kwargs.get('fees', None) payment_method = kwargs.get('payment_method', 'CC') corp_type = kwargs.get('corp_type', None) _instance: PaymentSystemService = None current_app.logger.debug('payment_method: {}, corp_type : {}'.format( payment_method, corp_type)) if not payment_method and not corp_type: raise BusinessException(Error.PAY003) if total_fees == 0 or (Role.STAFF.value in user.roles): _instance = InternalPayService() else: if payment_method == 'CC': _instance = PaybcService() elif payment_method == 'PREMIUM': _instance = BcolService() if not _instance: raise BusinessException(Error.PAY003) return _instance
def find_by_corp_type_and_filing_type( # pylint: disable=too-many-arguments cls, corp_type: str, filing_type_code: str, valid_date: date, **kwargs): """Calculate fees for the filing by using the arguments.""" current_app.logger.debug('<get_fees_by_corp_type_and_filing_type') if not corp_type and not filing_type_code: raise BusinessException(Error.PAY001) if kwargs.get('jurisdiction'): current_app.logger.warn('Not using Jurisdiction now!!!') fee_schedule_dao = FeeScheduleModel.find_by_filing_type_and_corp_type( corp_type, filing_type_code, valid_date) if not fee_schedule_dao: raise BusinessException(Error.PAY002) fee_schedule = FeeSchedule() fee_schedule._dao = fee_schedule_dao # pylint: disable=protected-access if kwargs.get('is_priority') and fee_schedule_dao.priority_fee: fee_schedule.priority_fee = fee_schedule_dao.priority_fee.amount if kwargs.get('is_future_effective' ) and fee_schedule_dao.future_effective_fee: fee_schedule.future_effective_fee = fee_schedule_dao.future_effective_fee.amount if kwargs.get('waive_fees'): fee_schedule.fee_amount = 0 current_app.logger.debug('>get_fees_by_corp_type_and_filing_type') return fee_schedule
def create(**kwargs): """Create a subclass of PaymentSystemService based on input params.""" current_app.logger.debug('<create') user: UserContext = kwargs['user'] total_fees: int = kwargs.get('fees', None) payment_method = kwargs.get('payment_method', 'CC') account_info = kwargs.get('account_info', None) _instance: PaymentSystemService = None current_app.logger.debug('payment_method: {}'.format(payment_method)) if not payment_method: raise BusinessException(Error.INVALID_CORP_OR_FILING_TYPE) if total_fees == 0: _instance = InternalPayService() elif Role.STAFF.value in user.roles: if account_info is not None and account_info.get( 'bcolAccountNumber') is not None: _instance = BcolService() else: _instance = InternalPayService() else: if payment_method == 'CC': _instance = PaybcService() elif payment_method == 'DRAWDOWN': _instance = BcolService() if not _instance: raise BusinessException(Error.INVALID_CORP_OR_FILING_TYPE) return _instance
def _check_if_invoice_can_be_deleted(invoice: Invoice, payment: Payment = None): if invoice.invoice_status_code in (InvoiceStatus.PAID.value, InvoiceStatus.DELETED.value, InvoiceStatus.APPROVED.value): raise BusinessException(Error.COMPLETED_PAYMENT) if payment and payment.payment_status_code in ( PaymentStatus.COMPLETED.value, PaymentStatus.DELETED.value): raise BusinessException(Error.COMPLETED_PAYMENT)
def find_by_corp_type_and_filing_type( # pylint: disable=too-many-arguments cls, corp_type: str, filing_type_code: str, valid_date: date, **kwargs): """Calculate fees for the filing by using the arguments.""" current_app.logger.debug( f'<get_fees_by_corp_type_and_filing_type : {corp_type}, {filing_type_code}, ' f'{valid_date}') user: UserContext = kwargs['user'] if not corp_type and not filing_type_code: raise BusinessException(Error.INVALID_CORP_OR_FILING_TYPE) fee_schedule_dao = FeeScheduleModel.find_by_filing_type_and_corp_type( corp_type, filing_type_code, valid_date) if not fee_schedule_dao: raise BusinessException(Error.INVALID_CORP_OR_FILING_TYPE) fee_schedule = FeeSchedule() fee_schedule._dao = fee_schedule_dao # pylint: disable=protected-access fee_schedule.quantity = kwargs.get('quantity') # Find fee overrides for account. account_fee = AccountFeeModel.find_by_auth_account_id_and_corp_type( user.account_id, corp_type) apply_filing_fees: bool = account_fee.apply_filing_fees if account_fee else True if not apply_filing_fees: fee_schedule.fee_amount = 0 fee_schedule.waived_fee_amount = 0 # Set transaction fees fee_schedule.service_fees = FeeSchedule.calculate_service_fees( fee_schedule_dao, account_fee) # Special case for CSO partner type which is different from normal flow if fee_schedule.corp_type_code == 'CSO' and fee_schedule.quantity: fee_schedule.service_fees = fee_schedule.service_fees * fee_schedule.quantity if kwargs.get( 'is_priority' ) and fee_schedule_dao.priority_fee and apply_filing_fees: fee_schedule.priority_fee = fee_schedule_dao.priority_fee.amount if kwargs.get( 'is_future_effective' ) and fee_schedule_dao.future_effective_fee and apply_filing_fees: fee_schedule.future_effective_fee = fee_schedule_dao.future_effective_fee.amount if kwargs.get('waive_fees'): fee_schedule.fee_amount = 0 fee_schedule.priority_fee = 0 fee_schedule.future_effective_fee = 0 fee_schedule.service_fees = 0 current_app.logger.debug('>get_fees_by_corp_type_and_filing_type') return fee_schedule
def create_from_payment_method(payment_method: str): """Create the payment system implementation from payment method.""" _instance: PaymentSystemService = None if payment_method == PaymentMethod.DIRECT_PAY.value: _instance = DirectPayService() elif payment_method == PaymentMethod.CC.value: _instance = PaybcService() elif payment_method == PaymentMethod.DRAWDOWN.value: _instance = BcolService() elif payment_method == PaymentMethod.INTERNAL.value: _instance = InternalPayService() elif payment_method == PaymentMethod.ONLINE_BANKING.value: _instance = OnlineBankingService() elif payment_method == PaymentMethod.PAD.value: _instance = PadService() elif payment_method == PaymentMethod.EFT.value: _instance = EftService() elif payment_method == PaymentMethod.WIRE.value: _instance = WireService() elif payment_method == PaymentMethod.EJV.value: _instance = EjvPayService() if not _instance: raise BusinessException(Error.INVALID_CORP_OR_FILING_TYPE) return _instance
def create(invoice_id: int, fee: FeeSchedule, **kwargs): """Create Payment Line Item record.""" current_app.logger.debug('<create') user: UserContext = kwargs['user'] p = PaymentLineItem() p.invoice_id = invoice_id p.total = fee.total p.fee_schedule_id = fee.fee_schedule_id p.description = fee.description p.filing_fees = fee.fee_amount p.gst = fee.gst p.priority_fees = fee.priority_fee p.pst = fee.pst p.future_effective_fees = fee.future_effective_fee p.quantity = fee.quantity p.line_item_status_code = Status.CREATED.value if fee.waived_fee_amount > 0: if user.has_role(Role.STAFF.value): p.waived_fees = fee.waived_fee_amount p.waived_by = user.user_name else: raise BusinessException(Error.PAY003) p_dao = p.flush() p = PaymentLineItem() p._dao = p_dao # pylint: disable=protected-access current_app.logger.debug('>create') return p
def create_refund(cls, invoice_id: int, request: Dict[str, str], **kwargs) -> Dict[str, str]: """Create refund.""" current_app.logger.debug(f'Starting refund : {invoice_id}') # Do validation by looking up the invoice invoice: InvoiceModel = InvoiceModel.find_by_id(invoice_id) paid_statuses = (InvoiceStatus.PAID.value, InvoiceStatus.APPROVED.value, InvoiceStatus.UPDATE_REVENUE_ACCOUNT.value) if invoice.invoice_status_code not in paid_statuses: current_app.logger.info( f'Cannot process refund as status of {invoice_id} is {invoice.invoice_status_code}' ) raise BusinessException(Error.INVALID_REQUEST) refund: RefundService = RefundService() refund.invoice_id = invoice_id refund.reason = get_str_by_path(request, 'reason') refund.requested_by = kwargs['user'].user_name refund.requested_date = datetime.now() refund.flush() pay_system_service: PaymentSystemService = PaymentSystemFactory.create_from_payment_method( payment_method=invoice.payment_method_code) invoice_status = pay_system_service.process_cfs_refund(invoice) message = REFUND_SUCCESS_MESSAGES.get( f'{invoice.payment_method_code}.{invoice.invoice_status_code}') # set invoice status invoice.invoice_status_code = invoice_status or InvoiceStatus.REFUND_REQUESTED.value invoice.refund = invoice.total # no partial refund invoice.save() current_app.logger.debug(f'Completed refund : {invoice_id}') return {'message': message}
def _validate_redirect_url_and_throw_error(payment_method: str, return_url: str): """Check and Throw if the return_url is not a valid url.""" is_validity_check_needed = payment_method in ( PaymentMethod.CC.value, PaymentMethod.DIRECT_PAY.value) if is_validity_check_needed and not is_valid_redirect_url(return_url): raise BusinessException(Error.INVALID_REDIRECT_URI)
def create_refund(cls, invoice_id: int, request: Dict[str, str], **kwargs) -> None: """Create refund.""" current_app.logger.debug('<create refund') # Do validation by looking up the invoice invoice: InvoiceModel = InvoiceModel.find_by_id(invoice_id) # Allow refund only for direct pay payments, and only if the status of invoice is PAID/UPDATE_REVENUE_ACCOUNT paid_statuses = (InvoiceStatus.PAID.value, InvoiceStatus.APPROVED.value, InvoiceStatus.UPDATE_REVENUE_ACCOUNT.value) if invoice.invoice_status_code not in paid_statuses: raise BusinessException(Error.INVALID_REQUEST) refund: RefundService = RefundService() refund.invoice_id = invoice_id refund.reason = get_str_by_path(request, 'reason') refund.requested_by = kwargs['user'].user_name refund.requested_date = datetime.now() refund.flush() cls._process_cfs_refund(invoice) # set invoice status invoice.invoice_status_code = InvoiceStatus.REFUND_REQUESTED.value invoice.refund = invoice.total # no partial refund invoice.save()
def create_receipt(payment_identifier: str, invoice_identifier: str, filing_data: Dict[str, Any], skip_auth_check: bool = False, **kwargs): """Create receipt.""" current_app.logger.debug('<create receipt initiated') receipt_dict = { 'templateName': 'payment_receipt', 'reportName': filing_data.pop('fileName', 'payment_receipt') } template_vars = {} template_vars.update(filing_data) # invoice number not mandatory ;since only one invoice exist for a payment now if not invoice_identifier: invoice_data = Invoice.find_by_payment_identifier(payment_identifier, skip_auth_check=skip_auth_check) else: invoice_data = Invoice.find_by_id(invoice_identifier, payment_identifier, skip_auth_check=skip_auth_check) payment_account = PaymentAccount.find_by_pay_system_id( credit_account_id=invoice_data.credit_account_id, internal_account_id=invoice_data.internal_account_id, bcol_account_id=invoice_data.bcol_account_id) invoice_reference = InvoiceReference.find_completed_reference_by_invoice_id(invoice_data.id) # template_vars['incorporationNumber'] = payment_account.corp_number template_vars['invoiceNumber'] = invoice_reference.invoice_number if payment_account.payment_system_code == PaymentSystem.INTERNAL.value and invoice_data.routing_slip: template_vars['routingSlipNumber'] = invoice_data.routing_slip if not invoice_data.receipts: raise BusinessException(Error.INVALID_REQUEST) template_vars['receiptNo'] = invoice_data.receipts[0].receipt_number template_vars['filingIdentifier'] = filing_data.get('filingIdentifier', invoice_data.filing_id) if invoice_data.bcol_account_id: bcol_account: BcolPaymentAccountModel = BcolPaymentAccountModel.find_by_id(invoice_data.bcol_account_id) template_vars['bcOnlineAccountNumber'] = bcol_account.bcol_account_id payment_method = PaymentModel.find_payment_method_by_payment_id(payment_identifier) # TODO fix properly later if not invoice_data.internal_account_id: template_vars['paymentMethod'] = payment_method.description template_vars['invoice'] = camelcase_dict(invoice_data.asdict(), {}) receipt_dict['templateVars'] = template_vars current_app.logger.debug( '<OAuthService invoked from receipt.py {}'.format(current_app.config.get('REPORT_API_BASE_URL'))) pdf_response = OAuthService.post(current_app.config.get('REPORT_API_BASE_URL'), kwargs['user'].bearer_token, AuthHeaderType.BEARER, ContentType.JSON, receipt_dict) current_app.logger.debug('<OAuthService responded to receipt.py') return pdf_response
def get_receipt_details(filing_data, invoice_identifier, skip_auth_check): """Return receipt details.""" receipt_details: dict = {} # invoice number mandatory invoice_data = Invoice.find_by_id(invoice_identifier, skip_auth_check=skip_auth_check) is_pending_pad_invoice = invoice_data.payment_method_code == PaymentMethod.PAD.value and \ invoice_data.invoice_status_code != InvoiceStatus.PAID.value if not is_pending_pad_invoice and not invoice_data.receipts: raise BusinessException(Error.INVALID_REQUEST) invoice_reference = InvoiceReference.find_completed_reference_by_invoice_id( invoice_data.id) receipt_details['invoiceNumber'] = invoice_reference.invoice_number if invoice_data.payment_method_code == PaymentSystem.INTERNAL.value and invoice_data.routing_slip: receipt_details['routingSlipNumber'] = invoice_data.routing_slip receipt_details[ 'receiptNumber'] = None if is_pending_pad_invoice else invoice_data.receipts[ 0].receipt_number receipt_details['filingIdentifier'] = filing_data.get( 'filingIdentifier', invoice_data.filing_id) receipt_details['bcOnlineAccountNumber'] = invoice_data.bcol_account payment_method = PaymentMethodModel.find_by_code( invoice_data.payment_method_code) receipt_details['paymentMethod'] = payment_method.code if invoice_data.payment_method_code != PaymentSystem.INTERNAL.value: receipt_details[ 'paymentMethodDescription'] = payment_method.description receipt_details['invoice'] = camelcase_dict(invoice_data.asdict(), {}) return receipt_details
def create(payment_identifier: str, request_json: Dict): """Create transaction record.""" current_app.logger.debug('<create transaction') # Lookup payment record payment: Payment = Payment.find_by_id(payment_identifier, skip_auth_check=True) # Check if return url is valid return_url = request_json.get('clientSystemUrl') if payment.payment_system_code == PaymentSystem.PAYBC.value and not is_valid_redirect_url( return_url): raise BusinessException(Error.PAY013) if not payment.id: raise BusinessException(Error.PAY005) # Cannot start transaction on completed payment if payment.payment_status_code in (Status.COMPLETED.value, Status.DELETED.value, Status.DELETE_ACCEPTED.value): raise BusinessException(Error.PAY006) # If there are active transactions (status=CREATED), then invalidate all of them and create a new one. existing_transactions = PaymentTransactionModel.find_by_payment_id( payment.id) if existing_transactions: for existing_transaction in existing_transactions: if existing_transaction.status_code != Status.CANCELLED.value: existing_transaction.status_code = Status.CANCELLED.value existing_transaction.transaction_end_time = datetime.now() existing_transaction.save() transaction = PaymentTransaction() transaction.payment_id = payment.id transaction.client_system_url = return_url transaction.status_code = Status.CREATED.value transaction_dao = transaction.flush() transaction._dao = transaction_dao # pylint: disable=protected-access transaction.pay_system_url = transaction.build_pay_system_url( payment, transaction.id, request_json.get('payReturnUrl')) transaction_dao = transaction.save() transaction = PaymentTransaction() transaction._dao = transaction_dao # pylint: disable=protected-access current_app.logger.debug('>create transaction') return transaction
def create_routing_slip_refund(cls, routing_slip_number: str, request: Dict[str, str], **kwargs) -> Dict[str, str]: """Create Routing slip refund.""" current_app.logger.debug('<create Routing slip refund') # # check if routing slip exists # validate user role -> update status of routing slip # check refunds table # if Yes ; update the data [only with whatever is in payload] # if not ; create new entry # call cfs rs_model = RoutingSlipModel.find_by_number(routing_slip_number) if not rs_model: raise BusinessException(Error.RS_DOESNT_EXIST) reason = get_str_by_path(request, 'reason') if (refund_status := get_str_by_path(request, 'status')) is None: raise BusinessException(Error.INVALID_REQUEST)
def create_invoice(self, payment_account: PaymentAccount, # pylint: disable=too-many-locals line_items: [PaymentLineItem], invoice: Invoice, **kwargs): """Create Invoice in PayBC.""" current_app.logger.debug('<create_invoice') user: UserContext = kwargs['user'] pay_endpoint = current_app.config.get('BCOL_API_ENDPOINT') + '/payments' corp_number = invoice.business_identifier amount_excluding_txn_fees = sum(line.total for line in line_items) filing_types = ','.join([item.filing_type_code for item in line_items]) remarks = f'{corp_number}({filing_types})' if user.first_name: remarks = f'{remarks}-{user.first_name}' payload: Dict = { # 'userId': payment_account.bcol_user_id if payment_account.bcol_user_id else 'PE25020', 'userId': payment_account.bcol_user_id, 'invoiceNumber': str(invoice.id), 'folioNumber': invoice.folio_number, 'amount': str(amount_excluding_txn_fees), 'rate': str(amount_excluding_txn_fees), 'remarks': remarks[:50], 'feeCode': self._get_fee_code(kwargs.get('corp_type_code'), user.is_staff() or user.is_system()) } if user.is_staff() or user.is_system(): payload['userId'] = user.user_name_with_no_idp if user.is_staff() else current_app.config[ 'BCOL_USERNAME_FOR_SERVICE_ACCOUNT_PAYMENTS'] payload['accountNumber'] = payment_account.bcol_account_id payload['formNumber'] = invoice.dat_number payload['reduntantFlag'] = 'Y' payload['rateType'] = 'C' if payload.get('folioNumber', None) is None: # Set empty folio if None payload['folioNumber'] = '' try: pay_response = self.post(pay_endpoint, user.bearer_token, AuthHeaderType.BEARER, ContentType.JSON, payload, raise_for_error=False) response_json = pay_response.json() current_app.logger.debug(response_json) pay_response.raise_for_status() except HTTPError as bol_err: current_app.logger.error(bol_err) error_type: str = response_json.get('type') if error_type.isdigit(): error = get_bcol_error(int(error_type)) else: error = Error.BCOL_ERROR raise BusinessException(error) invoice = { 'invoice_number': response_json.get('key'), 'reference_number': response_json.get('sequenceNo'), 'totalAmount': -(int(response_json.get('totalAmount', 0)) / 100) } current_app.logger.debug('>create_invoice') return invoice
def get_payment(cls, payment_id): """Get payment related records.""" try: payment: Payment = Payment.find_by_id(payment_id) if not payment.id: raise BusinessException(Error.PAY005) return payment.asdict() except Exception as e: current_app.logger.debug('Error on get payment {}', e) raise
def find_account(cls, business_info: Dict[str, Any], authorization: Dict[str, Any], payment_system: str, **kwargs): """Find payment account by corp number, corp type and payment system code.""" current_app.logger.debug('<find_payment_account') user: UserContext = kwargs['user'] auth_account_id: str = get_str_by_path(authorization, 'account/id') bcol_user_id: str = get_str_by_path(authorization, 'account/paymentPreference/bcOnlineUserId') bcol_account_id: str = get_str_by_path(authorization, 'account/paymentPreference/bcOnlineAccountId') corp_number: str = business_info.get('businessIdentifier') corp_type: str = business_info.get('corpType') account_dao = None if payment_system == PaymentSystem.BCOL.value: # If BCOL payment and if the payment is inititated by customer check if bcol_user_id is present # Staff and system can make payments for users with no bcol account if not user.is_system() and not user.is_staff() and bcol_user_id is None: raise BusinessException(Error.INCOMPLETE_ACCOUNT_SETUP) account_dao: BcolPaymentAccount = BcolPaymentAccount.find_by_bcol_user_id_and_account( auth_account_id=auth_account_id, bcol_user_id=bcol_user_id, bcol_account_id=bcol_account_id ) elif payment_system == PaymentSystem.INTERNAL.value: account_dao: InternalPaymentAccount = InternalPaymentAccount. \ find_by_corp_number_and_corp_type_and_account_id(corp_number=corp_number, corp_type=corp_type, account_id=auth_account_id ) elif payment_system == PaymentSystem.PAYBC.value: if not corp_number and not corp_type: raise BusinessException(Error.INVALID_CORP_OR_FILING_TYPE) account_dao = CreditPaymentAccount.find_by_corp_number_and_corp_type_and_auth_account_id( corp_number=corp_number, corp_type=corp_type, auth_account_id=auth_account_id ) payment_account = PaymentAccount() payment_account.populate(account_dao) # pylint: disable=protected-access current_app.logger.debug('>find_payment_account') return payment_account
def _validate_and_throw_error(instance: PaymentSystemService, payment_account: PaymentAccount): if isinstance(instance, PadService): is_in_pad_confirmation_period = payment_account.pad_activation_date > datetime.now( ) is_cfs_account_in_pending_status = payment_account.cfs_account_status == \ CfsAccountStatus.PENDING_PAD_ACTIVATION.value if is_in_pad_confirmation_period or is_cfs_account_in_pending_status: raise BusinessException( Error.ACCOUNT_IN_PAD_CONFIRMATION_PERIOD)
def create(payment_method: str = None, corp_type: str = None, payment_system: str = None): """Create a subclass of PaymentSystemService based on input params.""" current_app.logger.debug('<create') _instance: PaymentSystemService = None current_app.logger.debug('payment_method: {}, corp_type : {}'.format( payment_method, corp_type)) if not payment_method and not corp_type and not payment_system: raise BusinessException(Error.PAY003) if (payment_method == 'CC' and corp_type == 'CP') or payment_system == 'PAYBC': _instance = PaybcService() else: raise BusinessException(Error.PAY003) return _instance
def create(**kwargs): """Create a subclass of PaymentSystemService based on input params.""" current_app.logger.debug('<create') user: UserContext = kwargs['user'] total_fees: int = kwargs.get('fees', None) payment_account: PaymentAccount = kwargs.get('payment_account', None) payment_method = kwargs.get( 'payment_method', PaymentMethod.DIRECT_PAY.value if current_app.config.get('DIRECT_PAY_ENABLED') else PaymentMethod.CC.value) account_info = kwargs.get('account_info', None) has_bcol_account_number = account_info is not None and account_info.get( 'bcolAccountNumber') is not None _instance: PaymentSystemService = None current_app.logger.debug('payment_method: {}'.format(payment_method)) if not payment_method: raise BusinessException(Error.INVALID_CORP_OR_FILING_TYPE) if total_fees == 0: _instance = InternalPayService() elif Role.STAFF.value in user.roles: if has_bcol_account_number: _instance = BcolService() else: _instance = InternalPayService() else: # System accounts can create BCOL payments similar to staff by providing as payload if has_bcol_account_number and Role.SYSTEM.value in user.roles: _instance = BcolService() else: _instance = PaymentSystemFactory.create_from_payment_method( payment_method) if not _instance: raise BusinessException(Error.INVALID_CORP_OR_FILING_TYPE) PaymentSystemFactory._validate_and_throw_error(_instance, payment_account) return _instance
def create(payment_identifier: str, redirect_uri: str, jwt: JwtManager = None, skip_auth_check: bool = False): """Create transaction record.""" current_app.logger.debug('<create transaction') # Lookup payment record payment: Payment = Payment.find_by_id(payment_identifier, jwt=jwt, one_of_roles=[EDIT_ROLE], skip_auth_check=skip_auth_check) if not payment.id: raise BusinessException(Error.PAY005) if payment.payment_status_code == Status.COMPLETED.value: # Cannot start transaction on completed payment raise BusinessException(Error.PAY006) # If there are active transactions (status=CREATED), then invalidate all of them and create a new one. existing_transactions = PaymentTransactionModel.find_by_payment_id( payment.id) if existing_transactions: for existing_transaction in existing_transactions: if existing_transaction.status_code != Status.CANCELLED.value: existing_transaction.status_code = Status.CANCELLED.value existing_transaction.transaction_end_time = datetime.now() existing_transaction.save() transaction = PaymentTransaction() transaction.payment_id = payment.id transaction.client_system_url = redirect_uri transaction.status_code = Status.CREATED.value transaction_dao = transaction.flush() transaction._dao = transaction_dao # pylint: disable=protected-access transaction.pay_system_url = transaction.build_pay_system_url( payment, transaction.id) transaction_dao = transaction.save() transaction = PaymentTransaction() transaction._dao = transaction_dao # pylint: disable=protected-access current_app.logger.debug('>create transaction') return transaction
def find_by_id(payment_identifier: int, transaction_id: uuid): """Find transaction by id.""" transaction_dao = PaymentTransactionModel.find_by_id_and_payment_id(transaction_id, payment_identifier) if not transaction_dao: raise BusinessException(Error.INVALID_TRANSACTION_ID) transaction = PaymentTransaction() transaction._dao = transaction_dao # pylint: disable=protected-access current_app.logger.debug('>find_by_id') return transaction
def find_by_id(transaction_id: uuid): """Find transaction by id.""" current_app.logger.debug(f'>find_by_id {transaction_id}') transaction_dao = PaymentTransactionModel.find_by_id(transaction_id) if not transaction_dao: raise BusinessException(Error.INVALID_TRANSACTION_ID) transaction = PaymentTransaction.__wrap_dao(transaction_dao) current_app.logger.debug('>find_by_id') return transaction
def find_by_id(account_id: int): """Find account by id.""" account_dao = PaymentAccountModel.find_by_id(account_id) if not account_dao: raise BusinessException(Error.PAY009) account = PaymentAccount() account._dao = account_dao # pylint: disable=protected-access current_app.logger.debug('>find_by_id') return account
def create_receipt(payment_identifier: str, invoice_identifier: str, filing_data: Tuple[Dict[str, Any]], user_jwt: str): """Create receipt.""" current_app.logger.debug('<create receipt initiated', payment_identifier, invoice_identifier) receipt_dict = { 'templateVars': { 'lineItems': [], }, 'templateName': 'payment_receipt_coops', 'reportName': 'payment_receipt_coops' } template_vars = receipt_dict['templateVars'] template_vars['coopsName'] = filing_data.get('corpName') template_vars['filingDateTime'] = filing_data.get('filingDateTime') # inovice number not mandatory ;since only one invoice exist for a payment now if not invoice_identifier: invoice_data = Invoice.find_by_payment_identifier( payment_identifier).asdict() else: invoice_data = Invoice.find_by_id(invoice_identifier, payment_identifier).asdict() template_vars['incorporationNumber'] = invoice_data['created_by'] template_vars['paymentInvoiceNumber'] = invoice_data['invoice_number'] if 'receipts' not in invoice_data: raise BusinessException(Error.PAY999) template_vars['receiptNumber'] = invoice_data['receipts'][0][ 'receipt_number'] for line_item in invoice_data['line_items']: template_vars['lineItems'].append({ 'description': line_item['description'], 'filingFees': '{:.2f}'.format(line_item['total']) }) template_vars['lineItems'].append({ 'description': 'Total', 'filingFees': '{:.2f}'.format(invoice_data['total']) }) current_app.logger.debug('<OAuthService invoked from receipt.py', current_app.config.get('REPORT_API_BASE_URL')) pdf_response = OAuthService.post( current_app.config.get('REPORT_API_BASE_URL'), user_jwt, AuthHeaderType.BEARER, ContentType.JSON, receipt_dict) current_app.logger.debug('<OAuthService responded to receipt.py') return pdf_response
def create_from_system_code(payment_system: str): """Create the payment system implementation from the payment system code.""" _instance: PaymentSystemService = None if payment_system == PaymentSystem.PAYBC.value: _instance = PaybcService() elif payment_system == PaymentSystem.BCOL.value: _instance = BcolService() elif payment_system == PaymentSystem.INTERNAL.value: _instance = InternalPayService() if not _instance: raise BusinessException(Error.PAY003) return _instance
def _validate_routing_slip_number_digits(rs_number: str): if len(rs_number) != 9 or not rs_number.isdigit(): raise BusinessException(Error.FAS_INVALID_ROUTING_SLIP_DIGITS) # Using the first 8 digits of the routing slip data_digits = list(map(int, rs_number[:8])) validation_digit = int(rs_number[8]) # For every 2nd digit: # -- Multiply the digit by 2 # -- If the sum is 2 digits, add the two digits together (this will always be a 1 digit number in this case) replacement_digits = [int(str(x)[0]) + int(str(x)[1]) if x > 9 else x for x in [i * 2 for i in data_digits[1::2]]] # -- Substitute the resulting digit for the original digit in the iteration replacement_digits.reverse() data_digits[1::2] = replacement_digits[:len(data_digits[1::2])] # Add all numbers together (of the 8 digits) # Subtract the 2nd digit of the sum from 10 checksum = ((10 - (sum(data_digits) % 10)) % 10) # The difference should equal the 9th digit of the routing slip ID if validation_digit != checksum: raise BusinessException(Error.FAS_INVALID_ROUTING_SLIP_DIGITS)
def _validate_linking(routing_slip: RoutingSlipModel, parent_rs_slip: RoutingSlipModel) -> None: """Validate the linking. 1). child already has a parent/already linked. 2). its already a parent. 3). parent_rs_slip has a parent.ie parent_rs_slip shouldn't already be linked 4). one of them has transactions """ if RoutingSlip._is_linked_already(routing_slip): raise BusinessException(Error.RS_ALREADY_LINKED) children = RoutingSlipModel.find_children(routing_slip.number) if children and len(children) > 0: raise BusinessException(Error.RS_ALREADY_A_PARENT) if RoutingSlip._is_linked_already(parent_rs_slip): raise BusinessException(Error.RS_PARENT_ALREADY_LINKED) # prevent self linking if routing_slip.number == parent_rs_slip.number: raise BusinessException(Error.RS_CANT_LINK_TO_SAME) # has one of these has pending if routing_slip.invoices: raise BusinessException(Error.RS_CHILD_HAS_TRANSACTIONS) # Stop the user from linking NSF. NSF can only be a parent. if routing_slip.status == RoutingSlipStatus.NSF.value: raise BusinessException(Error.RS_CANT_LINK_NSF) RoutingSlip._validate_status(parent_rs_slip, routing_slip)