def test_paybc_system_factory(session, public_user_mock):
    """Assert a paybc service is returned."""
    from pay_api.factory.payment_system_factory import PaymentSystemFactory  # noqa I001; errors out the test case

    # Test for CC and CP
    instance = PaymentSystemFactory.create(payment_method='CC', corp_type='CP')
    assert isinstance(instance, PaybcService)
    assert isinstance(instance, PaymentSystemService)

    # Test for CC and CP with zero fees
    instance = PaymentSystemFactory.create(fees=0,
                                           payment_method='CC',
                                           corp_type='CP')
    assert isinstance(instance, InternalPayService)
    assert isinstance(instance, PaymentSystemService)

    # Test for PAYBC Service
    instance = PaymentSystemFactory.create_from_system_code(
        PaymentSystem.PAYBC.value)
    assert isinstance(instance, PaybcService)
    assert isinstance(instance, PaymentSystemService)

    # Test for Internal Service
    instance = PaymentSystemFactory.create_from_system_code(
        PaymentSystem.INTERNAL.value)
    assert isinstance(instance, InternalPayService)
    assert isinstance(instance, PaymentSystemService)

    # Test for BCOL Service
    instance = PaymentSystemFactory.create_from_system_code(
        PaymentSystem.BCOL.value)
    assert isinstance(instance, BcolService)
    assert isinstance(instance, PaymentSystemService)
示例#2
0
def test_invalid_pay_system(session, public_user_mock):
    """Test invalid data."""
    from pay_api.factory.payment_system_factory import PaymentSystemFactory  # noqa I001; errors out the test case

    from pay_api.exceptions import BusinessException

    with pytest.raises(BusinessException) as excinfo:
        PaymentSystemFactory.create(payment_method=None, corp_type=None)
    assert excinfo.value.code == Error.INVALID_CORP_OR_FILING_TYPE.name

    with pytest.raises(BusinessException) as excinfo:
        PaymentSystemFactory.create(payment_method='XXX', corp_type='XXX')
    assert excinfo.value.code == Error.INVALID_CORP_OR_FILING_TYPE.name

    with pytest.raises(BusinessException) as excinfo:
        PaymentSystemFactory.create_from_system_code('XXX', 'XXXX')
    assert excinfo.value.code == Error.INVALID_CORP_OR_FILING_TYPE.name
    def build_pay_system_url(payment: Payment, transaction_id: uuid, pay_return_url: str):
        """Build pay system url which will be used to redirect to the payment system."""
        current_app.logger.debug('<build_pay_system_url')
        pay_system_service: PaymentSystemService = PaymentSystemFactory.create_from_system_code(
            payment_system=payment.payment_system_code
        )
        invoice = InvoiceModel.find_by_payment_id(payment.id)
        invoice_reference = InvoiceReference.find_active_reference_by_invoice_id(invoice.id)
        return_url = f'{pay_return_url}/{payment.id}/transaction/{transaction_id}'

        current_app.logger.debug('>build_pay_system_url')
        return pay_system_service.get_payment_system_url(Invoice.populate(invoice), invoice_reference, return_url)
示例#4
0
    def delete_payment(cls, payment_id: int):  # pylint: disable=too-many-locals,too-many-statements
        """Delete payment related records.

        Does the following;
        1. Check if payment is eligible to be deleted.
        2. Mark the payment and invoices records as deleted.
        3. Publish message to queue
        """
        current_app.logger.debug('<delete_payment')

        # update transaction function will update the status from PayBC
        _update_active_transactions(payment_id)

        payment: Payment = Payment.find_by_id(payment_id, skip_auth_check=True)
        _check_if_payment_is_completed(payment)

        # Create the payment system implementation
        pay_service: PaymentSystemService = PaymentSystemFactory.create_from_system_code(
            payment.payment_system_code)

        # Cancel all invoices
        for invoice in payment.invoices:
            invoice_reference = InvoiceReference.find_active_reference_by_invoice_id(
                invoice.id)
            payment_account = PaymentAccount.find_by_pay_system_id(
                credit_account_id=invoice.credit_account_id,
                internal_account_id=invoice.internal_account_id,
                bcol_account_id=invoice.bcol_account_id)
            pay_service.cancel_invoice(
                payment_account=payment_account,
                inv_number=invoice_reference.invoice_number)
            invoice.invoice_status_code = InvoiceStatus.DELETED.value
            for line in invoice.payment_line_items:
                line.line_item_status_code = LineItemStatus.CANCELLED.value
            invoice.save()
            invoice_reference.status_code = InvoiceReferenceStatus.CANCELLED.value
            invoice_reference.save()

        payment.payment_status_code = PaymentStatus.DELETED.value
        payment.save()

        current_app.logger.debug('>delete_payment')
    def update_transaction(payment_identifier: int, transaction_id: uuid,  # pylint: disable=too-many-locals
                           receipt_number: str):
        """Update transaction record.

        Does the following:
        1. Find the payment record with the id
        2. Find the invoice record using the payment identifier
        3. Call the pay system service and get the receipt details
        4. Save the receipt record
        5. Change the status of Invoice
        6. Change the status of Payment
        7. Update the transaction record
        """
        transaction_dao: PaymentTransactionModel = PaymentTransactionModel.find_by_id_and_payment_id(
            transaction_id, payment_identifier
        )
        if not transaction_dao:
            raise BusinessException(Error.INVALID_TRANSACTION_ID)
        if transaction_dao.status_code == TransactionStatus.COMPLETED.value:
            raise BusinessException(Error.INVALID_TRANSACTION)

        payment: Payment = Payment.find_by_id(payment_identifier, skip_auth_check=True)

        if payment.payment_status_code == PaymentStatus.COMPLETED.value:
            raise BusinessException(Error.COMPLETED_PAYMENT)

        pay_system_service: PaymentSystemService = PaymentSystemFactory.create_from_system_code(
            payment_system=payment.payment_system_code
        )

        invoice = Invoice.find_by_payment_identifier(payment_identifier, skip_auth_check=True)
        invoice_reference = InvoiceReference.find_active_reference_by_invoice_id(invoice.id)
        payment_account = PaymentAccount.find_by_pay_system_id(
            credit_account_id=invoice.credit_account_id,
            internal_account_id=invoice.internal_account_id,
            bcol_account_id=invoice.bcol_account_id)

        try:
            receipt_details = pay_system_service.get_receipt(payment_account, receipt_number, invoice_reference)
            txn_reason_code = None
        except ServiceUnavailableException as exc:
            txn_reason_code = exc.status
            receipt_details = None

        if receipt_details:
            # Find if a receipt exists with same receipt_number for the invoice
            receipt = PaymentTransaction.__save_receipt(invoice, receipt_details)

            invoice.paid = receipt.receipt_amount

            if invoice.paid == invoice.total:
                invoice.invoice_status_code = InvoiceStatus.PAID.value
                payment.payment_status_code = PaymentStatus.COMPLETED.value
                payment.save()

                invoice_reference.status_code = InvoiceReferenceStatus.COMPLETED.value
                invoice_reference.save()

            invoice.save()

            transaction_dao.status_code = TransactionStatus.COMPLETED.value
        else:
            transaction_dao.status_code = TransactionStatus.FAILED.value

        transaction_dao.transaction_end_time = datetime.now()

        # Publish status to Queue
        PaymentTransaction.publish_status(transaction_dao, payment, invoice.filing_id)

        transaction_dao = transaction_dao.save()

        transaction = PaymentTransaction()
        transaction._dao = transaction_dao  # pylint: disable=protected-access
        transaction.pay_system_reason_code = txn_reason_code

        current_app.logger.debug('>update_transaction')
        return transaction