Beispiel #1
0
def test_get_payment_system_url_service_fees(session, public_user_mock):
    """Assert that the url returned is correct."""
    today = current_local_time().strftime(PAYBC_DATE_FORMAT)
    payment_account = factory_payment_account()
    payment = factory_payment()
    payment_account.save()
    payment.save()
    invoice = factory_invoice(payment_account)
    invoice.save()
    invoice_ref = factory_invoice_reference(invoice.id).save()
    fee_schedule = FeeSchedule.find_by_filing_type_and_corp_type('CP', 'OTANN')
    distribution_code = DistributionCodeModel.find_by_active_for_fee_schedule(fee_schedule.fee_schedule_id)

    distribution_code_svc = DistributionCode()
    distribution_code_payload = get_distribution_code_payload()
    # Set service fee distribution
    distribution_code_payload.update({'serviceFeeDistributionCodeId': distribution_code.distribution_code_id})
    # update the existing gl code with new values
    distribution_code_svc.save_or_update(distribution_code_payload,
                                         distribution_code.distribution_code_id)

    service_fee = 100
    line = factory_payment_line_item(invoice.id, fee_schedule_id=fee_schedule.fee_schedule_id, service_fees=service_fee)
    line.save()
    direct_pay_service = DirectPayService()
    payment_response_url = direct_pay_service.get_payment_system_url_for_invoice(invoice, invoice_ref, 'google.com')
    url_param_dict = dict(urllib.parse.parse_qsl(urllib.parse.urlsplit(payment_response_url).query))
    assert url_param_dict['trnDate'] == today
    assert url_param_dict['glDate'] == today
    assert url_param_dict['description'] == 'Direct_Sale'
    assert url_param_dict['pbcRefNumber'] == current_app.config.get('PAYBC_DIRECT_PAY_REF_NUMBER')
    assert url_param_dict['trnNumber'] == generate_transaction_number(invoice.id)
    assert url_param_dict['trnAmount'] == str(invoice.total)
    assert url_param_dict['paymentMethod'] == 'CC'
    assert url_param_dict['redirectUri'] == 'google.com'
    revenue_str = f"1:{distribution_code_payload['client']}." \
                  f"{distribution_code_payload['responsibilityCentre']}." \
                  f"{distribution_code_payload['serviceLine']}." \
                  f"{distribution_code_payload['stob']}." \
                  f"{distribution_code_payload['projectCode']}." \
                  f'000000.0000:10.00'
    revenue_str_service_fee = f"2:{distribution_code_payload['client']}." \
                              f"{distribution_code_payload['responsibilityCentre']}." \
                              f"{distribution_code_payload['serviceLine']}." \
                              f"{distribution_code_payload['stob']}." \
                              f"{distribution_code_payload['projectCode']}." \
                              f'000000.0000:{format(service_fee, DECIMAL_PRECISION)}'
    assert url_param_dict['revenue'] == f'{revenue_str}|{revenue_str_service_fee}'
    urlstring = f"trnDate={today}&pbcRefNumber={current_app.config.get('PAYBC_DIRECT_PAY_REF_NUMBER')}&" \
                f'glDate={today}&description=Direct_Sale&' \
                f'trnNumber={generate_transaction_number(invoice.id)}&' \
                f'trnAmount={invoice.total}&' \
                f'paymentMethod=CC&' \
                f'redirectUri=google.com&' \
                f'currency=CAD&' \
                f'revenue={revenue_str}|' \
                f'{revenue_str_service_fee}'
    expected_hash_str = HashingService.encode(urlstring)

    assert expected_hash_str == url_param_dict['hashValue']
    def _create_nsf_invoice(cls, cfs_account: CfsAccountModel, rs_number: str,
                            payment_account: PaymentAccountModel) -> InvoiceModel:
        """Create Invoice, line item and invoice reference records."""
        fee_schedule: FeeScheduleModel = FeeScheduleModel.find_by_filing_type_and_corp_type(corp_type_code='BCR',
                                                                                            filing_type_code='NSF')
        invoice = InvoiceModel(
            bcol_account=payment_account.bcol_account,
            payment_account_id=payment_account.id,
            cfs_account_id=cfs_account.id,
            invoice_status_code=InvoiceStatus.CREATED.value,
            total=fee_schedule.fee.amount,
            service_fees=0,
            paid=0,
            payment_method_code=PaymentMethod.INTERNAL.value,
            corp_type_code='BCR',
            created_on=datetime.now(),
            created_by='SYSTEM',
            routing_slip=rs_number
        )
        invoice = invoice.save()
        distribution: DistributionCodeModel = DistributionCodeModel.find_by_active_for_fee_schedule(
            fee_schedule.fee_schedule_id)

        line_item = PaymentLineItemModel(
            invoice_id=invoice.id,
            total=invoice.total,
            fee_schedule_id=fee_schedule.fee_schedule_id,
            description=fee_schedule.filing_type.description,
            filing_fees=invoice.total,
            gst=0,
            priority_fees=0,
            pst=0,
            future_effective_fees=0,
            line_item_status_code=LineItemStatus.ACTIVE.value,
            service_fees=0,
            fee_distribution_id=distribution.distribution_code_id)
        line_item.save()

        invoice_response = CFSService.create_account_invoice(transaction_number=invoice.id,
                                                             line_items=invoice.payment_line_items,
                                                             cfs_account=cfs_account)

        invoice_number = invoice_response.json().get('invoice_number', None)
        current_app.logger.info(f'invoice_number  {invoice_number}  created in CFS for NSF.')

        InvoiceReferenceModel(
            invoice_id=invoice.id,
            invoice_number=invoice_number,
            reference_number=invoice_response.json().get('pbc_ref_number', None),
            status_code=InvoiceReferenceStatus.ACTIVE.value
        ).save()

        return invoice
Beispiel #3
0
def factory_payment_line_item(invoice_id: str, fee_schedule_id: int, filing_fees: int = 10, total: int = 10,
                              service_fees: int = 0, status: str = LineItemStatus.ACTIVE.value):
    """Return Factory."""
    return PaymentLineItem(
        invoice_id=invoice_id,
        fee_schedule_id=fee_schedule_id,
        filing_fees=filing_fees,
        total=total,
        service_fees=service_fees,
        line_item_status_code=status,
        fee_distribution_id=DistributionCode.find_by_active_for_fee_schedule(fee_schedule_id).distribution_code_id
    )
Beispiel #4
0
def _create_nsf_invoice(cfs_account: CfsAccountModel, inv_number: str,
                        payment_account: PaymentAccountModel) -> InvoiceModel:
    """Create Invoice, line item and invoice referwnce records."""
    fee_schedule: FeeScheduleModel = FeeScheduleModel.find_by_filing_type_and_corp_type(
        corp_type_code='BCR', filing_type_code='NSF')
    invoice = InvoiceModel(bcol_account=payment_account.bcol_account,
                           payment_account_id=payment_account.id,
                           cfs_account_id=cfs_account.id,
                           invoice_status_code=InvoiceStatus.CREATED.value,
                           total=fee_schedule.fee.amount,
                           service_fees=0,
                           paid=0,
                           payment_method_code=PaymentMethod.CC.value,
                           corp_type_code='BCR',
                           created_on=datetime.now(),
                           created_by='SYSTEM')
    invoice = invoice.save()
    distribution: DistributionCodeModel = DistributionCodeModel.find_by_active_for_fee_schedule(
        fee_schedule.fee_schedule_id)

    line_item = PaymentLineItemModel(
        invoice_id=invoice.id,
        total=invoice.total,
        fee_schedule_id=fee_schedule.fee_schedule_id,
        description=fee_schedule.filing_type.description,
        filing_fees=invoice.total,
        gst=0,
        priority_fees=0,
        pst=0,
        future_effective_fees=0,
        line_item_status_code=LineItemStatus.ACTIVE.value,
        service_fees=0,
        fee_distribution_id=distribution.distribution_code_id
        if distribution else 1)  # TODO
    line_item.save()

    inv_ref: InvoiceReferenceModel = InvoiceReferenceModel(
        invoice_id=invoice.id,
        invoice_number=inv_number,
        reference_number=InvoiceReferenceModel.
        find_any_active_reference_by_invoice_number(
            invoice_number=inv_number).reference_number,
        status_code=InvoiceReferenceStatus.ACTIVE.value)
    inv_ref.save()

    return invoice
    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_excluding_service_fees
        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 if fee.quantity else 1
        p.line_item_status_code = LineItemStatus.ACTIVE.value
        p.waived_fees = fee.waived_fee_amount
        p.service_fees = fee.service_fees

        # Set distribution details to line item
        distribution_code = None
        if p.total > 0:
            distribution_code = DistributionCodeModel.find_by_active_for_fee_schedule(
                fee.fee_schedule_id)
            p.fee_distribution_id = distribution_code.distribution_code_id

        if fee.waived_fee_amount > 0:
            if user.has_role(Role.STAFF.value):
                p.waived_by = user.user_name
            else:
                raise BusinessException(Error.FEE_OVERRIDE_NOT_ALLOWED)

        p_dao = p.flush()

        p = PaymentLineItem()
        p._dao = p_dao  # pylint: disable=protected-access

        # Set distribution model to avoid more queries to DB
        p.fee_distribution = distribution_code
        current_app.logger.debug('>create')
        return p
Beispiel #6
0
async def test_failed_payment_ejv_reconciliations(session, app, stan_server,
                                                  event_loop, client_id,
                                                  events_stan, future,
                                                  mock_publish):
    """Test Reconciliations worker."""
    # Call back for the subscription
    from reconciliations.worker import cb_subscription_handler

    # Create a Credit Card Payment
    # register the handler to test it
    await subscribe_to_queue(
        events_stan,
        current_app.config.get('SUBSCRIPTION_OPTIONS').get('subject'),
        current_app.config.get('SUBSCRIPTION_OPTIONS').get('queue'),
        current_app.config.get('SUBSCRIPTION_OPTIONS').get('durable_name'),
        cb_subscription_handler)

    # 1. Create EJV payment accounts
    # 2. Create invoice and related records
    # 3. Create a feedback file and assert status

    corp_type = 'BEN'
    filing_type = 'BCINC'

    # Find fee schedule which have service fees.
    fee_schedule: FeeScheduleModel = FeeScheduleModel.find_by_filing_type_and_corp_type(
        corp_type, filing_type)
    # Create a service fee distribution code
    service_fee_dist_code = factory_distribution(name='service fee',
                                                 client='112',
                                                 reps_centre='99999',
                                                 service_line='99999',
                                                 stob='9999',
                                                 project_code='9999999')
    service_fee_dist_code.save()

    dist_code: DistributionCodeModel = DistributionCodeModel.find_by_active_for_fee_schedule(
        fee_schedule.fee_schedule_id)
    # Update fee dist code to match the requirement.
    dist_code.client = '112'
    dist_code.responsibility_centre = '22222'
    dist_code.service_line = '33333'
    dist_code.stob = '4444'
    dist_code.project_code = '5555555'
    dist_code.service_fee_distribution_code_id = service_fee_dist_code.distribution_code_id
    dist_code.save()

    # GA
    jv_account_1 = factory_create_ejv_account(auth_account_id='1')
    jv_account_2 = factory_create_ejv_account(auth_account_id='2')

    # GI
    jv_account_3 = factory_create_ejv_account(auth_account_id='3',
                                              client='111')
    jv_account_4 = factory_create_ejv_account(auth_account_id='4',
                                              client='111')

    # Now create JV records.
    # Create EJV File model
    file_ref = f'INBOX.{datetime.now()}'
    ejv_file: EjvFileModel = EjvFileModel(
        file_ref=file_ref,
        disbursement_status_code=DisbursementStatus.UPLOADED.value,
        is_distribution=False).save()
    ejv_file_id = ejv_file.id

    feedback_content = f'..BG...........00000000{ejv_file_id}...\n' \
                       f'..BH...0000.................................................................................' \
                       f'.....................................................................CGI\n'

    jv_accounts = [jv_account_1, jv_account_2, jv_account_3, jv_account_4]
    inv_ids = []
    jv_account_ids = []
    inv_total_amount = 101.5
    for jv_acc in jv_accounts:
        jv_account_ids.append(jv_acc.id)
        inv = factory_invoice(payment_account=jv_acc,
                              corp_type_code=corp_type,
                              total=inv_total_amount,
                              status_code=InvoiceStatus.APPROVED.value,
                              payment_method_code=None)
        factory_invoice_reference(inv.id)
        line: PaymentLineItemModel = factory_payment_line_item(
            invoice_id=inv.id,
            fee_schedule_id=fee_schedule.fee_schedule_id,
            filing_fees=100,
            total=100,
            service_fees=1.5,
            fee_dist_id=dist_code.distribution_code_id)
        inv_ids.append(inv.id)
        ejv_header: EjvHeaderModel = EjvHeaderModel(
            disbursement_status_code=DisbursementStatus.UPLOADED.value,
            ejv_file_id=ejv_file.id,
            payment_account_id=jv_acc.id).save()

        EjvInvoiceLinkModel(
            invoice_id=inv.id,
            ejv_header_id=ejv_header.id,
            disbursement_status_code=DisbursementStatus.UPLOADED.value).save()
        inv_total = f'{inv.total:.2f}'.zfill(15)
        pay_line_amount = f'{line.total:.2f}'.zfill(15)
        service_fee_amount = f'{line.service_fees:.2f}'.zfill(15)
        jh_and_jd = f'..JH...FI0000000{ejv_header.id}.........................{inv_total}.....................' \
                    f'............................................................................................' \
                    f'............................................................................................' \
                    f'.........1111ERROR..........................................................................' \
                    f'.......................................................................CGI\n' \
                    f'..JD...FI0000000{ejv_header.id}00001........................................................' \
                    f'...........{pay_line_amount}D.................................................................' \
                    f'...................................{inv.id}                                             ' \
                    f'                                                                1111ERROR...................' \
                    f'............................................................................................' \
                    f'..................................CGI\n' \
                    f'..JD...FI0000000{ejv_header.id}00002........................................................' \
                    f'...........{pay_line_amount}C.................................................................' \
                    f'...................................{inv.id}                                             ' \
                    f'                                                                1111ERROR...................' \
                    f'............................................................................................' \
                    f'..................................CGI\n' \
                    f'..JD...FI0000000{ejv_header.id}00003...........................................................' \
                    f'........{service_fee_amount}D.................................................................' \
                    f'...................................{inv.id}                                             ' \
                    f'                                                                1111ERROR...................' \
                    f'............................................................................................' \
                    f'..................................CGI\n' \
                    f'..JD...FI0000000{ejv_header.id}00004........................................................' \
                    f'...........{service_fee_amount}C..............................................................' \
                    f'......................................{inv.id}                                             ' \
                    f'                                                                1111ERROR...................' \
                    f'............................................................................................' \
                    f'..................................CGI\n'
        feedback_content = feedback_content + jh_and_jd
    feedback_content = feedback_content + f'..BT.......FI0000000{ejv_header.id}000000000000002{inv_total}0000.......' \
                                          f'.........................................................................' \
                                          f'......................................................................CGI'
    ack_file_name = f'ACK.{file_ref}'

    with open(ack_file_name, 'a+') as jv_file:
        jv_file.write('')
        jv_file.close()

    # Now upload the ACK file to minio and publish message.
    upload_to_minio(file_name=ack_file_name, value_as_bytes=str.encode(''))

    await helper_add_ejv_event_to_queue(events_stan, file_name=ack_file_name)

    # Query EJV File and assert the status is changed
    ejv_file = EjvFileModel.find_by_id(ejv_file_id)
    assert ejv_file.disbursement_status_code == DisbursementStatus.ACKNOWLEDGED.value

    feedback_file_name = f'FEEDBACK.{file_ref}'

    with open(feedback_file_name, 'a+') as jv_file:
        jv_file.write(feedback_content)
        jv_file.close()

    # Now upload the ACK file to minio and publish message.
    with open(feedback_file_name, 'rb') as f:
        upload_to_minio(f.read(), feedback_file_name)

    await helper_add_ejv_event_to_queue(events_stan,
                                        file_name=feedback_file_name,
                                        message_type='FEEDBACKReceived')

    # Query EJV File and assert the status is changed
    ejv_file = EjvFileModel.find_by_id(ejv_file_id)
    assert ejv_file.disbursement_status_code == DisbursementStatus.COMPLETED.value
    # Assert invoice and receipt records
    for inv_id in inv_ids:
        invoice: InvoiceModel = InvoiceModel.find_by_id(inv_id)
        assert invoice.disbursement_status_code is None
        assert invoice.invoice_status_code == InvoiceStatus.APPROVED.value  # Will stay as original status
        invoice_ref: InvoiceReferenceModel = InvoiceReferenceModel.find_reference_by_invoice_id_and_status(
            inv_id, InvoiceReferenceStatus.COMPLETED.value)
        assert invoice_ref is None  # No completed inv ref
        receipt = ReceiptModel.find_by_invoice_id_and_receipt_number(
            invoice_id=inv_id)
        assert receipt is None  # NO receipt

    # Assert payment records
    for jv_account_id in jv_account_ids:
        account = PaymentAccountModel.find_by_id(jv_account_id)
        payment: PaymentModel = PaymentModel.search_account_payments(
            auth_account_id=account.auth_account_id,
            payment_status=PaymentStatus.COMPLETED.value,
            page=1,
            limit=100)[0]
        assert len(payment) == 0
Beispiel #7
0
def test_payments_for_gov_accounts(session, monkeypatch):
    """Test payments for gov accounts.

    Steps:
    1) Update a distribution code with client code 112.
    2) Create multiple gov accounts for GA - 112
    3) Create multiple gov accounts for GI - NOT 112
    4) Create some transactions for these accounts
    5) Run the job and assert results.
    """
    monkeypatch.setattr('pysftp.Connection.put', lambda *args, **kwargs: None)

    corp_type = 'BEN'
    filing_type = 'BCINC'

    # Find fee schedule which have service fees.
    fee_schedule: FeeSchedule = FeeSchedule.find_by_filing_type_and_corp_type(corp_type, filing_type)
    # Create a service fee distribution code
    service_fee_dist_code = factory_distribution(name='service fee', client='112', reps_centre='99999',
                                                 service_line='99999',
                                                 stob='9999', project_code='9999999')
    service_fee_dist_code.save()

    dist_code: DistributionCode = DistributionCode.find_by_active_for_fee_schedule(fee_schedule.fee_schedule_id)
    # Update fee dist code to match the requirement.
    dist_code.client = '112'
    dist_code.responsibility_centre = '22222'
    dist_code.service_line = '33333'
    dist_code.stob = '4444'
    dist_code.project_code = '5555555'
    dist_code.service_fee_distribution_code_id = service_fee_dist_code.distribution_code_id
    dist_code.save()

    # GA
    jv_account_1 = factory_create_ejv_account(auth_account_id='1')
    jv_account_2 = factory_create_ejv_account(auth_account_id='2')

    # GI
    jv_account_3 = factory_create_ejv_account(auth_account_id='3', client='111')
    jv_account_4 = factory_create_ejv_account(auth_account_id='4', client='111')

    jv_accounts = [jv_account_1, jv_account_2, jv_account_3, jv_account_4]
    inv_ids = []
    for jv_acc in jv_accounts:
        inv = factory_invoice(payment_account=jv_acc, corp_type_code=corp_type, total=101.5,
                              status_code=InvoiceStatus.APPROVED.value, payment_method_code=None)
        factory_payment_line_item(invoice_id=inv.id,
                                  fee_schedule_id=fee_schedule.fee_schedule_id,
                                  filing_fees=100,
                                  total=100,
                                  service_fees=1.5,
                                  fee_dist_id=dist_code.distribution_code_id)
        inv_ids.append(inv.id)

    EjvPaymentTask.create_ejv_file()

    # Lookup invoice and assert invoice status
    for inv_id in inv_ids:
        invoice_ref = InvoiceReference.find_reference_by_invoice_id_and_status(inv_id,
                                                                               InvoiceReferenceStatus.ACTIVE.value)
        assert invoice_ref

        ejv_inv_link = db.session.query(EjvInvoiceLink).filter(EjvInvoiceLink.invoice_id == inv_id).first()
        assert ejv_inv_link

        ejv_header = db.session.query(EjvHeader).filter(EjvHeader.id == ejv_inv_link.ejv_header_id).first()
        assert ejv_header.disbursement_status_code == DisbursementStatus.UPLOADED.value
        assert ejv_header

        ejv_file: EjvFile = EjvFile.find_by_id(ejv_header.ejv_file_id)
        assert ejv_file
        assert ejv_file.disbursement_status_code == DisbursementStatus.UPLOADED.value
        assert not ejv_file.is_distribution