Пример #1
0
def factory_payment_account(
        payment_system_code: str = 'PAYBC',
        payment_method_code: str = 'CC',
        account_number='4101',
        bcol_user_id='test',
        auth_account_id: str = '1234',
        cfs_account_status: str = CfsAccountStatus.ACTIVE.value):
    """Return Factory."""
    # Create a payment account
    account = PaymentAccount(auth_account_id=auth_account_id,
                             bcol_user_id=bcol_user_id,
                             bcol_account='TEST',
                             payment_method=payment_method_code,
                             pad_activation_date=datetime.now()).save()

    CfsAccount(cfs_party='11111',
               cfs_account=account_number,
               cfs_site='29921',
               account_id=account.id,
               status=cfs_account_status).save()

    if payment_system_code == PaymentSystem.BCOL.value:
        account.payment_method = PaymentMethod.DRAWDOWN.value
    elif payment_system_code == PaymentSystem.PAYBC.value:
        account.payment_method = payment_method_code

    return account
Пример #2
0
def test_internal_rs_back_active(session, public_user_mock):
    """12033 - Scenario 2.

    Routing slip is complete and a transaction is cancelled
    the balance is restored - Should move back to Active
    """
    payment_response = PaymentService.create_invoice(
        get_routing_slip_payment_request(), get_auth_staff())
    account_model = PaymentAccount.find_by_auth_account_id(get_auth_staff().get('account').get('id'))
    account_id = account_model.id
    assert account_id is not None
    assert payment_response.get('id') is not None

    rs_number = '123456789'
    rs = factory_routing_slip(number=rs_number, payment_account_id=account_id, remaining_amount=50.00)
    rs.save()

    # Create another invoice with a routing slip.
    invoice = PaymentService.create_invoice(get_routing_slip_payment_request(), get_auth_staff())
    account_model = PaymentAccount.find_by_auth_account_id(get_auth_staff().get('account').get('id'))

    assert account_id == account_model.id

    rs = RoutingSlipModel.find_by_number(rs_number)
    assert rs.remaining_amount == 0.0
    assert rs.status == RoutingSlipStatus.COMPLETE.name

    invoice = Invoice.find_by_id(invoice['id'])
    InternalPayService().process_cfs_refund(invoice)

    assert rs.status == RoutingSlipStatus.ACTIVE.name
Пример #3
0
def test_create_payment_record_with_internal_pay(session, public_user_mock):
    """Assert that the payment records are created."""
    # Create invoice without routing slip.
    payment_response = PaymentService.create_invoice(
        get_routing_slip_payment_request(), get_auth_staff())
    account_model = PaymentAccount.find_by_auth_account_id(get_auth_staff().get('account').get('id'))
    account_id = account_model.id
    assert account_id is not None
    assert payment_response.get('id') is not None

    rs_number = '123456789'
    rs = factory_routing_slip(number=rs_number, payment_account_id=account_id, remaining_amount=50.00)
    rs.save()

    # Create another invoice with a routing slip.
    PaymentService.create_invoice(get_routing_slip_payment_request(), get_auth_staff())
    account_model = PaymentAccount.find_by_auth_account_id(get_auth_staff().get('account').get('id'))

    assert account_id == account_model.id

    rs = RoutingSlipModel.find_by_number(rs_number)
    assert rs.remaining_amount == 0.0
    """12033 - Scenario 1.

    Manual transaction reduces RS to 0.00
    Routing slip status becomes Completed
    """
    assert rs.status == RoutingSlipStatus.COMPLETE.name
def test_activate_bcol_change_to_pad(session):
    """Test Activate account."""
    # Create a pending account first, then call the job
    account = factory_create_pad_account(
        auth_account_id='1', payment_method=PaymentMethod.DRAWDOWN.value)
    CreateAccountTask.create_accounts()
    account = PaymentAccount.find_by_id(account.id)
    cfs_account: CfsAccount = CfsAccount.find_effective_by_account_id(
        account.id)
    assert cfs_account.status == CfsAccountStatus.PENDING_PAD_ACTIVATION.value, 'Created account has pending pad status'
    assert account.payment_method == PaymentMethod.DRAWDOWN.value

    ActivatePadAccountTask.activate_pad_accounts()
    cfs_account: CfsAccount = CfsAccount.find_effective_by_account_id(
        account.id)
    assert cfs_account.status == CfsAccountStatus.PENDING_PAD_ACTIVATION.value, \
        'Same day Job runs and shouldnt change anything.'
    account = PaymentAccount.find_by_id(account.id)
    assert account.payment_method == PaymentMethod.DRAWDOWN.value

    time_delay = current_app.config['PAD_CONFIRMATION_PERIOD_IN_DAYS']
    with freeze_time(datetime.today() + timedelta(days=time_delay, minutes=1)):
        ActivatePadAccountTask.activate_pad_accounts()
        assert cfs_account.status == CfsAccountStatus.ACTIVE.value, \
            'After the confirmation period is over , status should be active'
        account = PaymentAccount.find_by_id(account.id)
        assert account.payment_method == PaymentMethod.PAD.value
Пример #5
0
def test_find_by_invalid_corp_number_and_corp_type_and_system(session):
    """Assert find works.

    Start with a blank database.
    """
    payment_account = factory_payment_account()
    payment_account.save()
    assert PaymentAccount.find_by_corp_number_and_corp_type_and_system('CP0001234', 'CP', 'BCOL') is None
    assert PaymentAccount.find_by_corp_number_and_corp_type_and_system(None, None, None) is None
Пример #6
0
def test_rollback(session):
    """Assert rollback works.

    Start with a blank database.
    """
    payment_account = factory_payment_account()
    payment_account.flush()
    assert PaymentAccount.find_by_corp_number_and_corp_type_and_system('CP0001234', 'CP', 'PAYBC') is not None
    payment_account.rollback()
    assert PaymentAccount.find_by_corp_number_and_corp_type_and_system('CP0001234', 'CP', 'PAYBC') is None
Пример #7
0
def test_create_payment_record(session):
    """Assert that the payment records are created."""
    payment_response = PaymentService.create_payment(get_payment_request(), 'test')
    account_model = PaymentAccount.find_by_corp_number_and_corp_type_and_system('CP1234', 'CP', 'PAYBC')
    account_id = account_model.id
    assert account_id is not None
    assert payment_response.get('id') is not None
    # Create another payment with same request, the account should be the same
    PaymentService.create_payment(get_payment_request(), 'test')
    account_model = PaymentAccount.find_by_corp_number_and_corp_type_and_system('CP1234', 'CP', 'PAYBC')
    assert account_id == account_model.id
Пример #8
0
def test_create_payment_record(session, public_user_mock):
    """Assert that the payment records are created."""
    payment_response = PaymentService.create_invoice(get_payment_request(), get_auth_basic_user())
    account_model = PaymentAccount.find_by_auth_account_id(get_auth_basic_user().get('account').get('id'))
    account_id = account_model.id
    assert account_id is not None
    assert payment_response.get('id') is not None
    # Create another payment with same request, the account should be the same
    PaymentService.create_invoice(get_payment_request(), get_auth_basic_user())
    account_model = PaymentAccount.find_by_auth_account_id(get_auth_basic_user().get('account').get('id'))

    assert account_id == account_model.id
Пример #9
0
def test_create_payment_record_with_direct_pay(session, public_user_mock):
    """Assert that the payment records are created."""
    current_app.config['DIRECT_PAY_ENABLED'] = True
    payment_response = PaymentService.create_invoice(
        get_payment_request(), get_auth_basic_user(PaymentMethod.DIRECT_PAY.value))
    account_model = PaymentAccount.find_by_auth_account_id(get_auth_basic_user().get('account').get('id'))
    account_id = account_model.id
    assert account_id is not None
    assert payment_response.get('id') is not None
    # Create another payment with same request, the account should be the same
    PaymentService.create_invoice(get_payment_request(), get_auth_basic_user())
    account_model = PaymentAccount.find_by_auth_account_id(get_auth_basic_user().get('account').get('id'))

    assert account_id == account_model.id
Пример #10
0
 def _update_pad_activation_date(cls, cfs_account: CfsAccountModel,
                                 is_sandbox: bool,
                                 payment_account: PaymentAccountModel):
     """Update PAD activation date."""
     is_pad = payment_account.payment_method == PaymentMethod.PAD.value
     # If the account is created for sandbox env, then set the status to ACTIVE and set pad activation time to now
     if is_pad and is_sandbox:
         cfs_account.status = CfsAccountStatus.ACTIVE.value
         payment_account.pad_activation_date = datetime.now()
     # override payment method for since pad has 3 days wait period
     elif is_pad:
         effective_pay_method, activation_date = PaymentAccount._get_payment_based_on_pad_activation(
             payment_account)
         payment_account.pad_activation_date = activation_date
         payment_account.payment_method = effective_pay_method
Пример #11
0
def test_get_monthly_statement_report_as_csv(session, client, jwt, app):
    """Assert that the monthly statement report is returning response."""
    # Create a payment account and statement details, then get all statements for the account
    token = jwt.create_jwt(get_claims(), token_header)
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json',
        'Accept': ContentType.CSV.value
    }

    rv = client.post('/api/v1/payment-requests',
                     data=json.dumps(
                         get_payment_request(business_identifier='CP0002000')),
                     headers=headers)

    payment: Payment = Payment.find_by_id(rv.json.get('id'))
    bcol_account: BcolPaymentAccount = BcolPaymentAccount.find_by_id(
        payment.invoices[0].bcol_account_id)
    pay_account: PaymentAccount = PaymentAccount.find_by_id(
        bcol_account.account_id)

    settings_model = factory_statement_settings(
        payment_account_id=pay_account.id,
        frequency=StatementFrequency.DAILY.value)
    statement_model = factory_statement(
        payment_account_id=pay_account.id,
        frequency=StatementFrequency.DAILY.value,
        statement_settings_id=settings_model.id)
    factory_statement_invoices(statement_id=statement_model.id,
                               invoice_id=payment.invoices[0].id)

    rv = client.get(
        f'/api/v1/accounts/{pay_account.auth_account_id}/statements/{statement_model.id}',
        headers=headers)
    assert rv.status_code == 200
Пример #12
0
def test_statement_find_by_account(session):
    """Assert that the statement settings by id works."""
    bcol_account = factory_premium_payment_account()
    bcol_account.save()

    payment = factory_payment()
    payment.save()
    i = factory_invoice(payment_account=bcol_account)
    i.save()
    factory_invoice_reference(i.id).save()

    settings_model = factory_statement_settings(
        payment_account_id=bcol_account.id,
        frequency=StatementFrequency.DAILY.value)
    statement_model = factory_statement(
        payment_account_id=bcol_account.id,
        frequency=StatementFrequency.DAILY.value,
        statement_settings_id=settings_model.id)
    factory_statement_invoices(statement_id=statement_model.id,
                               invoice_id=i.id)

    payment_account = PaymentAccount.find_by_id(bcol_account.id)
    statements = StatementService.find_by_account_id(
        payment_account.auth_account_id, page=1, limit=10)
    assert statements is not None
    assert statements.get('total') == 1
Пример #13
0
    def create_accounts(cls):  # pylint: disable=too-many-locals
        """Find all pending accounts to be created in CFS.

        Steps:
        1. Find all pending CFS accounts.
        2. Create CFS accounts.
        3. Publish a message to the queue if successful.
        """
        # Pass payment method if offline account creation has be restricted based on payment method.
        pending_accounts: List[
            CfsAccountModel] = CfsAccountModel.find_all_pending_accounts()
        current_app.logger.info(
            f'Found {len(pending_accounts)} CFS Accounts to be created.')
        if len(pending_accounts) == 0:
            return

        auth_token = get_token()

        for pending_account in pending_accounts:
            # Find the payment account and create the pay system instance.
            pay_account: PaymentAccountModel = PaymentAccountModel.find_by_id(
                pending_account.account_id)
            if pay_account.payment_method in (PaymentMethod.CASH.value,
                                              PaymentMethod.CHEQUE.value):
                routing_slip.create_cfs_account(pending_account, pay_account)
            else:
                cls._create_cfs_account(pending_account, pay_account,
                                        auth_token)
Пример #14
0
def test_update_statement_daily_to_daily(session):
    """Assert that going from daily to daily creates a new record."""
    bcol_account = factory_premium_payment_account()
    bcol_account.save()

    payment = factory_payment()
    payment.save()
    i = factory_invoice(payment_account=bcol_account)
    i.save()
    factory_invoice_reference(i.id).save()
    factory_statement_settings(payment_account_id=bcol_account.id,
                               frequency=StatementFrequency.DAILY.value)

    # update to weekly
    payment_account = PaymentAccount.find_by_id(bcol_account.id)
    statement_settings = StatementSettingsService.update_statement_settings(payment_account.auth_account_id,
                                                                            StatementFrequency.DAILY.value)
    assert statement_settings is not None
    assert statement_settings.get('frequency') == StatementFrequency.DAILY.value
    assert statement_settings.get('to_date') is None

    # daily to daily - assert daily should start by tomorow
    assert statement_settings.get('from_date') == (datetime.today() + timedelta(days=1)).strftime('%Y-%m-%d')

    # daily to daily - assert current active one is stil daily ending today
    current_statement_settings = StatementSettingsModel.find_active_settings(payment_account.auth_account_id,
                                                                             datetime.today())
    assert current_statement_settings is not None
    assert current_statement_settings.frequency == StatementFrequency.DAILY.value
    assert current_statement_settings.to_date == datetime.today().date()
Пример #15
0
def test_create_ejv_payment_request(session, client, jwt, app):
    """Assert payment request works for EJV accounts."""
    token = jwt.create_jwt(get_claims(role=Role.SYSTEM.value), token_header)
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json'
    }
    # Create account first
    rv = client.post('/api/v1/accounts',
                     data=json.dumps(get_gov_account_payload(account_id=1234)),
                     headers=headers)
    auth_account_id = rv.json.get('authAccountId')

    payment_account: PaymentAccountModel = PaymentAccountModel.find_by_auth_account_id(
        auth_account_id)
    dist_code: DistributionCodeModel = DistributionCodeModel.find_by_active_for_account(
        payment_account.id)

    assert dist_code
    assert dist_code.account_id == payment_account.id

    token = jwt.create_jwt(get_claims(), token_header)
    headers = {
        'Authorization': f'Bearer {token}',
        'content-type': 'application/json',
        'Account-Id': auth_account_id
    }

    rv = client.post('/api/v1/payment-requests',
                     data=json.dumps(get_payment_request()),
                     headers=headers)
    assert rv.json.get('paymentMethod') == PaymentMethod.EJV.value
    assert rv.json.get('statusCode') == InvoiceStatus.APPROVED.value
Пример #16
0
    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()
Пример #17
0
    def create_payment_receipt(auth_account_id: str, credit_request: Dict[str,
                                                                          str],
                               **kwargs) -> Payment:
        """Create a payment record for the 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)
        # Create a payment record
        # Create a receipt in CFS for the  amount.
        payment = Payment.create(
            payment_method=credit_request.get('paymentMethod'),
            payment_system=PaymentSystem.PAYBC.value,
            payment_account_id=pay_account.id)
        receipt_number: str = generate_receipt_number(payment.id)
        receipt_date = credit_request.get('paymentDate')
        amount = credit_request.get('paidAmount')

        receipt_response = CFSService.create_cfs_receipt(
            cfs_account=cfs_account,
            rcpt_number=receipt_number,
            rcpt_date=receipt_date,
            amount=amount,
            payment_method=credit_request.get('paymentMethod'))

        payment.receipt_number = receipt_response.get('receipt_number',
                                                      receipt_number)
        payment.paid_amount = amount
        payment.created_by = kwargs['user'].user_name
        payment.payment_date = parser.parse(receipt_date)
        payment.payment_status_code = PaymentStatus.COMPLETED.value
        payment.save()

        return payment
Пример #18
0
def test_get_statement_report_for_empty_invoices(session):
    """Assert that the get statement report works for statement with no invoices."""
    bcol_account = factory_premium_payment_account()
    bcol_account.save()

    payment = factory_payment()
    payment.save()
    i = factory_invoice(payment_account=bcol_account)
    i.save()
    factory_invoice_reference(i.id).save()
    factory_payment_line_item(invoice_id=i.id, fee_schedule_id=1).save()

    settings_model = factory_statement_settings(
        payment_account_id=bcol_account.id,
        frequency=StatementFrequency.DAILY.value)
    statement_model = factory_statement(
        payment_account_id=bcol_account.id,
        frequency=StatementFrequency.DAILY.value,
        statement_settings_id=settings_model.id)

    payment_account = PaymentAccount.find_by_id(bcol_account.id)
    statements = StatementService.find_by_account_id(
        payment_account.auth_account_id, page=1, limit=10)
    assert statements is not None

    report_response, report_name = StatementService.get_statement_report(
        statement_id=statement_model.id,
        content_type='application/pdf',
        auth=get_auth_premium_user())
    assert report_response is not None
def test_update_pad_account(session):
    """Test update account."""
    # Create a pending account first, then call the job
    account = factory_create_pad_account(auth_account_id='2')
    CreateAccountTask.create_accounts()

    account = PaymentAccount.find_by_id(account.id)
    cfs_account = CfsAccount.find_effective_by_account_id(account.id)

    assert cfs_account.payment_instrument_number

    # Now update the account.
    new_payment_details = {
        'bankInstitutionNumber': '111',
        'bankTransitNumber': '222',
        'bankAccountNumber': '3333333333'
    }
    PadService().update_account(name='Test', cfs_account=cfs_account, payment_info=new_payment_details)
    cfs_account = CfsAccount.find_by_id(cfs_account.id)

    # Run the job again
    CreateAccountTask.create_accounts()

    updated_cfs_account: CfsAccount = CfsAccount.find_effective_by_account_id(account.id)
    assert updated_cfs_account.id != cfs_account.id
    assert updated_cfs_account.bank_account_number == new_payment_details.get('bankAccountNumber')
    assert updated_cfs_account.bank_branch_number == new_payment_details.get('bankTransitNumber')
    assert updated_cfs_account.bank_number == new_payment_details.get('bankInstitutionNumber')

    assert cfs_account.status == CfsAccountStatus.INACTIVE.value
    assert updated_cfs_account.status == CfsAccountStatus.PENDING_PAD_ACTIVATION.value
    assert updated_cfs_account.payment_instrument_number
Пример #20
0
def test_create_zero_dollar_payment_record(session, public_user_mock):
    """Assert that the payment records are created and completed."""
    payment_response = PaymentService.create_payment(
        get_zero_dollar_payment_request())
    account_model = PaymentAccount.find_by_corp_number_and_corp_type_and_system(
        'CP0001234', 'CP', 'INTERNAL')
    account_id = account_model.id
    assert account_id is not None
    assert payment_response.get('id') is not None
    assert payment_response.get('status_code') == 'COMPLETED'
    # Create another payment with same request, the account should be the same
    PaymentService.create_payment(get_zero_dollar_payment_request())
    account_model = PaymentAccount.find_by_corp_number_and_corp_type_and_system(
        'CP0001234', 'CP', 'INTERNAL')
    assert account_id == account_model.id
    assert payment_response.get('status_code') == 'COMPLETED'
Пример #21
0
def factory_payment_account(corp_number: str = 'CP1234',
                            corp_type_code='CP',
                            payment_system_code='PAYBC'):
    """Factory."""
    return PaymentAccount(corp_number=corp_number,
                          corp_type_code=corp_type_code,
                          payment_system_code=payment_system_code)
Пример #22
0
def factory_premium_payment_account(bcol_user_id='PB25020', bcol_account_id='1234567890', auth_account_id='1234'):
    """Return Factory."""
    account = PaymentAccount(auth_account_id=auth_account_id,
                             bcol_user_id=bcol_user_id,
                             bcol_account=bcol_account_id,
                             )
    return account
Пример #23
0
    def _apply_routing_slips_to_pending_invoices(cls, routing_slip: RoutingSlipModel) -> float:
        """Apply the routing slips again, when routing slip is linked to an NSF parent."""
        current_app.logger.info(f'Starting NSF recovery process for {routing_slip.number}')
        routing_slip_payment_account: PaymentAccountModel = PaymentAccountModel.find_by_id(
            routing_slip.payment_account_id)

        # apply invoice to the active CFS_ACCOUNT which will be the parent routing slip
        active_cfs_account = CfsAccountModel.find_effective_by_account_id(routing_slip_payment_account.id)

        invoices: List[InvoiceModel] = db.session.query(InvoiceModel) \
            .filter(InvoiceModel.routing_slip == routing_slip.number,
                    InvoiceModel.invoice_status_code.in_([InvoiceStatus.CREATED.value, InvoiceStatus.APPROVED.value])) \
            .all()
        current_app.logger.info(f'Found {len(invoices)} to apply receipt')
        applied_amount = 0
        for inv in invoices:
            inv_ref: InvoiceReferenceModel = InvoiceReferenceModel.find_reference_by_invoice_id_and_status(
                inv.id, InvoiceReferenceStatus.ACTIVE.value
            )
            cls.apply_routing_slips_to_invoice(
                routing_slip_payment_account, active_cfs_account, routing_slip, inv, inv_ref.invoice_number
            )

            # IF invoice balance is zero, then update records.
            if CFSService.get_invoice(cfs_account=active_cfs_account, inv_number=inv_ref.invoice_number) \
                    .get('amount_due') == 0:
                applied_amount += inv.total
                inv_ref.status_code = InvoiceReferenceStatus.COMPLETED.value
                inv.invoice_status_code = InvoiceStatus.PAID.value

        return applied_amount
Пример #24
0
def factory_payment_account(corp_number: str = 'CP0001234',
                            corp_type_code: str = 'CP',
                            payment_system_code: str = 'PAYBC',
                            account_number='4101',
                            bcol_user_id='test',
                            auth_account_id: str = '1234'):
    """Factory."""
    # Create a payment account
    account = PaymentAccount(auth_account_id=auth_account_id).save()

    if payment_system_code == PaymentSystem.BCOL.value:
        return BcolPaymentAccount(bcol_user_id=bcol_user_id,
                                  bcol_account_id='TEST',
                                  account_id=account.id)
    elif payment_system_code == PaymentSystem.PAYBC.value:
        return CreditPaymentAccount(corp_number=corp_number,
                                    corp_type_code=corp_type_code,
                                    paybc_party='11111',
                                    paybc_account=account_number,
                                    paybc_site='29921',
                                    account_id=account.id)
    elif payment_system_code == PaymentSystem.INTERNAL.value:
        return InternalPaymentAccount(corp_number=corp_number,
                                      corp_type_code=corp_type_code,
                                      account_id=account.id)
Пример #25
0
    def _notify_for_ob(cls):  # pylint: disable=too-many-locals
        """Notify for online banking.

        1) Find the accounts with pending invoices
        2) get total remaining for that account

        """
        unpaid_status = (InvoiceStatus.SETTLEMENT_SCHEDULED.value,
                         InvoiceStatus.PARTIAL.value,
                         InvoiceStatus.CREATED.value)
        notification_date = datetime.today() - timedelta(
            days=current_app.config.get('NOTIFY_AFTER_DAYS'))
        # Get distinct accounts with pending invoices for that exact day
        notification_pending_accounts = db.session.query(
            InvoiceModel.payment_account_id
        ).distinct().filter(
            and_(
                InvoiceModel.invoice_status_code.in_(unpaid_status),
                InvoiceModel.payment_method_code ==
                PaymentMethod.ONLINE_BANKING.value,
                # cast is used to get the exact match stripping the timestamp from date
                cast(InvoiceModel.created_on,
                     Date) == notification_date.date())).all()
        current_app.logger.debug(
            f'Found {len(notification_pending_accounts)} invoices to notify admins.'
        )
        for payment_account in notification_pending_accounts:
            try:
                payment_account_id = payment_account[0]
                total = db.session.query(
                    func.sum(InvoiceModel.total).label('total')
                ).filter(
                    and_(
                        InvoiceModel.invoice_status_code.in_(unpaid_status),
                        InvoiceModel.payment_account_id == payment_account_id,
                        InvoiceModel.payment_method_code ==
                        PaymentMethod.ONLINE_BANKING.value)).group_by(
                            InvoiceModel.payment_account_id).all()
                pay_account: PaymentAccountModel = \
                    PaymentAccountModel.find_by_id(payment_account_id)

                cfs_account = CfsAccountModel.find_effective_by_account_id(
                    payment_account_id)

                # emit account mailer event
                addition_params_to_mailer = {
                    'transactionAmount': total[0][0],
                    'cfsAccountId': cfs_account.cfs_account,
                    'authAccountId': pay_account.auth_account_id,
                }
                mailer.publish_mailer_events('ob.outstandingInvoice',
                                             pay_account,
                                             addition_params_to_mailer)
            except Exception as e:  # NOQA # pylint: disable=broad-except
                capture_message(
                    f'Error on notifying mailer  OB Pending invoice: account id={pay_account.id}, '
                    f'auth account : {pay_account.auth_account_id}, ERROR : {str(e)}',
                    level='error')
                current_app.logger.error(e)
Пример #26
0
def activate_pad_account(auth_account_id: str):
    """Activate the pad account."""
    payment_account: PaymentAccount = PaymentAccount.find_by_auth_account_id(auth_account_id)
    payment_account.pad_activation_date = datetime.now()
    payment_account.save()
    cfs_account: CfsAccount = CfsAccount.find_effective_by_account_id(payment_account.id)
    cfs_account.status = 'ACTIVE'
    cfs_account.save()
Пример #27
0
def factory_create_wire_account(auth_account_id='1234',
                                status=CfsAccountStatus.PENDING.value):
    """Return Factory."""
    account = PaymentAccount(auth_account_id=auth_account_id,
                             payment_method=PaymentMethod.WIRE.value,
                             name=f'Test {auth_account_id}').save()
    CfsAccount(status=status, account_id=account.id).save()
    return account
Пример #28
0
    def _cancel_rs_invoices(cls):
        """Cancel routing slip invoices in CFS."""
        invoices: List[InvoiceModel] = InvoiceModel.query \
            .filter(InvoiceModel.payment_method_code == PaymentMethod.INTERNAL.value) \
            .filter(InvoiceModel.invoice_status_code == InvoiceStatus.REFUND_REQUESTED.value) \
            .filter(InvoiceModel.routing_slip is not None) \
            .order_by(InvoiceModel.created_on.asc()).all()

        current_app.logger.info(
            f'Found {len(invoices)} to be cancelled in CFS.')
        for invoice in invoices:
            # call unapply rcpts
            # adjust invoice to zero
            current_app.logger.debug(f'Calling the invoice {invoice.id}')
            routing_slip = RoutingSlipModel.find_by_number(
                invoice.routing_slip)
            routing_slip_payment_account: PaymentAccountModel = PaymentAccountModel.find_by_id(
                routing_slip.payment_account_id)
            cfs_account: CfsAccountModel = CfsAccountModel.find_effective_by_account_id(
                routing_slip_payment_account.id)
            # Find COMPLETED invoice reference; as unapply has to be done only if invoice is created and applied in CFS.
            invoice_reference = InvoiceReferenceModel. \
                find_reference_by_invoice_id_and_status(invoice.id, status_code=InvoiceReferenceStatus.COMPLETED.value)
            if invoice_reference:
                current_app.logger.debug(
                    f'Found invoice reference - {invoice_reference.invoice_number}'
                )
                try:
                    # find receipts against the invoice and unapply
                    # apply receipt now
                    receipts: List[
                        ReceiptModel] = ReceiptModel.find_all_receipts_for_invoice(
                            invoice_id=invoice.id)
                    for receipt in receipts:
                        CFSService.unapply_receipt(
                            cfs_account, receipt.receipt_number,
                            invoice_reference.invoice_number)

                    adjustment_negative_amount = -invoice.total
                    CFSService.adjust_invoice(
                        cfs_account=cfs_account,
                        inv_number=invoice_reference.invoice_number,
                        amount=adjustment_negative_amount)

                except Exception as e:  # NOQA # pylint: disable=broad-except
                    capture_message(
                        f'Error on canelling Routing Slip invoice: invoice id={invoice.id}, '
                        f'routing slip : {routing_slip.id}, ERROR : {str(e)}',
                        level='error')
                    current_app.logger.error(e)
                    # TODO stop execution ? what should be the invoice stats ; should we set it to error or retry?
                    continue

                invoice_reference.status_code = InvoiceReferenceStatus.CANCELLED.value

            invoice.invoice_status_code = InvoiceStatus.REFUNDED.value
            invoice.save()
Пример #29
0
    def _save_account(cls,
                      account_request: Dict[str, any],
                      payment_account: PaymentAccountModel,
                      is_sandbox: bool = False):
        """Update and save payment account and CFS account model."""
        # pylint:disable=cyclic-import, import-outside-toplevel
        from pay_api.factory.payment_system_factory import PaymentSystemFactory

        payment_account.auth_account_id = account_request.get('accountId')

        # If the payment method is CC, set the payment_method as DIRECT_PAY
        if payment_method := get_str_by_path(account_request,
                                             'paymentInfo/methodOfPayment'):
            payment_account.payment_method = payment_method
            payment_account.bcol_account = account_request.get(
                'bcolAccountNumber', None)
            payment_account.bcol_user_id = account_request.get(
                'bcolUserId', None)
Пример #30
0
    def find_by_id(cls, account_id: int):
        """Find pay account by id."""
        current_app.logger.debug('<find_by_id')

        account = PaymentAccount()
        account._dao = PaymentAccountModel.find_by_id(account_id)  # pylint: disable=protected-access

        current_app.logger.debug('>find_by_id')
        return account